Content card design improvements (#19737)

refs. https://linear.app/tryghost/issue/DES-122/bookmark-card-issues

This PR addresses the following content card related problems:

1. The design of the following cards are more self-contained so it makes
more sense to use `px` for their font-sizes and spacings so it looks the
same regardless of the theme. Of course themes still can override these
values.

Updated cards to use `px` for font sizing:
- audio
- bookmark
- file
- product

2. So far header and signup cards had been using `rem` for font-sizes
and some sizing. This commit updates these to use `em` instead so that
it's consistent with all other cards.

3. The favicon sometimes is not available for bookmark cards. This PR also
fixes that by providing a default favicon for these cases.
This commit is contained in:
Peter Zimon 2024-02-29 17:09:34 +01:00 committed by GitHub
parent c7e475feb0
commit 8f3617aaa8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 113 additions and 68 deletions

View File

@ -7,7 +7,8 @@
display: flex;
width: 100%;
min-height: 96px;
border-radius: 3px;
border-radius: 6px;
padding: 4px;
box-shadow: inset 0 0 0 1px rgba(124, 139, 154, 0.25);
}
@ -25,7 +26,7 @@
background: transparent;
object-fit: cover;
aspect-ratio: 1/1;
border-radius: 2px;
border-radius: 3px;
}
.kg-audio-thumbnail.placeholder {
@ -55,8 +56,8 @@
padding: 8px 12px;
border: none;
font-family: inherit;
font-size: 1.15em;
font-weight: 700;
font-size: 16px;
font-weight: 600;
line-height: 1.15em;
background: transparent;
}
@ -72,9 +73,9 @@
min-width: 38px;
padding: 0 4px;
font-family: inherit;
font-size: .85em;
font-size: 12.5px;
font-weight: 500;
line-height: 1.4em;
line-height: 1em;
white-space: nowrap;
}
@ -82,9 +83,9 @@
width: 56px;
color: #ababab;
font-family: inherit;
font-size: .85em;
font-size: 12.5px;
font-weight: 500;
line-height: 1.4em;
line-height: 1em;
white-space: nowrap;
}
@ -127,9 +128,9 @@
min-width: 37px;
padding: 0 4px;
font-family: inherit;
font-size: .85em;
font-size: 12.5px;
font-weight: 600;
line-height: 1.4em;
line-height: 1em;
text-align: left;
background: transparent;
white-space: nowrap;

View File

@ -13,7 +13,7 @@
.kg-bookmark-card a.kg-bookmark-container:hover {
display: flex;
text-decoration: none;
border-radius: 3px;
border-radius: 6px;
border: 1px solid rgb(124 139 154 / 25%);
overflow: hidden;
color: inherit;
@ -31,14 +31,14 @@
}
.kg-bookmark-title {
font-size: 1.5rem;
font-size: 15px;
line-height: 1.4em;
font-weight: 600;
}
.kg-bookmark-description {
display: -webkit-box;
font-size: 1.4rem;
font-size: 14px;
line-height: 1.5em;
margin-top: 3px;
font-weight: 400;
@ -54,7 +54,7 @@
align-items: center;
margin-top: 22px;
width: 100%;
font-size: 1.4rem;
font-size: 14px;
font-weight: 500;
white-space: nowrap;
}

View File

@ -12,10 +12,10 @@
align-items: stretch;
justify-content: space-between;
color: inherit;
padding: 6px;
padding: 12px;
min-height: 92px;
border: 1px solid rgb(124 139 154 / 25%);
border-radius: 3px;
border-radius: 5px;
transition: all ease-in-out 0.35s;
text-decoration: none;
width: 100%;
@ -34,26 +34,27 @@
}
.kg-file-card-title {
font-size: 1.15em;
font-weight: 700;
font-size: 16px;
font-weight: 600;
line-height: 1.3em;
}
.kg-file-card-caption {
font-size: 0.95em;
font-size: 14px;
line-height: 1.3em;
opacity: 0.6;
opacity: 0.7;
}
.kg-file-card-title + .kg-file-card-caption {
margin-top: -3px;
flex-grow: 1;
margin-top: 3px;
}
.kg-file-card-metadata {
display: inline;
font-size: 0.825em;
font-size: 14px;
line-height: 1.3em;
margin-top: 2px;
margin-top: 5px;
}
.kg-file-card-filename {
@ -63,14 +64,15 @@
.kg-file-card-filesize {
display: inline-block;
font-size: 0.925em;
font-size: 14px;
opacity: 0.6;
}
.kg-file-card-filesize:before {
display: inline-block;
content: "\2022";
margin-right: 4px;
margin-left: 6px;
margin-right: 6px;
}
.kg-file-card-icon {
@ -81,6 +83,7 @@
width: 80px;
min-width: 80px;
height: 100%;
min-height: 80px;
}
.kg-file-card-icon:before {
@ -94,7 +97,7 @@
background: currentColor;
opacity: 0.06;
transition: opacity ease-in-out 0.35s;
border-radius: 2px;
border-radius: 3px;
}
.kg-file-card a.kg-file-card-container:hover .kg-file-card-icon:before {
@ -123,7 +126,7 @@
}
.kg-file-card-small .kg-file-card-metadata {
font-size: 1.0em;
font-size: 14px;
margin-top: 0;
}

View File

@ -104,7 +104,7 @@
.kg-content-wide .kg-header-card-content .kg-header-card-image {
height: 100%;
padding: 8rem 0;
padding: 5.6em 0;
object-fit: contain;
}
@ -112,22 +112,22 @@
.kg-header-card h2.kg-header-card-heading {
margin: 0;
font-size: clamp(2.4rem, 4vw, 3.6rem);
font-size: clamp(1.7em, 4vw, 2.5em);
font-weight: 700;
line-height: 1em;
line-height: 1.05em;
letter-spacing: -0.01em;
}
.kg-header-card.kg-width-wide h2.kg-header-card-heading {
font-size: clamp(2.4rem, 5vw, 4.8rem);
font-size: clamp(1.7em, 5vw, 3.3em);
}
.kg-header-card.kg-width-full h2.kg-header-card-heading {
font-size: clamp(2.8rem, 5.6vw, 6rem);
font-size: clamp(1.9em, 5.6vw, 4.2em);
}
.kg-header-card.kg-width-full.kg-layout-split h2.kg-header-card-heading {
font-size: clamp(2.8rem, 4vw, 4.8rem);
font-size: clamp(1.9em, 4vw, 3.3em);
}
/* Subheading */
@ -139,7 +139,7 @@
.kg-header-card .kg-header-card-subheading {
max-width: 40em;
margin: 0;
font-size: clamp(1.05em, 2vw, 2rem);
font-size: clamp(1.05em, 2vw, 1.4em);
font-weight: 500;
line-height: 1.2em;
}
@ -153,23 +153,24 @@
}
.kg-header-card.kg-width-wide .kg-header-card-subheading {
font-size: clamp(1.05em, 2vw, 2.2rem);
font-size: clamp(1.05em, 2vw, 1.55em);
}
.kg-header-card.kg-width-full .kg-header-card-subheading:not(.kg-layout-split .kg-header-card-subheading) {
max-width: min(65vmax, 1200px);
font-size: clamp(1.05em, 2vw, 2.4rem);
font-size: clamp(1.05em, 2vw, 1.7em);
}
.kg-header-card.kg-width-full.kg-layout-split .kg-header-card-subheading {
font-size: clamp(1.05em, 2vw, 2.2rem);
font-size: clamp(1.05em, 2vw, 1.55em);
}
.kg-header-card.kg-v2 .kg-header-card-button {
display: flex;
position: relative;
align-items: center;
height: 4.6rem;
height: 2.9em;
min-height: 46px;
padding: 0 1.2em;
outline: none;
border: none;
@ -243,15 +244,15 @@
}
.kg-content-wide .kg-header-card-content .kg-header-card-image {
padding: 2.4rem 0 0;
padding: 1.7em 0 0;
}
.kg-content-wide.kg-swapped .kg-header-card-content .kg-header-card-image {
padding: 0 0 2.4rem;
padding: 0 0 1.7em;
}
.kg-header-card.kg-v2 .kg-header-card-button {
height: 4.2rem;
height: 2.9em;
}
.kg-header-card.kg-v2.kg-width-wide .kg-header-card-button,

View File

@ -36,8 +36,8 @@
.kg-product-card h4.kg-product-card-title {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
text-decoration: none;
font-weight: 700;
font-size: 1.4em;
font-weight: 600;
font-size: 21px;
margin-top: 0;
margin-bottom: 0;
line-height: 1.15em;
@ -51,7 +51,7 @@
.kg-product-card .kg-product-card-description ol,
.kg-product-card .kg-product-card-description ul {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
font-size: 0.95em;
font-size: 14px;
line-height: 1.5em;
opacity: .7;
margin-bottom: 0;
@ -94,7 +94,7 @@
}
.kg-product-card-rating-star {
height: 28px;
height: 20px;
width: 20px;
}
@ -116,14 +116,14 @@
position: static;
align-items: center;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
font-size: 0.95em;
font-size: 14px;
font-weight: 600;
line-height: 1em;
text-decoration: none;
width: 100%;
height: 2.4em;
border-radius: 5px;
padding: 0 1.2em;
height: 38px;
border-radius: 6px;
padding: 0 12px;
transition: opacity 0.2s ease-in-out;
}

View File

@ -97,7 +97,7 @@
.kg-content-wide .kg-signup-card-content .kg-signup-card-image {
height: 100%;
padding: 8rem 0;
padding: 5.6em 0;
object-fit: contain;
}
@ -105,22 +105,22 @@
.kg-signup-card h2.kg-signup-card-heading {
margin: 0;
font-size: clamp(2.4rem, 4vw, 3.6rem);
font-size: clamp(1.7em, 4vw, 2.5em);
font-weight: 700;
line-height: 1em;
line-height: 1.05em;
letter-spacing: -0.01em;
}
.kg-signup-card.kg-width-wide h2.kg-signup-card-heading {
font-size: clamp(2.4rem, 5vw, 4.8rem);
font-size: clamp(1.7em, 5vw, 3.3em);
}
.kg-signup-card.kg-width-full h2.kg-signup-card-heading {
font-size: clamp(2.8rem, 5.6vw, 6rem);
font-size: clamp(1.9em, 5.6vw, 4.2em);
}
.kg-signup-card.kg-width-full.kg-layout-split h2.kg-signup-card-heading {
font-size: clamp(2.8rem, 4vw, 4.8rem);
font-size: clamp(1.9em, 4vw, 3.3em);
}
/* Subheading */
@ -132,7 +132,7 @@
.kg-signup-card .kg-signup-card-subheading {
max-width: 40em;
margin: 0;
font-size: clamp(1.05em, 2vw, 2rem);
font-size: clamp(1.05em, 2vw, 1.4em);
font-weight: 500;
line-height: 1.2em;
}
@ -146,16 +146,16 @@
}
.kg-signup-card.kg-width-wide .kg-signup-card-subheading {
font-size: clamp(1.05em, 2vw, 2.2rem);
font-size: clamp(1.05em, 2vw, 1.55em);
}
.kg-signup-card.kg-width-full .kg-signup-card-subheading:not(.kg-layout-split .kg-signup-card-subheading) {
max-width: min(65vmax, 1200px);
font-size: clamp(1.05em, 2vw, 2.4rem);
font-size: clamp(1.05em, 2vw, 1.7em);
}
.kg-signup-card.kg-width-full.kg-layout-split .kg-signup-card-subheading {
font-size: clamp(1.05em, 2vw, 2.2rem);
font-size: clamp(1.05em, 2vw, 1.55em);
}
/* Subscribe form */
@ -203,7 +203,8 @@
.kg-signup-card-input {
width: 100%;
height: 4.6rem;
height: 2.9em;
min-height: 46px;
margin: 0 3px 0 0;
padding: 12px 16px;
border: none;
@ -220,7 +221,8 @@
display: flex;
position: relative;
align-items: center;
height: 4.6rem;
height: 2.9em;
min-height: 46px;
padding: 0 1.2em;
outline: none;
border: none;
@ -355,21 +357,21 @@
}
.kg-content-wide .kg-signup-card-content .kg-signup-card-image {
padding: 2.4rem 0 0;
padding: 1.7em 0 0;
}
.kg-content-wide.kg-swapped .kg-signup-card-content .kg-signup-card-image {
padding: 0 0 2.4rem;
padding: 0 0 1.7em;
}
.kg-signup-card-input {
height: 4.2rem;
height: 2.9em;
padding: 6px 12px;
font-size: 1em;
}
.kg-signup-card-button {
height: 4.2rem;
height: 2.9em;
}
.kg-signup-card.kg-width-wide .kg-signup-card-button,

View File

@ -82,7 +82,7 @@
padding: 0 4px;
color: #fff;
font-family: inherit;
font-size: .85em;
font-size: 12.5px;
font-weight: 500;
line-height: 1.4em;
white-space: nowrap;
@ -91,7 +91,7 @@
.kg-video-time {
color: rgba(255, 255, 255, 0.6);
font-family: inherit;
font-size: .85em;
font-size: 12.5px;
font-weight: 500;
line-height: 1.4em;
white-space: nowrap;
@ -142,7 +142,7 @@
padding: 0 4px;
color: #fff;
font-family: inherit;
font-size: .85em;
font-size: 12.5px;
font-weight: 600;
line-height: 1.4em;
text-align: left;

View File

@ -221,6 +221,35 @@ describe('Oembed API', function () {
should.exist(res.body.errors);
});
it('should replace icon URL when it returns 404', async function () {
// Mock the page so it contains a readable icon URL
const pageMock = nock('http://example.com')
.get('/page-with-icon')
.reply(
200,
'<html><head><title>TESTING</title><link rel="icon" href="http://example.com/icon.svg"></head><body></body></html>',
{'content-type': 'text/html'}
);
// Mock the icon URL to return 404
nock('http://example.com/')
.head('/icon.svg')
.reply(404);
const url = encodeURIComponent(' http://example.com/page-with-icon\t '); // Whitespaces are to make sure urls are trimmed
const res = await request.get(localUtils.API.getApiQuery(`oembed/?url=${url}&type=bookmark`))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200);
// Check that the icon URL mock was loaded
pageMock.isDone().should.be.true();
// Check that the substitute icon URL is returned in place of the original
res.body.metadata.icon.should.eql('https://static.ghost.org/v5.0.0/images/link-icon.svg');
});
});
describe('with unknown provider', function () {

View File

@ -259,6 +259,15 @@ class OEmbedService {
});
}
if (metadata.icon) {
try {
await this.externalRequest.head(metadata.icon);
} catch (err) {
metadata.icon = 'https://static.ghost.org/v5.0.0/images/link-icon.svg';
logging.error(err);
}
}
return {
version: '1.0',
type: 'bookmark',