Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat(web): Introduce Card component #DS-1397 #1751

Open
wants to merge 18 commits into
base: integration/card
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
435010f
Feat(web): Introduce `Card` component #DS-1397
adamkudrna Nov 12, 2024
9b718ff
fixup! Feat(web): Introduce `Card` component #DS-1397
adamkudrna Nov 14, 2024
dcedd05
fixup! fixup! Feat(web): Introduce `Card` component #DS-1397
adamkudrna Nov 14, 2024
19f42d2
fixup! fixup! fixup! Feat(web): Introduce `Card` component #DS-1397
adamkudrna Nov 14, 2024
028a33d
fixup! fixup! fixup! fixup! Feat(web): Introduce `Card` component #DS…
adamkudrna Nov 19, 2024
f263ffd
fixup! fixup! fixup! fixup! fixup! Feat(web): Introduce `Card` compon…
adamkudrna Nov 21, 2024
2e48110
fixup! fixup! fixup! fixup! fixup! fixup! Feat(web): Introduce `Card`…
adamkudrna Nov 23, 2024
d7d87ae
Fix(web): Prevent SVG inside `PartnerLogo` from overflowing #DS-1560
adamkudrna Nov 23, 2024
1144e46
fixup! fixup! fixup! fixup! fixup! fixup! fixup! Feat(web): Introduce…
adamkudrna Nov 23, 2024
fd87691
fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! Feat(web): In…
adamkudrna Nov 23, 2024
49d7151
fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! Feat(w…
adamkudrna Nov 25, 2024
d78c286
fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup!…
adamkudrna Nov 25, 2024
b7c8eec
fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup!…
adamkudrna Nov 25, 2024
5a68dcc
fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup!…
adamkudrna Nov 25, 2024
7afadb0
fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup!…
adamkudrna Nov 28, 2024
e2f81e0
fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup!…
adamkudrna Nov 28, 2024
a4aca39
fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup!…
adamkudrna Dec 3, 2024
0bd69d6
fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup!…
adamkudrna Dec 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
432 changes: 432 additions & 0 deletions packages/web/src/scss/components/Card/README.md

Large diffs are not rendered by default.

152 changes: 152 additions & 0 deletions packages/web/src/scss/components/Card/_Card.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
// 1. Get ready for card link overlay.
// 2. If there is a expanded CardMedia in a boxed vertical card, replace card padding with empty grid columns/rows.
// 3. Allow shrinking in grid layouts.
// 4. Make sure links and buttons are clickable.
// 5. Make text content selectable when there is a stretched CardLink.

@use '@tokens' as tokens;
@use '../../tools/breakpoint';
@use '../../tools/typography';
@use 'theme';
adamkudrna marked this conversation as resolved.
Show resolved Hide resolved

.Card {
adamkudrna marked this conversation as resolved.
Show resolved Hide resolved
--#{tokens.$css-variable-prefix}card-padding: #{theme.$padding};

@include typography.generate(theme.$typography);

position: relative; // 1.
display: grid;
min-width: 0; // 3.
color: theme.$color;

@include breakpoint.up(tokens.$breakpoint-tablet) {
--#{tokens.$css-variable-prefix}card-padding: #{theme.$padding-tablet};
}
}

// 4., 5.
.Card:has(.CardLink) :where(a:not(.CardLink), button),
.Card:has(.CardLink):has(.CardBody--selectable) :where(p, ul, ol, dl) {
position: relative;
z-index: 1;
}

.Card--vertical {
grid-template-rows: auto 1fr auto;
grid-template-areas:
'media'
'body'
'footer';
}

.Card--horizontal {
grid-template-columns: auto 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
'media logo'
'media body'
'media footer';
}

.Card--horizontalReversed {
grid-template-columns: 1fr auto;
grid-template-rows: auto 1fr auto;
grid-template-areas:
'logo media'
'body media'
'footer media';
}

:is(.Card--horizontal, .Card--horizontalReversed):has(.CardArtwork:not(:only-child), .CardMedia:not(:only-child)) {
column-gap: theme.$gap;
}

.Card--boxed {
border: theme.$border-width theme.$border-style theme.$border-color;
border-radius: theme.$border-radius;
background-color: theme.$background-color;

&:has(.CardLink) {
@media (hover: hover) {
transition: box-shadow theme.$transition-duration theme.$transition-timing;

&:hover {
box-shadow: theme.$box-shadow-state-hover;
}
}
}

&:not(:has(.CardMedia--expanded)) {
padding: var(--#{tokens.$css-variable-prefix}card-padding);
}
}

.Card--boxed.Card--vertical {
&:has(.CardMedia--expanded) {
adamkudrna marked this conversation as resolved.
Show resolved Hide resolved
grid-template-columns:
var(--#{tokens.$css-variable-prefix}card-padding)
1fr
var(--#{tokens.$css-variable-prefix}card-padding); // 2.

grid-template-rows:
var(--#{tokens.$css-variable-prefix}card-padding)
auto
1fr
auto;
grid-template-areas:
'media media media'
'media media media'
'. body .'
'. footer .';
}

&:has(.CardMedia:not(:only-child)) {
padding-bottom: var(--#{tokens.$css-variable-prefix}card-padding);
}
}

.Card--boxed.Card--horizontal {
&:has(.CardMedia--expanded) {
adamkudrna marked this conversation as resolved.
Show resolved Hide resolved
grid-template-columns: auto 1fr;
grid-template-rows:
var(--#{tokens.$css-variable-prefix}card-padding)
auto
1fr
auto
var(--#{tokens.$css-variable-prefix}card-padding); // 2.

grid-template-areas:
'media .'
'media logo'
'media body'
'media footer'
'media .';
}

&:has(.CardMedia:not(:only-child)) {
padding-right: var(--#{tokens.$css-variable-prefix}card-padding);
}
}

.Card--boxed.Card--horizontalReversed {
&:has(.CardMedia--expanded) {
adamkudrna marked this conversation as resolved.
Show resolved Hide resolved
grid-template-columns: 1fr auto;
grid-template-rows:
var(--#{tokens.$css-variable-prefix}card-padding)
auto
1fr
auto
var(--#{tokens.$css-variable-prefix}card-padding); // 2.

grid-template-areas:
'. media'
'logo media'
'body media'
'footer media'
'. media';
}

&:has(.CardMedia:not(:only-child)) {
padding-left: var(--#{tokens.$css-variable-prefix}card-padding);
}
}
17 changes: 17 additions & 0 deletions packages/web/src/scss/components/Card/_CardArtwork.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
@use '../../tools/dictionaries';
@use 'theme';

.CardArtwork {
display: grid;
grid-area: media;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as this is shared with the actual Media subcomponent, it would be better to use something more generic? grid-area: illustration? or something

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unable to come up with anything good. Maybe you will? Illustration doesn't work I think, it's weird to place e.g. a video into the "illustration" region.

}

@include dictionaries.generate-alignments(
$class-name: 'CardArtwork',
$dictionary-values: theme.$artwork-alignment-dictionary,
$axis: 'x'
);

.Card--vertical > .CardArtwork:not(:last-child) {
margin-bottom: theme.$gap;
}
9 changes: 9 additions & 0 deletions packages/web/src/scss/components/Card/_CardBody.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@use 'theme';

.CardBody {
grid-area: body;

&:not(:last-child) {
margin-bottom: theme.$gap;
}
}
9 changes: 9 additions & 0 deletions packages/web/src/scss/components/Card/_CardEyebrow.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@use '../../tools/typography';
@use 'theme';

.CardEyebrow {
@include typography.generate(theme.$eyebrow-typography);

margin-bottom: theme.$eyebrow-margin-bottom;
adamkudrna marked this conversation as resolved.
Show resolved Hide resolved
color: theme.$eyebrow-color;
}
29 changes: 29 additions & 0 deletions packages/web/src/scss/components/Card/_CardFooter.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// 1. Restore interactions for individual actions.

@use '../../tools/dictionaries';
@use 'theme';

.CardFooter {
z-index: 1;
display: flex;
flex-direction: row;
flex-wrap: wrap;
grid-area: footer;
gap: theme.$footer-gap;
pointer-events: none;

&:not(:last-child) {
margin-bottom: theme.$gap;
}
}

// 1.
.CardFooter :where(a:not(.CardLink), button) {
pointer-events: auto;
}

@include dictionaries.generate-alignments(
$class-name: 'CardFooter',
$dictionary-values: theme.$footer-alignment-dictionary,
$axis: 'x'
);
7 changes: 7 additions & 0 deletions packages/web/src/scss/components/Card/_CardLink.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@use '../../tools/links';

.CardLink:first-of-type {
@include links.stretch();

text-decoration: none;
adamkudrna marked this conversation as resolved.
Show resolved Hide resolved
}
25 changes: 25 additions & 0 deletions packages/web/src/scss/components/Card/_CardLogo.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
@use 'theme';

.CardLogo {
display: inline-flex;
align-items: center;
justify-content: center;
border: theme.$logo-border-width theme.$logo-border-style theme.$logo-border-color;
border-radius: theme.$logo-border-radius;
background-color: theme.$logo-background-color;
}

.Card--vertical > .CardLogo {
grid-area: media;
place-self: end;
margin-right: theme.$logo-offset-horizontal;
}

:is(.Card--horizontal, .Card--horizontalReversed) > .CardLogo {
grid-area: logo;
justify-self: start;

&:not(:last-child) {
margin-bottom: theme.$gap;
}
}
85 changes: 85 additions & 0 deletions packages/web/src/scss/components/Card/_CardMedia.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// 1. Expand any images or videos to fill the available space, not just direct descendants. This is for the scenario
// when the media is wrapped, for example in a link.
// 2. Make sure rounded corners are applied to video player too.
// 3. Do not let the media push the body content out of the horizontal card.
// 4. We need the specific combination of classes, expanded CardMedia is designed to work only with boxed cards.

@use '@tokens' as tokens;
@use '../../tools/dictionaries';
@use 'theme';

.CardMedia {
--#{tokens.$css-variable-prefix}card-media-border-radius-top-left: #{theme.$border-radius};
--#{tokens.$css-variable-prefix}card-media-border-radius-top-right: #{theme.$border-radius};
--#{tokens.$css-variable-prefix}card-media-border-radius-bottom-left: #{theme.$border-radius};
--#{tokens.$css-variable-prefix}card-media-border-radius-bottom-right: #{theme.$border-radius};
--#{tokens.$css-variable-prefix}card-media-canvas-width: auto;
--#{tokens.$css-variable-prefix}card-media-canvas-height: auto;

grid-area: media;
overflow: hidden;
border-radius: var(--#{tokens.$css-variable-prefix}card-media-border-radius-top-left)
var(--#{tokens.$css-variable-prefix}card-media-border-radius-top-right)
var(--#{tokens.$css-variable-prefix}card-media-border-radius-bottom-right)
var(--#{tokens.$css-variable-prefix}card-media-border-radius-bottom-left);
}

.CardMedia__canvas {
width: var(--#{tokens.$css-variable-prefix}card-media-canvas-width);
max-width: 100%; // 3.
height: var(--#{tokens.$css-variable-prefix}card-media-canvas-height);
}

// 1.
.CardMedia__canvas :where(img, video) {
display: block; // 2.
width: 100%;
height: 100%;
object-fit: cover;
}

.Card--vertical > {
adamkudrna marked this conversation as resolved.
Show resolved Hide resolved
@include dictionaries.generate-sizes($class-name: 'CardMedia', $sizes: theme.$media-sizes-vertical);
}

:is(.Card--horizontal, .Card--horizontalReversed) > {
@include dictionaries.generate-sizes($class-name: 'CardMedia', $sizes: theme.$media-sizes-horizontal);
}

:is(.Card--horizontal, .Card--horizontalReversed) > .CardMedia {
--#{tokens.$css-variable-prefix}card-media-canvas-width: var(--spirit-card-media-size);

align-self: start;
min-width: 0; // 3.
}

:is(.Card--horizontal, .Card--horizontalReversed) > :is(.CardMedia--expanded, .CardMedia--filledHeight) {
--#{tokens.$css-variable-prefix}card-media-canvas-height: 100%;

align-self: stretch;
}

.Card--vertical > .CardMedia {
--#{tokens.$css-variable-prefix}card-media-canvas-height: var(--spirit-card-media-size);

&:not(:last-child) {
margin-bottom: theme.$gap-dense;
}
}

// stylelint-disable selector-max-class -- 4.
.Card--vertical.Card--boxed > .CardMedia--expanded:not(:last-child) {
crishpeen marked this conversation as resolved.
Show resolved Hide resolved
--#{tokens.$css-variable-prefix}card-media-border-radius-bottom-left: 0;
--#{tokens.$css-variable-prefix}card-media-border-radius-bottom-right: 0;
}

.Card--horizontal.Card--boxed > .CardMedia--expanded:not(:last-child) {
--#{tokens.$css-variable-prefix}card-media-border-radius-top-right: 0;
--#{tokens.$css-variable-prefix}card-media-border-radius-bottom-right: 0;
}

.Card--horizontalReversed.Card--boxed > .CardMedia--expanded:not(:last-child) {
--#{tokens.$css-variable-prefix}card-media-border-radius-top-left: 0;
--#{tokens.$css-variable-prefix}card-media-border-radius-bottom-left: 0;
}
// stylelint-enable
16 changes: 16 additions & 0 deletions packages/web/src/scss/components/Card/_CardTitle.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
@use '../../tools/typography';
@use 'theme';

.CardTitle {
@include typography.generate(theme.$title-typography);

color: theme.$title-color;

&:not(:last-child) {
adamkudrna marked this conversation as resolved.
Show resolved Hide resolved
margin-bottom: theme.$title-margin-bottom;
}
}

.CardTitle--heading {
adamkudrna marked this conversation as resolved.
Show resolved Hide resolved
@include typography.generate(theme.$title-heading-typography);
}
Loading
Loading