From cb4e94f025e01ed741c08dcaf0ece429f5730349 Mon Sep 17 00:00:00 2001 From: Ned Zimmerman Date: Thu, 30 Jan 2020 14:16:24 -0700 Subject: [PATCH] feat: improve card semantics (resolves #190) (#209) * feat: improve resource card semantics [WIP] * fix: pagination indicator regression * feat: overhaul resource card semantics * feat: apply new card layout to resource list * fix: adjust spacing below locality * feat: improve semantics of other card variants * fix: align filled favorite icon with unfilled favorite icon * fix: address SVG padding issue in buttons * fix: include overflow text in topic list * feat: add screen reader labels to metadata * feat: add separator component, use period instead of middot * fix: adjust separator spacing for NVDA --- src/assets/images/favorite-filled.svg | 2 +- src/assets/styles/common/_todo.scss | 5 + src/assets/styles/components/_buttons.scss | 4 +- src/assets/styles/components/_card.scss | 93 ++++++++++--------- src/assets/styles/components/_menu.scss | 4 +- .../01-atoms/_separator/separator.njk | 1 + .../02-molecules/01-card/card--resource.njk | 58 ++++++++++++ .../02-molecules/01-card/card.config.js | 5 +- src/components/02-molecules/01-card/card.njk | 85 +++++++---------- .../03-layouts/02-archive/archive.config.js | 3 +- 10 files changed, 160 insertions(+), 100 deletions(-) create mode 100644 src/components/01-atoms/_separator/separator.njk create mode 100644 src/components/02-molecules/01-card/card--resource.njk diff --git a/src/assets/images/favorite-filled.svg b/src/assets/images/favorite-filled.svg index 53de3caa..8d60a969 100644 --- a/src/assets/images/favorite-filled.svg +++ b/src/assets/images/favorite-filled.svg @@ -1 +1 @@ - + diff --git a/src/assets/styles/common/_todo.scss b/src/assets/styles/common/_todo.scss index bbc67b86..cd4b7942 100644 --- a/src/assets/styles/common/_todo.scss +++ b/src/assets/styles/common/_todo.scss @@ -11,3 +11,8 @@ input[type="file"] > input[type="button"]::-moz-focus-inner { .spacer { height: rem(24); } + +.separator { + padding-left: 0.325em; + vertical-align: super; +} diff --git a/src/assets/styles/components/_buttons.scss b/src/assets/styles/components/_buttons.scss index 76e4ee7b..797a39fc 100644 --- a/src/assets/styles/components/_buttons.scss +++ b/src/assets/styles/components/_buttons.scss @@ -173,11 +173,11 @@ padding: 0 rem(8); svg + * { - margin-right: 0.25em; + margin-left: 0.25em; } svg + .screen-reader-text { - margin-right: 0.25em; + margin-right: 0; } * + svg { diff --git a/src/assets/styles/components/_card.scss b/src/assets/styles/components/_card.scss index c9cce81d..12d53049 100644 --- a/src/assets/styles/components/_card.scss +++ b/src/assets/styles/components/_card.scss @@ -11,6 +11,7 @@ background-color: $white; border-top: rem(3) solid $blue-500; box-shadow: 0 0 rem(5) rgba(0, 0, 0, 0.16); + height: 100%; padding: rem(22); position: relative; transition: box-shadow 0.1s; @@ -30,11 +31,9 @@ box-shadow: 0 0 rem(25) transparentize($blue-500, 0.75); padding: rem(22) rem(19) rem(19); } - - @include card($blue-500, $white, true); } -.card + .card { +.cards .card__wrapper + .card__wrapper { margin-top: rem(30); } @@ -63,36 +62,18 @@ margin-top: rem(22); } -.card__format { - background: $blue-500; - color: $white; - font-family: $font-family-sans; - font-size: rem(14); - font-weight: $font-weight-semibold; - padding: rem(2) rem(6); - - svg { - color: $red-400; - margin-right: rem(4); - width: 1.25em; - } -} - -.card__sep, -.card__language { - font-family: $font-family-sans; - font-size: rem(14); -} - .card header { position: relative; } .card__title { + align-items: flex-start; + display: flex; + flex-direction: column; font-size: rem(20); font-weight: $font-weight-bold; line-height: (30 / 20); - margin-top: rem(12); + margin-top: 0; a { color: $black; @@ -120,46 +101,74 @@ } } -.card__date, +.card header + * { + margin-top: rem(9); +} + .card__byline, -.card__locality, +.card__meta, .card__description, -.card__tags { +.card__favorite { color: $grey-600; font-size: rem(14); - margin-top: rem(2); + margin-top: rem(9); } -.card__date, -.card__locality { +.card__byline, +.card__meta { svg { height: 1.125em; - margin-bottom: rem(-2); - margin-right: 0; } } +.card__meta { + padding-left: 1.5em; + text-indent: -1.5em; +} + +.card__format { + background: $blue-500; + color: $white; + display: inline-block; + font-family: $font-family-sans; + font-size: rem(14); + font-weight: $font-weight-semibold; + margin-bottom: rem(12); + padding: rem(2) rem(6); +} + .card__tags { - margin-top: rem(2); + margin-top: rem(6); .badges { display: inline-flex; } - p { - display: inline; - margin-left: rem(8); + .overflow { + color: $grey-600; + font-size: rem(14); + margin-left: rem(4); } } -.card header + * { - margin-top: rem(6); +.card__favorite { + color: $black; + font-weight: $font-weight-bold; + text-align: right; + + svg { + color: $red-500; + } } .card--resource { @include card($red-400, $black, false); .card__format { + color: inherit; + display: inline; + font-family: inherit; + font-weight: inherit; padding: 0; } } @@ -201,7 +210,7 @@ } } - .card { + .cards .card__wrapper { margin-bottom: rem(30); width: calc(50% - #{rem(30)} / 2); @@ -219,7 +228,7 @@ } } - .card + .card { + .cards .card__wrapper + .card__wrapper { margin-top: 0; } } @@ -247,7 +256,7 @@ } } - .card { + .cards .card__wrapper { margin-bottom: rem(30); margin-left: rem(30); width: calc((100% - (#{rem(30)} * 2)) / 3); diff --git a/src/assets/styles/components/_menu.scss b/src/assets/styles/components/_menu.scss index 25761bcf..550011c8 100644 --- a/src/assets/styles/components/_menu.scss +++ b/src/assets/styles/components/_menu.scss @@ -1,4 +1,4 @@ -nav { +[role="banner"] nav { align-items: center; display: flex; flex-direction: row; @@ -202,7 +202,7 @@ nav { } @include breakpoint-up(md) { - nav { + [role="banner"] nav { height: rem(80); margin-left: auto; } diff --git a/src/components/01-atoms/_separator/separator.njk b/src/components/01-atoms/_separator/separator.njk new file mode 100644 index 00000000..1d0df295 --- /dev/null +++ b/src/components/01-atoms/_separator/separator.njk @@ -0,0 +1 @@ +. diff --git a/src/components/02-molecules/01-card/card--resource.njk b/src/components/02-molecules/01-card/card--resource.njk new file mode 100644 index 00000000..8eeef543 --- /dev/null +++ b/src/components/02-molecules/01-card/card--resource.njk @@ -0,0 +1,58 @@ +{% if not standAlone %} + + {% endif %} diff --git a/src/components/02-molecules/01-card/card.config.js b/src/components/02-molecules/01-card/card.config.js index 06d5fb92..d0373df5 100644 --- a/src/components/02-molecules/01-card/card.config.js +++ b/src/components/02-molecules/01-card/card.config.js @@ -18,11 +18,14 @@ module.exports = { formatIcon: 'article', name: 'Resource', title: 'Data as a common in the sharing economy', - byline: 'Centre d’économie Paris Nord', + byline: 'Carballa Smichowski Bruno', + publisher: 'Centre d’économie Paris Nord', locality: 'France', + date: 2016, topics: ['Commons', 'Policy'], topicCount: 4, href: 'resource', + favorite: true, language: 'English' } }, diff --git a/src/components/02-molecules/01-card/card.njk b/src/components/02-molecules/01-card/card.njk index 4d861f38..19eeba7a 100644 --- a/src/components/02-molecules/01-card/card.njk +++ b/src/components/02-molecules/01-card/card.njk @@ -1,61 +1,44 @@ {% if not standAlone %} - {% endif %} + {% endif %} + {% if locality %} +
+ location: {% render '@svg', {svg:'location'}, true %}{{ locality }} +
+ {% endif %} + {% if description %} +
{{ description }}
+ {% endif %} + + + +{% if not standAlone %} + +{% endif %} diff --git a/src/components/03-layouts/02-archive/archive.config.js b/src/components/03-layouts/02-archive/archive.config.js index 38292899..ae1a1a57 100644 --- a/src/components/03-layouts/02-archive/archive.config.js +++ b/src/components/03-layouts/02-archive/archive.config.js @@ -64,7 +64,8 @@ for ( let i = 0; i < resourceCount; i++ ) { formatIcon: thisFormat.svg, name: 'Resource', title: title( faker.lorem.words( faker.random.number( { min: 4, max: 12 } ) ) ), - byline: title( faker.lorem.words( faker.random.number( { min: 2, max: 4 } ) ) ), + byline: ( faker.random.boolean ) ? `${faker.name.firstName()} ${faker.name.lastName()}` : false, + publisher: faker.company.companyName(), locality: faker.address.country(), topics: [title( faker.company.catchPhraseNoun() ), title( faker.company.catchPhraseNoun() )], topicCount: faker.random.number( { min: 3, max: 7 } ),