From 81512c62e84de32a83b308cfcc85393108221170 Mon Sep 17 00:00:00 2001 From: eirikbacker Date: Tue, 24 Sep 2024 16:18:49 +0200 Subject: [PATCH 01/16] fix(Card): section api --- .../Previews/Components/Components.tsx | 24 +- packages/Overview.mdx | 32 +-- packages/css/card.css | 200 ++++++----------- packages/react/src/components/Card/Card.mdx | 10 +- .../src/components/Card/Card.stories.tsx | 212 ++++++++---------- packages/react/src/components/Card/Card.tsx | 45 ++-- .../react/src/components/Card/CardSection.tsx | 26 +++ packages/react/src/components/Card/index.ts | 40 +--- packages/react/stories/showcase.stories.tsx | 24 +- 9 files changed, 255 insertions(+), 358 deletions(-) create mode 100644 packages/react/src/components/Card/CardSection.tsx diff --git a/apps/theme/components/Previews/Components/Components.tsx b/apps/theme/components/Previews/Components/Components.tsx index affa277bcd..ac8fd2d0b2 100644 --- a/apps/theme/components/Previews/Components/Components.tsx +++ b/apps/theme/components/Previews/Components/Components.tsx @@ -158,41 +158,41 @@ export const Components = () => {
- + Sikkerhet og drift - - + Most provide as with carried business are much better more the. - + - + Skole og utdanning - - + Most provide as with carried business are much better more the. - + - + Mat og helse - - + Lenke til artikkel om mat og helse, der du kan lese mer om alt. - +
diff --git a/packages/Overview.mdx b/packages/Overview.mdx index b1682d4416..88f7e9bd67 100644 --- a/packages/Overview.mdx +++ b/packages/Overview.mdx @@ -36,7 +36,7 @@ som kan brukes til å videreutvikle og lage mer avanserte og sammensatte kompone rel='noreferrer' className='sb-unstyled' > - +

Kom i gang

-
- + + Les vår README-fil for å komme i gang med å bruke designsystemet. - + - +

Bidra

-
- + + Si gjerne i fra om du finner en bug eller har forslag til forbedringer. - +
- +

Tokens

-
- + + Design tokens sørger vi for at både designere og utviklere arbeider etter de samme reglene og retningslinjene. Les mer om Tokens. - +
- +

Eget tema?

-
- + + Skal du ta i bruk Designsystemet med dine egne farger og profil-preferanser? Kom i gang her. - +
diff --git a/packages/css/card.css b/packages/css/card.css index 5092af9b72..94abd98c18 100644 --- a/packages/css/card.css +++ b/packages/css/card.css @@ -1,43 +1,50 @@ .ds-card { --dsc-card-border-color: var(--ds-color-neutral-border-subtle); + --dsc-card-border-color--link: var(--ds-color-neutral-border-subtle); --dsc-card-backround: var(--ds-color-neutral-background-default); + --dsc-card-backround--active: var(--ds-color-neutral-surface-default); + --dsc-card-backround--hover: var(--ds-color-neutral-background-subtle); --dsc-card-color: var(--ds-color-neutral-text-default); + --dsc-card-padding: var(--ds-spacing-6); + --dsc-card-gap: 1rem; - display: flex; - flex-direction: column; - width: 100%; - box-sizing: border-box; - position: relative; - overflow: hidden; - color: var(--dsc-card-color); + /* For internal use only */ + --dsc-card-padding-half: calc(var(--dsc-card-padding) / 2); + --dsc-card-padding-invert: calc(var(--dsc-card-padding) * -1); + --dsc-card-padding-width: calc(100% + var(--dsc-card-padding) * 2); + + @composes ds-paragraph from './baseline/typography.css'; + + background: var(--dsc-card-backround); border-radius: min(1rem, var(--ds-border-radius-md)); border: 1px solid var(--dsc-card-border-color); - background: var(--dsc-card-backround); - - &[data-link] { - --dsc-card-border-color: var(--ds-color-neutral-border-default); + box-sizing: border-box; + color: var(--dsc-card-color); + padding: var(--dsc-card-padding); - text-decoration: none; + :is(h1, h2, h3, h4, h5, h6) { + color: inherit; - & h1, - & h2, - & h3, - & h4, - & h5, - & h6 { - color: var(--dsc-card-color); + & a:any-link { + color: inherit; text-decoration: underline; text-decoration-thickness: max(1px, 0.0625rem, 0.1025em); text-underline-offset: max(6px, 0.25rem, 0.22em); } + } + + /* Add states when contaning clickable heading */ + &:has(:is(h1, h2, h3, h4, h5, h6) a) { + --dsc-card-border-color: var(--dsc-card-border-color--link); &:active { - --dsc-card-backround: var(--ds-color-neutral-surface-default); + --dsc-card-backround--active: var(--ds-color-neutral-surface-default); + --dsc-card-backround--hover: var(--ds-color-neutral-background-subtle); } @media (hover: hover) and (pointer: fine) { &:hover { - --dsc-card-backround: var(--ds-color-neutral-background-subtle); + --dsc-card-backround: var(--dsc-card-backround--hover); } } } @@ -45,153 +52,78 @@ &[data-color='subtle'] { --dsc-card-border-color: var(--ds-color-neutral-border-subtle); --dsc-card-backround: var(--ds-color-neutral-background-subtle); - - &[data-link] { - --dsc-card-border-color: var(--ds-color-neutral-border-default); - - &:active { - --dsc-card-backround: var(--ds-color-neutral-surface-hover); - } - - @media (hover: hover) and (pointer: fine) { - &:hover { - --dsc-card-backround: var(--ds-color-neutral-surface-default); - } - } - } + --dsc-card-backround--active: var(--ds-color-neutral-surface-hover); + --dsc-card-backround--hover: var(--ds-color-neutral-surface-default); + --dsc-card-border-color--link: var(--ds-color-neutral-border-default); } &[data-color='brand1'] { --dsc-card-border-color: var(--ds-color-brand1-border-subtle); --dsc-card-backround: var(--ds-color-brand1-surface-default); --dsc-card-color: var(--ds-color-brand1-text-default); - - &[data-link] { - --dsc-card-border-color: var(--ds-color-brand1-border-default); - - &:active { - --dsc-card-backround: var(--ds-color-brand1-surface-active); - } - - @media (hover: hover) and (pointer: fine) { - &:hover { - --dsc-card-backround: var(--ds-color-brand1-surface-hover); - } - } - } + --dsc-card-backround--active: var(--ds-color-brand1-surface-active); + --dsc-card-backround--hover: var(--ds-color-brand1-surface-hover); + --dsc-card-border-color--link: var(--ds-color-brand1-border-default); } &[data-color='brand2'] { --dsc-card-border-color: var(--ds-color-brand2-border-subtle); --dsc-card-backround: var(--ds-color-brand2-surface-default); --dsc-card-color: var(--ds-color-brand2-text-default); - - &[data-link] { - --dsc-card-border-color: var(--ds-color-brand2-border-default); - - &:active { - --dsc-card-backround: var(--ds-color-brand2-surface-active); - } - - @media (hover: hover) and (pointer: fine) { - &:hover { - --dsc-card-backround: var(--ds-color-brand2-surface-hover); - } - } - } + --dsc-card-backround--active: var(--ds-color-brand2-surface-active); + --dsc-card-backround--hover: var(--ds-color-brand2-surface-hover); + --dsc-card-border-color--link: var(--ds-color-brand2-border-default); } &[data-color='brand3'] { --dsc-card-border-color: var(--ds-color-brand3-border-subtle); --dsc-card-backround: var(--ds-color-brand3-surface-default); --dsc-card-color: var(--ds-color-brand3-text-default); - - &[data-link] { - --dsc-card-border-color: var(--ds-color-brand3-border-default); - - &:active { - --dsc-card-backround: var(--ds-color-brand3-surface-active); - } - - @media (hover: hover) and (pointer: fine) { - &:hover { - --dsc-card-backround: var(--ds-color-brand3-surface-hover); - } - } - } - } - - .ds-card__header h1, - .ds-card__header h2, - .ds-card__header h3, - .ds-card__header h4, - .ds-card__header h5, - .ds-card__header h6 { - color: inherit; - } - - .ds-card__media > * { - display: flex; - flex-direction: column; - width: 100%; - border: 0; - } - - .ds-card__media { - width: auto; - } - - .ds-card__media:first-child { - padding-bottom: var(--ds-spacing-4); + --dsc-card-backround--active: var(--ds-color-brand3-surface-active); + --dsc-card-backround--hover: var(--ds-color-brand3-surface-hover); + --dsc-card-border-color--link: var(--ds-color-brand3-border-default); } +} - .ds-card__media:last-child { - padding-top: var(--ds-spacing-6); +:is(.ds-card, .ds-card__section) { + & > hr { + margin: 0 var(--dsc-card-padding-invert); + width: var(--dsc-card-padding-width); } - .ds-card__footer, - .ds-card__content { - display: flex; - justify-content: flex-start; - gap: var(--ds-spacing-4); - flex-wrap: wrap; - word-wrap: break-word; - padding: var(--ds-spacing-2) 0; - color: inherit; + & > * + * { + margin-top: var(--dsc-card-gap); /* https://every-layout.dev/layouts/stack/ */ } +} - .ds-card__content { - flex-direction: column; - } +.ds-card__section { + padding: var(--dsc-card-padding) var(--dsc-card-padding); + margin: var(--dsc-card-padding) var(--dsc-card-padding-invert); - .ds-card__header { - display: flex; - flex-direction: column; - flex-wrap: wrap; - word-wrap: break-word; - font-family: inherit; - padding: var(--ds-spacing-2) 0; + :is(&, hr) + & { + margin-top: 0; /* No margin-top if previous element is hr or also ds-card__section */ } - & a:any-link { - color: var(--ds-color-neutral-text-default); + &:has(+ &, + hr) { + margin-bottom: 0; /* No margin-bottom if next element is hr or also ds-card__section */ } - & > hr { - width: 100%; - margin: var(--ds-spacing-3) 0; + &:first-child { + margin-top: var(--dsc-card-padding-invert); } - & > *:not(.ds-card__media, hr) { - padding-left: var(--ds-spacing-6); - padding-right: var(--ds-spacing-6); + &:last-child { + margin-bottom: var(--dsc-card-padding-invert); } - & > *:not(.ds-card__media):first-child { - padding-top: var(--ds-spacing-6); + & > :where(img, figure, video, audio, iframe):only-child { + border: 0; + display: block; + margin: var(--dsc-card-padding-invert); + width: var(--dsc-card-padding-width); } - & > *:not(.ds-card__media):last-child { - padding-bottom: var(--ds-spacing-6); + & > :where(img, video):only-child { + height: auto; } } diff --git a/packages/react/src/components/Card/Card.mdx b/packages/react/src/components/Card/Card.mdx index afd0e39654..87bc8c562d 100644 --- a/packages/react/src/components/Card/Card.mdx +++ b/packages/react/src/components/Card/Card.mdx @@ -16,9 +16,9 @@ Med `Card` kan vi fremheve informasjon eller oppgaver som hører sammen. Kortene ```tsx import { Card } from '@digdir/designsystemet-react'; - Tittel - Innhold - Valgfri fotnote + Tittel + Innhold + Valgfri fotnote ; ``` @@ -27,9 +27,9 @@ import { Card } from '@digdir/designsystemet-react'; ## Eksempler -`Card.Media` +`Card.Section` -Bruk`Card.Media` hvis du vi ha bilder eller video i kortene. +Bruk`Card.Section` hvis du vi ha bilder eller video i kortene. diff --git a/packages/react/src/components/Card/Card.stories.tsx b/packages/react/src/components/Card/Card.stories.tsx index 3d80807b77..b82d1b755b 100644 --- a/packages/react/src/components/Card/Card.stories.tsx +++ b/packages/react/src/components/Card/Card.stories.tsx @@ -24,19 +24,15 @@ export default { } as Meta; export const Preview: Story = (args) => ( - - - - Card Neutral - - - + + + Card Neutral + + Most provide as with carried business are much better more the perfected designer. Writing slightly explain desk unable at supposedly about this - - - Footer text - + + Footer text ); @@ -52,52 +48,46 @@ export const LinkCard: Story = (args) => ( gridTemplateColumns: 'repeat(2, 400px)', }} > - + - + - - - - Link Card - - - + + + Link Card + + Most provide as with carried business are much better more the perfected designer. Writing slightly explain desk unable at supposedly about this - - - Footer text - + + Footer text - + - + - - - - Link Card - - - + + + Link Card + + Most provide as with carried business are much better more the perfected designer. Writing slightly explain desk unable at supposedly about this - - + + Footer text - + @@ -113,79 +103,69 @@ export const Variants: StoryFn = () => { }} > - + katt - - - - Card Neutral - - - + + + Card Neutral + + Most provide as with carried business are much better more the perfected designer. Writing slightly explain desk unable at supposedly about this - + - + katt - - - - Card Subtle - - - + + + Card Subtle + + Most provide as with carried business are much better more the perfected designer. Writing slightly explain desk unable at supposedly about this - + - + katter - - - - Card First - - - + + + Card First + + Most provide as with carried business are much better more the perfected designer. Writing slightly explain desk unable at supposedly about this - + - + katt - - - - Card Second - - - + + + Card Second + + Most provide as with carried business are much better more the perfected designer. Writing slightly explain desk unable at supposedly about this - + - + katt - - - - Card Third - - - + + + Card Third + + Most provide as with carried business are much better more the perfected designer. Writing slightly explain desk unable at supposedly about this - + ); @@ -200,41 +180,35 @@ export const Media: Story = () => ( }} > - + katt - - - - Card Neutral - - - + + + Card Neutral + + Most provide as with carried business are much better more the perfected designer. Writing slightly explain desk unable at supposedly about this - + - - - - Card Neutral - - - - + + Card Neutral + + Most provide as with carried business are much better more the perfected designer. Writing slightly explain desk unable at supposedly about this - - + + katt - + ); export const Video: Story = () => ( - + - - - - - Vi feira 30 år med digitalt innsyn - - - - + + + + Vi feira 30 år med digitalt innsyn + + + Det er i år 30 år sidan dei første forsøka med elektronisk postjournal i Noreg. Sjå opptak frå feiringa på Pressens Hus der det både var historiske tilbakeblikk og debatt om innsyn og openheit i forvaltninga. - + ); @@ -268,7 +240,7 @@ const options = [ export const Composed: Story = () => ( - +
( Fjern
-
- - + + + - +
); diff --git a/packages/react/src/components/Card/Card.tsx b/packages/react/src/components/Card/Card.tsx index 35bf93354b..952f6bf534 100644 --- a/packages/react/src/components/Card/Card.tsx +++ b/packages/react/src/components/Card/Card.tsx @@ -14,12 +14,7 @@ export type CardProps = { * @default false */ asChild?: boolean; - /** - * Changes styling if card is used as a link - * @default false - */ - isLink?: boolean; - /** Instances of `Card.Header`, `Card.Content`, `Card.Footer` or other React nodes like `Divider` */ + /** Instances of `Card.Section`, `Divider` or other React nodes */ children: ReactNode; } & HTMLAttributes; @@ -27,27 +22,23 @@ export type CardProps = { * Card component to present content in a structured way. * @example * - * Header - * Content - * Footer + * Header + * Content + * Footer * */ -export const Card = forwardRef( - ( - { isLink = false, asChild = false, color = 'neutral', className, ...rest }, - ref, - ) => { - const Component = asChild ? Slot : 'div'; - return ( - - ); - }, -); +export const Card = forwardRef(function Card( + { asChild = false, color = 'neutral', className, ...rest }, + ref, +) { + const Component = asChild ? Slot : 'div'; -Card.displayName = 'Card'; + return ( + + ); +}); diff --git a/packages/react/src/components/Card/CardSection.tsx b/packages/react/src/components/Card/CardSection.tsx new file mode 100644 index 0000000000..cb3f7b10bb --- /dev/null +++ b/packages/react/src/components/Card/CardSection.tsx @@ -0,0 +1,26 @@ +import { Slot } from '@radix-ui/react-slot'; +import cl from 'clsx/lite'; +import type { HTMLAttributes } from 'react'; +import { forwardRef } from 'react'; + +export type CardSectionProps = { + /** + * Change the default rendered element for the one passed as a child, merging their props and behavior. + * @default false + */ + asChild?: boolean; +} & HTMLAttributes; + +export const CardSection = forwardRef( + function CardSection({ asChild, className, ...rest }, ref) { + const Component = asChild ? Slot : 'div'; + + return ( + + ); + }, +); diff --git a/packages/react/src/components/Card/index.ts b/packages/react/src/components/Card/index.ts index 9c5592dd83..ec3f2f8364 100644 --- a/packages/react/src/components/Card/index.ts +++ b/packages/react/src/components/Card/index.ts @@ -1,36 +1,12 @@ -import type { CardProps } from './Card'; import { Card as CardParent } from './Card'; -import type { CardContentProps } from './CardContent'; -import { CardContent } from './CardContent'; -import type { CardFooterProps } from './CardFooter'; -import { CardFooter } from './CardFooter'; -import { CardHeader, type CardHeaderProps } from './CardHeader'; -import { CardMedia, type CardMediaProps } from './CardMedia'; +import { CardSection } from './CardSection'; -type CardComponent = typeof CardParent & { - Header: typeof CardHeader; - Content: typeof CardContent; - Footer: typeof CardFooter; - Media: typeof CardMedia; -}; +const Card = Object.assign(CardParent, { + Section: CardSection, +}); -const Card = CardParent as CardComponent; +Card.Section.displayName = 'Card.Section'; -Card.Header = CardHeader; -Card.Content = CardContent; -Card.Footer = CardFooter; -Card.Media = CardMedia; - -Card.Header.displayName = 'Card.Header'; -Card.Content.displayName = 'Card.Content'; -Card.Footer.displayName = 'Card.Footer'; -Card.Media.displayName = 'Card.Media'; - -export type { - CardProps, - CardHeaderProps, - CardContentProps, - CardFooterProps, - CardMediaProps, -}; -export { Card, CardHeader, CardContent, CardFooter, CardMedia }; +export type { CardProps } from './Card'; +export type { CardSectionProps } from './CardSection'; +export { Card, CardSection }; diff --git a/packages/react/stories/showcase.stories.tsx b/packages/react/stories/showcase.stories.tsx index 10c4c2a1c8..4267709160 100644 --- a/packages/react/stories/showcase.stories.tsx +++ b/packages/react/stories/showcase.stories.tsx @@ -163,29 +163,29 @@ export const Showcase: StoryFn = () => {
- + Sikkerhet og drift - - + + Most provide as with carried business are much better more the. - + - + Skole og utdanning - - + + Most provide as with carried business are much better more the. - + - + Mat og helse - - + + Lenke til artikkel om mat og helse, der du kan lese mer om alt. - +
From 6024c5ec889e4591b9386f23d3948a451ed86b93 Mon Sep 17 00:00:00 2001 From: eirikbacker Date: Tue, 24 Sep 2024 17:59:21 +0200 Subject: [PATCH 02/16] fix(Card): docs usage and a11y links --- .../_components/Card/BlogCard.module.css | 25 ++- .../app/bloggen/_components/Card/BlogCard.tsx | 66 +++----- .../Previews/Components/Components.module.css | 14 -- .../Previews/Components/Components.tsx | 48 ++---- packages/Overview.mdx | 148 ++++++++---------- packages/css/card.css | 14 +- packages/react/src/components/Card/Card.tsx | 25 ++- packages/react/stories/showcase.module.css | 14 -- packages/react/stories/showcase.stories.tsx | 32 ++-- 9 files changed, 159 insertions(+), 227 deletions(-) diff --git a/apps/storefront/app/bloggen/_components/Card/BlogCard.module.css b/apps/storefront/app/bloggen/_components/Card/BlogCard.module.css index 8f3648bd01..3da6a3570a 100644 --- a/apps/storefront/app/bloggen/_components/Card/BlogCard.module.css +++ b/apps/storefront/app/bloggen/_components/Card/BlogCard.module.css @@ -1,32 +1,27 @@ .image { - margin: 0; aspect-ratio: 16/9; } @media screen and (min-width: 1024px) { - .card[data-featured='true'] .media { - padding-bottom: 0; - } - .card[data-featured='true'] { display: grid; grid-template-columns: 1fr 1fr; } - .card[data-featured='true'] .wrapper { - display: flex; - flex-wrap: wrap; - flex-direction: column; - justify-content: center; - padding: var(--ds-spacing-8) var(--ds-spacing-10); + .card[data-featured='true'] > * { + margin: var(--dsc-card-padding-invert); } - .card[data-featured='true'] .heading { - padding-top: 0; + .card[data-featured='true'] > :first-child { + margin-right: 0; } - .card[data-featured='true'] .footer { - padding-bottom: 0; + .card[data-featured='true'] > :last-child { + margin-left: 0; + display: flex; + flex-direction: column; + justify-content: center; + padding: var(--ds-spacing-8) var(--ds-spacing-10); } } diff --git a/apps/storefront/app/bloggen/_components/Card/BlogCard.tsx b/apps/storefront/app/bloggen/_components/Card/BlogCard.tsx index 29f08f3381..ac0a989cee 100644 --- a/apps/storefront/app/bloggen/_components/Card/BlogCard.tsx +++ b/apps/storefront/app/bloggen/_components/Card/BlogCard.tsx @@ -1,9 +1,6 @@ import { Card, - CardContent, - CardFooter, - CardHeader, - CardMedia, + CardSection, Heading, Paragraph, Tag, @@ -42,49 +39,38 @@ export const BlogCard = ({ }: BlogCardProps) => { return ( - - - - -
- - {tagText && ( - - {tagText} - - )} - - {title} - - - - {desc} - + + + + + {tagText && ( + + {tagText} + + )} + + {title} + + {desc} + {author || (date && ( - - - {date} - {author && ( - <> - - {author} - - )} - - + <> + {date} + {author && ( + <> + + {author} + + )} + ))} -
- + +
); }; diff --git a/apps/theme/components/Previews/Components/Components.module.css b/apps/theme/components/Previews/Components/Components.module.css index 6fb768bb14..aa4e646b69 100644 --- a/apps/theme/components/Previews/Components/Components.module.css +++ b/apps/theme/components/Previews/Components/Components.module.css @@ -178,24 +178,10 @@ gap: 20px; } -.helpHeader { - padding-left: 20px; - padding-top: 20px; - padding-right: 20px; - margin-bottom: -10px; -} - .helpHeading { margin-bottom: 20px; } -.helpContent { - padding-right: 20px; - padding-bottom: 20px; - padding-left: 20px; - font-size: 16px; -} - .tagList { display: flex; align-items: center; diff --git a/apps/theme/components/Previews/Components/Components.tsx b/apps/theme/components/Previews/Components/Components.tsx index ac8fd2d0b2..0dddfd11fd 100644 --- a/apps/theme/components/Previews/Components/Components.tsx +++ b/apps/theme/components/Previews/Components/Components.tsx @@ -157,43 +157,25 @@ export const Components = () => { Hva kan vi hjelpe deg med?
- - - - Sikkerhet og drift - - - + + Sikkerhet og drift + Most provide as with carried business are much better more the. - + - - - - Skole og utdanning - - - + + Skole og utdanning + Most provide as with carried business are much better more the. - + - - - - - Mat og helse - - - - Lenke til artikkel om mat og helse, der du kan lese mer om alt. - - + + + Mat og helse + + + Lenke til artikkel om mat og helse, der du kan lese mer om alt. +
diff --git a/packages/Overview.mdx b/packages/Overview.mdx index 88f7e9bd67..886f7d70fe 100644 --- a/packages/Overview.mdx +++ b/packages/Overview.mdx @@ -25,111 +25,87 @@ som kan brukes til å videreutvikle og lage mer avanserte og sammensatte kompone marginBottom: 'var(--ds-spacing-12)', }} > - - + - - + -

Kom i gang

- - - - Les vår README-fil for å komme i gang med å bruke designsystemet. - -
+ Kom i gang + + + + Les vår README-fil for å komme i gang med å bruke designsystemet.
- - + - - + -

Bidra

- - - - Si gjerne i fra om du finner en bug eller har forslag til forbedringer. - -
+ Bidra + + + + Si gjerne i fra om du finner en bug eller har forslag til forbedringer.
- - + - - + -

Tokens

- - - - Design tokens sørger vi for at både designere og utviklere arbeider - etter de samme reglene og retningslinjene. Les mer om Tokens. - -
+ Tokens + + + + Design tokens sørger vi for at både designere og utviklere arbeider + etter de samme reglene og retningslinjene. Les mer om Tokens.
- - + - - + -

Eget tema?

- - - - Skal du ta i bruk Designsystemet med dine egne farger og - profil-preferanser? Kom i gang her. - -
+ Eget tema? + + + + Skal du ta i bruk Designsystemet med dine egne farger og + profil-preferanser? Kom i gang her.
diff --git a/packages/css/card.css b/packages/css/card.css index 94abd98c18..9165f7d1b6 100644 --- a/packages/css/card.css +++ b/packages/css/card.css @@ -37,6 +37,8 @@ &:has(:is(h1, h2, h3, h4, h5, h6) a) { --dsc-card-border-color: var(--dsc-card-border-color--link); + cursor: pointer; + &:active { --dsc-card-backround--active: var(--ds-color-neutral-surface-default); --dsc-card-backround--hover: var(--ds-color-neutral-background-subtle); @@ -86,13 +88,17 @@ } :is(.ds-card, .ds-card__section) { - & > hr { - margin: 0 var(--dsc-card-padding-invert); - width: var(--dsc-card-padding-width); + & > :first-child { + margin-block: 0; } & > * + * { - margin-top: var(--dsc-card-gap); /* https://every-layout.dev/layouts/stack/ */ + margin-block: var(--dsc-card-gap) 0; /* https://every-layout.dev/layouts/stack/ */ + } + + & > hr { + margin: 0 var(--dsc-card-padding-invert); + width: var(--dsc-card-padding-width); } } diff --git a/packages/react/src/components/Card/Card.tsx b/packages/react/src/components/Card/Card.tsx index 952f6bf534..7a819defd8 100644 --- a/packages/react/src/components/Card/Card.tsx +++ b/packages/react/src/components/Card/Card.tsx @@ -1,7 +1,8 @@ +import { useMergeRefs } from '@floating-ui/react'; import { Slot } from '@radix-ui/react-slot'; import cl from 'clsx/lite'; import type { HTMLAttributes, ReactNode } from 'react'; -import { forwardRef } from 'react'; +import { forwardRef, useEffect, useRef } from 'react'; export type CardProps = { /** @@ -32,12 +33,32 @@ export const Card = forwardRef(function Card( ref, ) { const Component = asChild ? Slot : 'div'; + const cardRef = useRef(null); + const mergedRefs = useMergeRefs([cardRef, ref]); + + // Forward click on card to heading links for better accessibility + // https://adrianroselli.com/2020/02/block-links-cards-clickable-regions-etc.html + useEffect(() => { + const card = cardRef.current; + const handleClick = ({ ctrlKey, metaKey, target }: MouseEvent) => { + const link = card?.querySelector( + ':is(h1,h2,h3,h4,h5,h6) a', + ); + + if (!link || link?.contains(target as Node)) return; // Let links handle their own clicks + if (ctrlKey || metaKey) window.open(link.href, '', 'noreferrer'); + else link.click(); // Using link.click instead of window.location.href as this will trigger the browser's handling of rel=, target=, etc. + }; + + card?.addEventListener('click', handleClick); + return () => card?.removeEventListener('click', handleClick); + }, []); return ( ); diff --git a/packages/react/stories/showcase.module.css b/packages/react/stories/showcase.module.css index 0d665444ad..d2ed504e18 100644 --- a/packages/react/stories/showcase.module.css +++ b/packages/react/stories/showcase.module.css @@ -147,24 +147,10 @@ gap: 20px; } -.helpHeader { - padding-left: 20px; - padding-top: 20px; - padding-right: 20px; - margin-bottom: -10px; -} - .helpHeading { margin-bottom: 20px; } -.helpContent { - padding-right: 20px; - padding-bottom: 20px; - padding-left: 20px; - font-size: 16px; -} - .tagList { display: flex; align-items: center; diff --git a/packages/react/stories/showcase.stories.tsx b/packages/react/stories/showcase.stories.tsx index 4267709160..14409ac1bc 100644 --- a/packages/react/stories/showcase.stories.tsx +++ b/packages/react/stories/showcase.stories.tsx @@ -163,30 +163,24 @@ export const Showcase: StoryFn = () => {
- - Sikkerhet og drift - - + Sikkerhet og drift + Most provide as with carried business are much better more the. - + - - Skole og utdanning - - + Skole og utdanning + Most provide as with carried business are much better more the. - + - - - - Mat og helse - - - Lenke til artikkel om mat og helse, der du kan lese mer om alt. - - + + + Mat og helse + + + Lenke til artikkel om mat og helse, der du kan lese mer om alt. +
From dccec621778f32635ced86a21b5b65b031a07a83 Mon Sep 17 00:00:00 2001 From: eirikbacker Date: Tue, 24 Sep 2024 18:21:39 +0200 Subject: [PATCH 03/16] fix(Card): states --- packages/css/card.css | 81 +++++++----- .../src/components/Card/Card.stories.tsx | 123 ++++++++++++------ .../react/src/components/Card/CardContent.tsx | 32 ----- .../react/src/components/Card/CardFooter.tsx | 32 ----- .../react/src/components/Card/CardHeader.tsx | 32 ----- .../react/src/components/Card/CardMedia.tsx | 28 ---- 6 files changed, 131 insertions(+), 197 deletions(-) delete mode 100644 packages/react/src/components/Card/CardContent.tsx delete mode 100644 packages/react/src/components/Card/CardFooter.tsx delete mode 100644 packages/react/src/components/Card/CardHeader.tsx delete mode 100644 packages/react/src/components/Card/CardMedia.tsx diff --git a/packages/css/card.css b/packages/css/card.css index 9165f7d1b6..4d37fc19d6 100644 --- a/packages/css/card.css +++ b/packages/css/card.css @@ -1,9 +1,9 @@ .ds-card { --dsc-card-border-color: var(--ds-color-neutral-border-subtle); --dsc-card-border-color--link: var(--ds-color-neutral-border-subtle); - --dsc-card-backround: var(--ds-color-neutral-background-default); - --dsc-card-backround--active: var(--ds-color-neutral-surface-default); - --dsc-card-backround--hover: var(--ds-color-neutral-background-subtle); + --dsc-card-background: var(--ds-color-neutral-background-default); + --dsc-card-background--active: var(--ds-color-neutral-surface-default); + --dsc-card-background--hover: var(--ds-color-neutral-background-subtle); --dsc-card-color: var(--ds-color-neutral-text-default); --dsc-card-padding: var(--ds-spacing-6); --dsc-card-gap: 1rem; @@ -15,79 +15,89 @@ @composes ds-paragraph from './baseline/typography.css'; - background: var(--dsc-card-backround); + background: var(--dsc-card-background); border-radius: min(1rem, var(--ds-border-radius-md)); border: 1px solid var(--dsc-card-border-color); box-sizing: border-box; color: var(--dsc-card-color); + overflow: clip; /* Bad, but needed to make media clipped by card radius */ padding: var(--dsc-card-padding); - :is(h1, h2, h3, h4, h5, h6) { + :is(h1, h2, h3, h4, h5, h6, p, ul, ol, li) { color: inherit; + } - & a:any-link { - color: inherit; - text-decoration: underline; - text-decoration-thickness: max(1px, 0.0625rem, 0.1025em); - text-underline-offset: max(6px, 0.25rem, 0.22em); - } + /* Style link in heading, or heading when Card is anchor */ + :is(h1, h2, h3, h4, h5, h6) a:any-link, + &:is(a:any-link) :is(h1, h2, h3, h4, h5, h6) { + color: inherit; + outline: 0; + text-decoration: underline; + text-decoration-thickness: max(1px, 0.0625rem, 0.1025em); + text-underline-offset: max(6px, 0.25rem, 0.22em); } - /* Add states when contaning clickable heading */ + /* Add states when Card is a anchor, button, or when containing a anchor in heading */ + &:is(a), &:has(:is(h1, h2, h3, h4, h5, h6) a) { --dsc-card-border-color: var(--dsc-card-border-color--link); cursor: pointer; - - &:active { - --dsc-card-backround--active: var(--ds-color-neutral-surface-default); - --dsc-card-backround--hover: var(--ds-color-neutral-background-subtle); - } + text-decoration: none; @media (hover: hover) and (pointer: fine) { &:hover { - --dsc-card-backround: var(--dsc-card-backround--hover); + --dsc-card-background: var(--dsc-card-background--hover); } } + + &:where(:focus-visible, :has(:focus-visible)) { + box-shadow: var(--dsc-focus-boxShadow); + } + + &:active { + --dsc-card-background: var(--dsc-card-background--active); + } } &[data-color='subtle'] { - --dsc-card-border-color: var(--ds-color-neutral-border-subtle); - --dsc-card-backround: var(--ds-color-neutral-background-subtle); - --dsc-card-backround--active: var(--ds-color-neutral-surface-hover); - --dsc-card-backround--hover: var(--ds-color-neutral-surface-default); + --dsc-card-background--active: var(--ds-color-neutral-surface-hover); + --dsc-card-background--hover: var(--ds-color-neutral-surface-default); + --dsc-card-background: var(--ds-color-neutral-background-subtle); --dsc-card-border-color--link: var(--ds-color-neutral-border-default); + --dsc-card-border-color: var(--ds-color-neutral-border-subtle); } &[data-color='brand1'] { + --dsc-card-background--active: var(--ds-color-brand1-surface-active); + --dsc-card-background--hover: var(--ds-color-brand1-surface-hover); + --dsc-card-background: var(--ds-color-brand1-surface-default); + --dsc-card-border-color--link: var(--ds-color-brand1-border-default); --dsc-card-border-color: var(--ds-color-brand1-border-subtle); - --dsc-card-backround: var(--ds-color-brand1-surface-default); --dsc-card-color: var(--ds-color-brand1-text-default); - --dsc-card-backround--active: var(--ds-color-brand1-surface-active); - --dsc-card-backround--hover: var(--ds-color-brand1-surface-hover); - --dsc-card-border-color--link: var(--ds-color-brand1-border-default); } &[data-color='brand2'] { + --dsc-card-background--active: var(--ds-color-brand2-surface-active); + --dsc-card-background--hover: var(--ds-color-brand2-surface-hover); + --dsc-card-background: var(--ds-color-brand2-surface-default); + --dsc-card-border-color--link: var(--ds-color-brand2-border-default); --dsc-card-border-color: var(--ds-color-brand2-border-subtle); - --dsc-card-backround: var(--ds-color-brand2-surface-default); --dsc-card-color: var(--ds-color-brand2-text-default); - --dsc-card-backround--active: var(--ds-color-brand2-surface-active); - --dsc-card-backround--hover: var(--ds-color-brand2-surface-hover); - --dsc-card-border-color--link: var(--ds-color-brand2-border-default); } &[data-color='brand3'] { + --dsc-card-background--active: var(--ds-color-brand3-surface-active); + --dsc-card-background--hover: var(--ds-color-brand3-surface-hover); + --dsc-card-background: var(--ds-color-brand3-surface-default); + --dsc-card-border-color--link: var(--ds-color-brand3-border-default); --dsc-card-border-color: var(--ds-color-brand3-border-subtle); - --dsc-card-backround: var(--ds-color-brand3-surface-default); --dsc-card-color: var(--ds-color-brand3-text-default); - --dsc-card-backround--active: var(--ds-color-brand3-surface-active); - --dsc-card-backround--hover: var(--ds-color-brand3-surface-hover); - --dsc-card-border-color--link: var(--ds-color-brand3-border-default); } } -:is(.ds-card, .ds-card__section) { +/* Usin :where to overwrite user agent CSS, but not our own CSS */ +:where(.ds-card, .ds-card__section) { & > :first-child { margin-block: 0; } @@ -116,6 +126,7 @@ &:first-child { margin-top: var(--dsc-card-padding-invert); + overflow: hidden; } &:last-child { diff --git a/packages/react/src/components/Card/Card.stories.tsx b/packages/react/src/components/Card/Card.stories.tsx index b82d1b755b..2b6971300b 100644 --- a/packages/react/src/components/Card/Card.stories.tsx +++ b/packages/react/src/components/Card/Card.stories.tsx @@ -48,47 +48,43 @@ export const LinkCard: Story = (args) => ( gridTemplateColumns: 'repeat(2, 400px)', }} > - - - - - - + + + + + + Link Card - - - Most provide as with carried business are much better more the - perfected designer. Writing slightly explain desk unable at supposedly - about this - - Footer text - + + + + Most provide as with carried business are much better more the perfected + designer. Writing slightly explain desk unable at supposedly about this + + Footer text - - - - - - + + + + + + Link Card - - - Most provide as with carried business are much better more the - perfected designer. Writing slightly explain desk unable at supposedly - about this - - - Footer text - - + + + + Most provide as with carried business are much better more the perfected + designer. Writing slightly explain desk unable at supposedly about this + + Footer text ); @@ -271,3 +267,54 @@ export const Composed: Story = () => (
); + +export const AsLink: Story = (args) => ( +
+ + + + + + + Link Card + + + Most provide as with carried business are much better more the + perfected designer. Writing slightly explain desk unable at supposedly + about this + + Footer text + + + + + + + + + Link Card + + + Most provide as with carried business are much better more the + perfected designer. Writing slightly explain desk unable at supposedly + about this + + Footer text + + +
+); diff --git a/packages/react/src/components/Card/CardContent.tsx b/packages/react/src/components/Card/CardContent.tsx deleted file mode 100644 index c5308a8be8..0000000000 --- a/packages/react/src/components/Card/CardContent.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { Slot } from '@radix-ui/react-slot'; -import cl from 'clsx/lite'; -import type { HTMLAttributes } from 'react'; -import { forwardRef } from 'react'; - -import { Paragraph } from '../Typography'; - -export type CardContentProps = { - /** - * Change the default rendered element for the one passed as a child, merging their props and behavior. - * @default false - */ - asChild?: boolean; -} & HTMLAttributes; - -export const CardContent = forwardRef( - ({ asChild, className, ...rest }, ref) => { - const Component = asChild ? Slot : 'div'; - - return ( - - - - ); - }, -); - -CardContent.displayName = 'CardContent'; diff --git a/packages/react/src/components/Card/CardFooter.tsx b/packages/react/src/components/Card/CardFooter.tsx deleted file mode 100644 index e9ff90a792..0000000000 --- a/packages/react/src/components/Card/CardFooter.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { Slot } from '@radix-ui/react-slot'; -import cl from 'clsx/lite'; -import type { HTMLAttributes } from 'react'; -import { forwardRef } from 'react'; - -import { Paragraph } from '../Typography'; - -export type CardFooterProps = { - /** - * Change the default rendered element for the one passed as a child, merging their props and behavior. - * @default false - */ - asChild?: boolean; -} & HTMLAttributes; - -export const CardFooter = forwardRef( - ({ asChild, className, ...rest }, ref) => { - const Component = asChild ? Slot : 'div'; - - return ( - - - - ); - }, -); - -CardFooter.displayName = 'CardFooter'; diff --git a/packages/react/src/components/Card/CardHeader.tsx b/packages/react/src/components/Card/CardHeader.tsx deleted file mode 100644 index a80df0f058..0000000000 --- a/packages/react/src/components/Card/CardHeader.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { Slot } from '@radix-ui/react-slot'; -import cl from 'clsx/lite'; -import type { HTMLAttributes } from 'react'; -import { forwardRef } from 'react'; - -import { Heading } from '../Typography'; - -export type CardHeaderProps = { - /** - * Change the default rendered element for the one passed as a child, merging their props and behavior. - * @default false - */ - asChild?: boolean; -} & HTMLAttributes; - -export const CardHeader = forwardRef( - ({ asChild, className, ...rest }, ref) => { - const Component = asChild ? Slot : 'div'; - - return ( - - - - ); - }, -); - -CardHeader.displayName = 'CardHeader'; diff --git a/packages/react/src/components/Card/CardMedia.tsx b/packages/react/src/components/Card/CardMedia.tsx deleted file mode 100644 index 53710ea05b..0000000000 --- a/packages/react/src/components/Card/CardMedia.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { Slot } from '@radix-ui/react-slot'; -import cl from 'clsx/lite'; -import type { HTMLAttributes } from 'react'; -import { forwardRef } from 'react'; - -export type CardMediaProps = { - /** - * Change the default rendered element for the one passed as a child, merging their props and behavior. - * @default false - */ - asChild?: boolean; -} & HTMLAttributes; - -export const CardMedia = forwardRef( - ({ asChild, className, ...rest }, ref) => { - const Component = asChild ? Slot : 'div'; - - return ( - - ); - }, -); - -CardMedia.displayName = 'CardMedia'; From 134ce0872559b816d31b03ab1286d0d272c330f7 Mon Sep 17 00:00:00 2001 From: eirikbacker Date: Tue, 24 Sep 2024 18:24:11 +0200 Subject: [PATCH 04/16] chore(Card): update tests --- .../react/src/components/Card/Card.test.tsx | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/packages/react/src/components/Card/Card.test.tsx b/packages/react/src/components/Card/Card.test.tsx index 7aa6759783..9cfc2baadc 100644 --- a/packages/react/src/components/Card/Card.test.tsx +++ b/packages/react/src/components/Card/Card.test.tsx @@ -2,17 +2,12 @@ import { render as renderRtl, screen } from '@testing-library/react'; import type { CardProps } from './Card'; import { Card } from './Card'; -import { CardContent } from './CardContent'; -import { CardFooter } from './CardFooter'; -import { CardHeader } from './CardHeader'; -import { CardMedia } from './CardMedia'; +import { CardSection } from './CardSection'; const renderCard = (props?: Partial) => renderRtl( - - - + , ); @@ -27,12 +22,12 @@ describe('Card Component', () => { renderRtl( - + cat - - - - + + + + , ); expect(screen.getByRole('img')).toHaveAttribute('src', mediaImage); From f486419d0066a9f734006310d1e49d6870df7e5b Mon Sep 17 00:00:00 2001 From: eirikbacker Date: Tue, 24 Sep 2024 18:28:30 +0200 Subject: [PATCH 05/16] chore(Card): storefront fix --- .../app/bloggen/2024/altinn-studio/page.mdx | 10 ++--- .../tilgjengelighet/kontrast/page.mdx | 44 +++++++++---------- 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/apps/storefront/app/bloggen/2024/altinn-studio/page.mdx b/apps/storefront/app/bloggen/2024/altinn-studio/page.mdx index 942ef601f1..1be02681d0 100644 --- a/apps/storefront/app/bloggen/2024/altinn-studio/page.mdx +++ b/apps/storefront/app/bloggen/2024/altinn-studio/page.mdx @@ -32,12 +32,10 @@ For at Team Altinn Studio skal nå sine mål om å skape et godt verktøy — m _"Det er viktig at det er mulig å utvide komponentene til det mer komplekse, fordi alle produkter skal løse et unikt behov i markedet, og ofte vil det forekomme situasjoner hvor mer spesialiserte komponenter er nødvendig. Hvis vi kan utvide eksisterende komponenter fra designsystemet, så vil vi kunne ivareta mye av tilgjengelighetskravene og visuell likhet med de grunnleggende komponentene uten å måtte legge inn for mye innsats."_ - - David Øvrelid, Tech Lead i Altinn Studio, forklarer hvordan Altinn Studio - bruker Designsystemet. Artikkelen ble først publisert på Medium. [Les den - opprinnelige - artikkelen](https://davidovrelid.com/hvordan-vi-kan-ta-i-bruk-designsystemet-no-p%C3%A5-en-forusigbar-m%C3%A5te-3988980884a2) - + David Øvrelid, Tech Lead i Altinn Studio, forklarer hvordan Altinn Studio + bruker Designsystemet. Artikkelen ble først publisert på Medium. [Les den + opprinnelige + artikkelen](https://davidovrelid.com/hvordan-vi-kan-ta-i-bruk-designsystemet-no-p%C3%A5-en-forusigbar-m%C3%A5te-3988980884a2)

diff --git a/apps/storefront/app/god-praksis/tilgjengelighet/kontrast/page.mdx b/apps/storefront/app/god-praksis/tilgjengelighet/kontrast/page.mdx index 451472ef09..45cc935ef0 100644 --- a/apps/storefront/app/god-praksis/tilgjengelighet/kontrast/page.mdx +++ b/apps/storefront/app/god-praksis/tilgjengelighet/kontrast/page.mdx @@ -37,29 +37,27 @@ For å sikre god lesbarhet skal all tekst ha tilstrekkelig kontrast mot bakgrunn Alle brukerne, også de med svekket syn, skal kunne se innholdet i digitale tjenester. Web Content Accessibility Guidelines (WCAG) inneholder suksesskriterier og forslag til løsninger for å lykkes. Men det er ikke samsvar mellom dagens kontrastregler og kravet om at alle skal kunne se innholdet. - - - Gjeldende regelverk, WCAG 2.1 - - - - **1.4.3 Kontrast (minimum) (Nivå AA)**: Kontrastforholdet mellom - teksten og bakgrunnen er minst 4,5:1. [1.4.3 Kontrast (minimum), WCAG - 2.1 - (w3.org)](https://www.w3.org/Translations/WCAG21-no/#contrast-minimum) - - - **1.4.11 Kontrast for ikke-tekstlig innhold (Nivå AA)**: Den visuelle - presentasjonen av det følgende har et kontrastforhold på minst 3:1 mot - farge(r) som ligger ved siden av. [1.4.11 Kontrast for ikke-tekstlig - innhold, WCAG 2.1 - (w3.org)](https://www.w3.org/Translations/WCAG21-no/#non-text-contrast) - - - + + Gjeldende regelverk, WCAG 2.1 + + + + **1.4.3 Kontrast (minimum) (Nivå AA)**: Kontrastforholdet mellom + teksten og bakgrunnen er minst 4,5:1. [1.4.3 Kontrast (minimum), WCAG + 2.1 + (w3.org)](https://www.w3.org/Translations/WCAG21-no/#contrast-minimum) + + + **1.4.11 Kontrast for ikke-tekstlig innhold (Nivå AA)**: Den visuelle + presentasjonen av det følgende har et kontrastforhold på minst 3:1 mot + farge(r) som ligger ved siden av. [1.4.11 Kontrast for ikke-tekstlig + innhold, WCAG 2.1 + (w3.org)](https://www.w3.org/Translations/WCAG21-no/#non-text-contrast) + +
From 03136ed245c1360d59dcdb19ad9bd54ad1e7ca2c Mon Sep 17 00:00:00 2001 From: eirikbacker Date: Tue, 24 Sep 2024 18:43:13 +0200 Subject: [PATCH 06/16] chore(Card): storefront fix --- .../tilgjengelighet/kontrast/page.mdx | 102 ++++++++---------- .../app/monstre/feilmeldinger/page.mdx | 17 +-- .../obligatoriske-og-valgfrie-felt/page.mdx | 4 +- .../app/monstre/systemvarsler/page.mdx | 8 +- 4 files changed, 53 insertions(+), 78 deletions(-) diff --git a/apps/storefront/app/god-praksis/tilgjengelighet/kontrast/page.mdx b/apps/storefront/app/god-praksis/tilgjengelighet/kontrast/page.mdx index 45cc935ef0..8cf700241b 100644 --- a/apps/storefront/app/god-praksis/tilgjengelighet/kontrast/page.mdx +++ b/apps/storefront/app/god-praksis/tilgjengelighet/kontrast/page.mdx @@ -63,36 +63,34 @@ Alle brukerne, også de med svekket syn, skal kunne se innholdet i digitale tjen
- - - Fremtidig eller strengere: - - - - **1.4.6 Kontrast** (forbedret) (Nivå AAA): Den visuelle presentasjonen - av tekst og bilder av tekst har et kontrastforhold på minst 7:1, - unntatt uvesentlig tekst og skriftstørrelser større enn 18px eller - 14px fet. [ 1.4.6 Kontrast (forbedret), WCAG 2.1 - (w3.org)](https://www.w3.org/Translations/WCAG21-no/#contrast-enhanced) - - - **WCAG 2.2: 2.4.13** Focus Appearance (Nivå AAA), om utseende til - fokusmarkering krever at fokusindikator har en kontrastverdi på 3:1 - mellom samme piksler i fokusert og ikke-fokusert tilstand. - [Understanding Success Criterion 2.4.13: Focus Appearance | WAI | - W3C](https://www.w3.org/WAI/WCAG22/Understanding/focus-appearance.html) - - - **WCAG 3** har et krav om farge og kontrast, visuell kontrast i tekst - (sølv): Sørg for tilstrekkelig kontrast mellom tekst i forgrunnen og - bakgrunnen for teksten. Her brukes det en ny metode, med navn APCA, - for å regne ut kontrasten. - - - + + Fremtidig eller strengere: + + + + **1.4.6 Kontrast** (forbedret) (Nivå AAA): Den visuelle presentasjonen + av tekst og bilder av tekst har et kontrastforhold på minst 7:1, + unntatt uvesentlig tekst og skriftstørrelser større enn 18px eller + 14px fet. [ 1.4.6 Kontrast (forbedret), WCAG 2.1 + (w3.org)](https://www.w3.org/Translations/WCAG21-no/#contrast-enhanced) + + + **WCAG 2.2: 2.4.13** Focus Appearance (Nivå AAA), om utseende til + fokusmarkering krever at fokusindikator har en kontrastverdi på 3:1 + mellom samme piksler i fokusert og ikke-fokusert tilstand. + [Understanding Success Criterion 2.4.13: Focus Appearance | WAI | + W3C](https://www.w3.org/WAI/WCAG22/Understanding/focus-appearance.html) + + + **WCAG 3** har et krav om farge og kontrast, visuell kontrast i tekst + (sølv): Sørg for tilstrekkelig kontrast mellom tekst i forgrunnen og + bakgrunnen for teksten. Her brukes det en ny metode, med navn APCA, + for å regne ut kontrasten. + + ## Mer presis metode @@ -130,31 +128,27 @@ Vi vet at selv om en løsning oppfyller de konkrete kravene fra regelverket om u Hvis vi oppfyller metoden i WCAG 2, etterlever vi teknisk sett kravet til universell utforming, men det betyr ikke at innholdet er tilgjengelig eller universelt utformet. Derfor strekker vi oss langt i å også oppfylle de fremtidige WCAG-3 kravene som bruker APCA-metoden. - - **Kontrast i WCAG 2 «luminosity contrast algorithm**
- _«I WCAG 2 er kontrast en måleenhet for forskjellen i den opplevde lysintensiteten - mellom to farger. Denne forskjellen er beskrevet som et forhold fra 1:1 (for - eksempel hvit på hvit) til 21:1 (for eksempel svart på hvit).»_ – WebAIM, vår - oversettelse. Kontrastene regnes ut ved hjelp av fargenes RGB, HEX eller HSL - verdier i tillegg til transparens (alpha), om fargen er tekst, grafikk, forgrunn - eller bakgrunn har ingen betydning. -
+ **Kontrast i WCAG 2 «luminosity contrast algorithm**
+ _«I WCAG 2 er kontrast en måleenhet for forskjellen i den opplevde lysintensiteten + mellom to farger. Denne forskjellen er beskrevet som et forhold fra 1:1 (for + eksempel hvit på hvit) til 21:1 (for eksempel svart på hvit).»_ – WebAIM, vår + oversettelse. Kontrastene regnes ut ved hjelp av fargenes RGB, HEX eller HSL + verdier i tillegg til transparens (alpha), om fargen er tekst, grafikk, forgrunn + eller bakgrunn har ingen betydning.

- - **Kontrast i WCAG 3 «visual contrast algorithm»**
I WCAG 3 benyttes en - visuell-kontrast algoritme som kalles for APCA, det er fremdeles - fargeverdiene som benyttes for å kalkulere kontrasten, men også om fargen er - tekst, grafikk, forgrunn eller bakgrunn, i tillegg har også valg av font, - font-vekt og størrelse en innvirkning på hvilke kontrastverdier som er - godkjent. Forskjellige farger som i WCAG 2 ville oppnådd like - kontrastverdier vil i APCA kunne få andre verdier fordi en i større grad - kalkulerer ut fra øyets evne til å oppfatte farger enn kun den tekniske - fargeverdien. -
+ **Kontrast i WCAG 3 «visual contrast algorithm»**
I WCAG 3 benyttes en + visuell-kontrast algoritme som kalles for APCA, det er fremdeles + fargeverdiene som benyttes for å kalkulere kontrasten, men også om fargen er + tekst, grafikk, forgrunn eller bakgrunn, i tillegg har også valg av font, + font-vekt og størrelse en innvirkning på hvilke kontrastverdier som er + godkjent. Forskjellige farger som i WCAG 2 ville oppnådd like + kontrastverdier vil i APCA kunne få andre verdier fordi en i større grad + kalkulerer ut fra øyets evne til å oppfatte farger enn kun den tekniske + fargeverdien.
## Verktøy for å teste kontrastverdier @@ -186,11 +180,9 @@ I variant B er teksten svart, og bakgrunnen er farge #6D7879. Teksten er noe min

- - **Bidra til artikkelen?**
- Vi vil gjerne ha dine innspill og tilbakemeldinger på artikkelen. Send oss en - e-post på: designsystem@digdir.no eller [kontakt oss i Github](https://github.com/digdir/designsystemet/issues/new). -
+ **Bidra til artikkelen?**
+ Vi vil gjerne ha dine innspill og tilbakemeldinger på artikkelen. Send oss en + e-post på: designsystem@digdir.no eller [kontakt oss i Github](https://github.com/digdir/designsystemet/issues/new).
- Merk: Vi ønsker å holde oss oppdatert om andre anbefalinger om plassering, og har [pågående diskusjon om dette på Git](https://github.com/digdir/designsystemet/discussions/1684#discussioncomment-9339006). - -
### Når skal vi vise en feilmelding? @@ -244,12 +241,8 @@ Vi kan bruke disse aria-attributtene og rollene: - Vi setter `aria-invalid="true"` på felt med feil, for å si fra om at det er en feil der. - Vi bruker `aria-describedby` for å koble feilmelding til feltet. - - + Vi unngår inntill videre å bruke `aria-errormessage` da den ikke har full støtte av hjelpemidler per nå. Men vi kommer til å oppdatere retningslinjene om støtten blir bedre i fremtiden. [Se diskusjon på github](https://github.com/digdir/designsystemet/discussions/1684) - ### Gi automatiske beskjeder @@ -274,12 +267,8 @@ For feilmeldinger som dukker opp dynamisk må vi bruke `aria-live` for at meldin

- - - Retningslinjene er utarbeidet i en tverretatlig arbeidsgruppe med deltakere fra Digdir, Nav, Skatt, Brreg, Politiet, KS DIF og Oslo kommune. Du kan påvirke arbeidet i [Github](https://github.com/digdir/designsystemet/discussions/1684) eller i [#Mønster-kanalen](https://designsystemet.slack.com/archives/C05RBGB92MC/p1712751837722749) på [Slack](https://join.slack.com/t/designsystemet/shared_invite/zt-2438eotl3-a4266Vd2IeqMWO8TBw5PrQ). - + + Retningslinjene er utarbeidet i en tverretatlig arbeidsgruppe med deltakere fra Digdir, Nav, Skatt, Brreg, Politiet, KS DIF og Oslo kommune. Du kan påvirke arbeidet i [Github](https://github.com/digdir/designsystemet/discussions/1684) eller i [#Mønster-kanalen](https://designsystemet.slack.com/archives/C05RBGB92MC/p1712751837722749) på [Slack](https://join.slack.com/t/designsystemet/shared_invite/zt-2438eotl3-a4266Vd2IeqMWO8TBw5PrQ). - - *Retningslinjene er utarbeidet i en tverretatlig arbeidsgruppe med deltakere fra Digdir, Nav, Skatt, Brreg og Oslo Origo. Du kan påvirke arbeidet i [Github](https://github.com/digdir/designsystemet/issues/new) eller i [#Mønster-kanalen](https://designsystemet.slack.com/archives/C05RBGB92MC/p1712751837722749) på [Slack](https://join.slack.com/t/designsystemet/shared_invite/zt-2438eotl3-a4266Vd2IeqMWO8TBw5PrQ). - + *Retningslinjene er utarbeidet i en tverretatlig arbeidsgruppe med deltakere fra Digdir, Nav, Skatt, Brreg og Oslo Origo. Du kan påvirke arbeidet i [Github](https://github.com/digdir/designsystemet/issues/new) eller i [#Mønster-kanalen](https://designsystemet.slack.com/archives/C05RBGB92MC/p1712751837722749) på [Slack](https://join.slack.com/t/designsystemet/shared_invite/zt-2438eotl3-a4266Vd2IeqMWO8TBw5PrQ). diff --git a/apps/storefront/app/monstre/systemvarsler/page.mdx b/apps/storefront/app/monstre/systemvarsler/page.mdx index 12455b2c05..7ae721f7fd 100644 --- a/apps/storefront/app/monstre/systemvarsler/page.mdx +++ b/apps/storefront/app/monstre/systemvarsler/page.mdx @@ -18,12 +18,8 @@ export default ({ children }) => ( /> ); - - - *Retningslinjene er under arbeid fra 5. juni 2024 i en tverretatlig arbeidsgruppe med deltakere fra Digdir, Nav, Skatt, Brreg, Politiet, KS DIF og Oslo kommune. Alle er velkommen til å påvirke arbeidet i [Github](https://github.com/digdir/designsystemet/discussions/1801) eller i [#Mønster-kanalen](https://designsystemet.slack.com/archives/C05RBGB92MC/p1712751837722749) på [Slack](https://join.slack.com/t/designsystemet/shared_invite/zt-2438eotl3-a4266Vd2IeqMWO8TBw5PrQ). - + + *Retningslinjene er under arbeid fra 5. juni 2024 i en tverretatlig arbeidsgruppe med deltakere fra Digdir, Nav, Skatt, Brreg, Politiet, KS DIF og Oslo kommune. Alle er velkommen til å påvirke arbeidet i [Github](https://github.com/digdir/designsystemet/discussions/1801) eller i [#Mønster-kanalen](https://designsystemet.slack.com/archives/C05RBGB92MC/p1712751837722749) på [Slack](https://join.slack.com/t/designsystemet/shared_invite/zt-2438eotl3-a4266Vd2IeqMWO8TBw5PrQ). Systemvarsler brukes for å varsle brukeren enten om feil i systemet eller holde dem informert om viktige ting de bør få med seg. Vi bruker dem til feil som ikke tilhører et skjemaelement, og som ikke validerer brukerens inndata. De bør derfor ha et annet utseende enn [brukerutløste feil](/monstre/feilmeldinger). From 402749985c5e42fd0126fcd419cb7f4706a6fea8 Mon Sep 17 00:00:00 2001 From: eirikbacker Date: Wed, 25 Sep 2024 14:04:22 +0200 Subject: [PATCH 07/16] fix(Card): rename CardSection to CardPart --- .../app/bloggen/_components/Card/BlogCard.tsx | 10 ++-- packages/css/card.css | 8 +-- packages/react/src/components/Card/Card.mdx | 10 ++-- .../src/components/Card/Card.stories.tsx | 56 +++++++++---------- .../react/src/components/Card/Card.test.tsx | 14 ++--- packages/react/src/components/Card/Card.tsx | 8 +-- .../Card/{CardSection.tsx => CardPart.tsx} | 8 +-- packages/react/src/components/Card/index.ts | 10 ++-- 8 files changed, 62 insertions(+), 62 deletions(-) rename packages/react/src/components/Card/{CardSection.tsx => CardPart.tsx} (68%) diff --git a/apps/storefront/app/bloggen/_components/Card/BlogCard.tsx b/apps/storefront/app/bloggen/_components/Card/BlogCard.tsx index ac0a989cee..230da0ccdf 100644 --- a/apps/storefront/app/bloggen/_components/Card/BlogCard.tsx +++ b/apps/storefront/app/bloggen/_components/Card/BlogCard.tsx @@ -1,6 +1,6 @@ import { Card, - CardSection, + CardPart, Heading, Paragraph, Tag, @@ -43,10 +43,10 @@ export const BlogCard = ({ className={cl(classes.card, className)} {...props} > - + - - + + {tagText && ( {tagText} @@ -70,7 +70,7 @@ export const BlogCard = ({ ))} - + ); }; diff --git a/packages/css/card.css b/packages/css/card.css index 4d37fc19d6..27bdd672a2 100644 --- a/packages/css/card.css +++ b/packages/css/card.css @@ -97,7 +97,7 @@ } /* Usin :where to overwrite user agent CSS, but not our own CSS */ -:where(.ds-card, .ds-card__section) { +:where(.ds-card, .ds-card__part) { & > :first-child { margin-block: 0; } @@ -112,16 +112,16 @@ } } -.ds-card__section { +.ds-card__part { padding: var(--dsc-card-padding) var(--dsc-card-padding); margin: var(--dsc-card-padding) var(--dsc-card-padding-invert); :is(&, hr) + & { - margin-top: 0; /* No margin-top if previous element is hr or also ds-card__section */ + margin-top: 0; /* No margin-top if previous element is hr or also ds-card__part */ } &:has(+ &, + hr) { - margin-bottom: 0; /* No margin-bottom if next element is hr or also ds-card__section */ + margin-bottom: 0; /* No margin-bottom if next element is hr or also ds-card__part */ } &:first-child { diff --git a/packages/react/src/components/Card/Card.mdx b/packages/react/src/components/Card/Card.mdx index 87bc8c562d..fe2c3f57a5 100644 --- a/packages/react/src/components/Card/Card.mdx +++ b/packages/react/src/components/Card/Card.mdx @@ -16,9 +16,9 @@ Med `Card` kan vi fremheve informasjon eller oppgaver som hører sammen. Kortene ```tsx import { Card } from '@digdir/designsystemet-react'; - Tittel - Innhold - Valgfri fotnote + Tittel + Innhold + Valgfri fotnote ; ``` @@ -27,9 +27,9 @@ import { Card } from '@digdir/designsystemet-react'; ## Eksempler -`Card.Section` +`Card.Part` -Bruk`Card.Section` hvis du vi ha bilder eller video i kortene. +Bruk`Card.Part` hvis du vi ha bilder eller video i kortene. diff --git a/packages/react/src/components/Card/Card.stories.tsx b/packages/react/src/components/Card/Card.stories.tsx index 2b6971300b..945a25094c 100644 --- a/packages/react/src/components/Card/Card.stories.tsx +++ b/packages/react/src/components/Card/Card.stories.tsx @@ -49,9 +49,9 @@ export const LinkCard: Story = (args) => ( }} > - + - + ( Footer text - + - + = () => { }} > - + katt - + Card Neutral @@ -112,9 +112,9 @@ export const Variants: StoryFn = () => { - + katt - + Card Subtle @@ -125,9 +125,9 @@ export const Variants: StoryFn = () => { - + katter - + Card First @@ -138,9 +138,9 @@ export const Variants: StoryFn = () => { - + katt - + Card Second @@ -151,9 +151,9 @@ export const Variants: StoryFn = () => { - + katt - + Card Third @@ -176,9 +176,9 @@ export const Media: Story = () => ( }} > - + katt - + Card Neutral @@ -195,16 +195,16 @@ export const Media: Story = () => ( Most provide as with carried business are much better more the perfected designer. Writing slightly explain desk unable at supposedly about this - + katt - + ); export const Video: Story = () => ( - + - + ( - +
( Fjern
-
+ - + - +
); @@ -282,9 +282,9 @@ export const AsLink: Story = (args) => ( target='_blank' rel='noopener noreferrer' > - + - + Link Card @@ -302,9 +302,9 @@ export const AsLink: Story = (args) => ( target='_blank' rel='noopener noreferrer' > - + - + Link Card diff --git a/packages/react/src/components/Card/Card.test.tsx b/packages/react/src/components/Card/Card.test.tsx index 9cfc2baadc..78b2cf5851 100644 --- a/packages/react/src/components/Card/Card.test.tsx +++ b/packages/react/src/components/Card/Card.test.tsx @@ -2,12 +2,12 @@ import { render as renderRtl, screen } from '@testing-library/react'; import type { CardProps } from './Card'; import { Card } from './Card'; -import { CardSection } from './CardSection'; +import { CardPart } from './CardPart'; const renderCard = (props?: Partial) => renderRtl( - + , ); @@ -22,12 +22,12 @@ describe('Card Component', () => { renderRtl( - + cat - - - - + + + + , ); expect(screen.getByRole('img')).toHaveAttribute('src', mediaImage); diff --git a/packages/react/src/components/Card/Card.tsx b/packages/react/src/components/Card/Card.tsx index 7a819defd8..b6480af576 100644 --- a/packages/react/src/components/Card/Card.tsx +++ b/packages/react/src/components/Card/Card.tsx @@ -15,7 +15,7 @@ export type CardProps = { * @default false */ asChild?: boolean; - /** Instances of `Card.Section`, `Divider` or other React nodes */ + /** Instances of `Card.Part`, `Divider` or other React nodes */ children: ReactNode; } & HTMLAttributes; @@ -23,9 +23,9 @@ export type CardProps = { * Card component to present content in a structured way. * @example * - * Header - * Content - * Footer + * Header + * Content + * Footer * */ export const Card = forwardRef(function Card( diff --git a/packages/react/src/components/Card/CardSection.tsx b/packages/react/src/components/Card/CardPart.tsx similarity index 68% rename from packages/react/src/components/Card/CardSection.tsx rename to packages/react/src/components/Card/CardPart.tsx index cb3f7b10bb..1e9197bf93 100644 --- a/packages/react/src/components/Card/CardSection.tsx +++ b/packages/react/src/components/Card/CardPart.tsx @@ -3,7 +3,7 @@ import cl from 'clsx/lite'; import type { HTMLAttributes } from 'react'; import { forwardRef } from 'react'; -export type CardSectionProps = { +export type CardPartProps = { /** * Change the default rendered element for the one passed as a child, merging their props and behavior. * @default false @@ -11,13 +11,13 @@ export type CardSectionProps = { asChild?: boolean; } & HTMLAttributes; -export const CardSection = forwardRef( - function CardSection({ asChild, className, ...rest }, ref) { +export const CardPart = forwardRef( + function CardPart({ asChild, className, ...rest }, ref) { const Component = asChild ? Slot : 'div'; return ( diff --git a/packages/react/src/components/Card/index.ts b/packages/react/src/components/Card/index.ts index ec3f2f8364..482d86d6d2 100644 --- a/packages/react/src/components/Card/index.ts +++ b/packages/react/src/components/Card/index.ts @@ -1,12 +1,12 @@ import { Card as CardParent } from './Card'; -import { CardSection } from './CardSection'; +import { CardPart } from './CardPart'; const Card = Object.assign(CardParent, { - Section: CardSection, + Part: CardPart, }); -Card.Section.displayName = 'Card.Section'; +Card.Part.displayName = 'Card.Part'; export type { CardProps } from './Card'; -export type { CardSectionProps } from './CardSection'; -export { Card, CardSection }; +export type { CardPartProps } from './CardPart'; +export { Card, CardPart }; From 500bd85653bc28b374a3c0d541f2c3e07693b596 Mon Sep 17 00:00:00 2001 From: eirikbacker Date: Thu, 26 Sep 2024 13:04:03 +0200 Subject: [PATCH 08/16] fix(Card): rename Card.Part to Card.Block --- packages/css/card.css | 108 +++--- .../src/components/Card/Card.stories.tsx | 345 ++++++++++-------- .../react/src/components/Card/Card.test.tsx | 2 +- .../Card/{CardPart.tsx => CardBlock.tsx} | 8 +- packages/react/src/components/Card/index.ts | 10 +- 5 files changed, 247 insertions(+), 226 deletions(-) rename packages/react/src/components/Card/{CardPart.tsx => CardBlock.tsx} (69%) diff --git a/packages/css/card.css b/packages/css/card.css index 27bdd672a2..d623f25dcc 100644 --- a/packages/css/card.css +++ b/packages/css/card.css @@ -8,28 +8,24 @@ --dsc-card-padding: var(--ds-spacing-6); --dsc-card-gap: 1rem; - /* For internal use only */ - --dsc-card-padding-half: calc(var(--dsc-card-padding) / 2); - --dsc-card-padding-invert: calc(var(--dsc-card-padding) * -1); - --dsc-card-padding-width: calc(100% + var(--dsc-card-padding) * 2); - - @composes ds-paragraph from './baseline/typography.css'; - background: var(--dsc-card-background); border-radius: min(1rem, var(--ds-border-radius-md)); - border: 1px solid var(--dsc-card-border-color); - box-sizing: border-box; + border: 0; /* Reset if
- - - + + - + ); +export const WithLink: Story = (args) => ( + <> + + + + + + + + Link Card + + + + Most provide as with carried business are much better more the + perfected designer. Writing slightly explain desk unable at supposedly + about this + + Footer text + + + + + + Link Card + + + + Most provide as with carried business are much better more the perfected + designer. Writing slightly explain desk unable at supposedly about this + + Footer text + + +); + export const AsLink: Story = (args) => ( -
+ <> - + - + + + + Link Card + + + Most provide as with carried business are much better more the + perfected designer. Writing slightly explain desk unable at + supposedly about this + + Footer text + + + + + Link Card @@ -296,15 +323,31 @@ export const AsLink: Story = (args) => ( Footer text + +); + +export const AsButton: Story = (args) => ( + <> + + + - - - - + -
+ ); diff --git a/packages/react/src/components/Card/Card.test.tsx b/packages/react/src/components/Card/Card.test.tsx index 78b2cf5851..77ab073412 100644 --- a/packages/react/src/components/Card/Card.test.tsx +++ b/packages/react/src/components/Card/Card.test.tsx @@ -2,7 +2,7 @@ import { render as renderRtl, screen } from '@testing-library/react'; import type { CardProps } from './Card'; import { Card } from './Card'; -import { CardPart } from './CardPart'; +import { CardPart } from './CardBlock'; const renderCard = (props?: Partial) => renderRtl( diff --git a/packages/react/src/components/Card/CardPart.tsx b/packages/react/src/components/Card/CardBlock.tsx similarity index 69% rename from packages/react/src/components/Card/CardPart.tsx rename to packages/react/src/components/Card/CardBlock.tsx index 1e9197bf93..3ba32a49c0 100644 --- a/packages/react/src/components/Card/CardPart.tsx +++ b/packages/react/src/components/Card/CardBlock.tsx @@ -3,7 +3,7 @@ import cl from 'clsx/lite'; import type { HTMLAttributes } from 'react'; import { forwardRef } from 'react'; -export type CardPartProps = { +export type CardBlockProps = { /** * Change the default rendered element for the one passed as a child, merging their props and behavior. * @default false @@ -11,13 +11,13 @@ export type CardPartProps = { asChild?: boolean; } & HTMLAttributes; -export const CardPart = forwardRef( - function CardPart({ asChild, className, ...rest }, ref) { +export const CardBlock = forwardRef( + function CardBlock({ asChild, className, ...rest }, ref) { const Component = asChild ? Slot : 'div'; return ( diff --git a/packages/react/src/components/Card/index.ts b/packages/react/src/components/Card/index.ts index 482d86d6d2..0a7568f090 100644 --- a/packages/react/src/components/Card/index.ts +++ b/packages/react/src/components/Card/index.ts @@ -1,12 +1,12 @@ import { Card as CardParent } from './Card'; -import { CardPart } from './CardPart'; +import { CardBlock } from './CardBlock'; const Card = Object.assign(CardParent, { - Part: CardPart, + Block: CardBlock, }); -Card.Part.displayName = 'Card.Part'; +Card.Block.displayName = 'Card.Block'; export type { CardProps } from './Card'; -export type { CardPartProps } from './CardPart'; -export { Card, CardPart }; +export type { CardBlockProps } from './CardBlock'; +export { Card, CardBlock }; From 242d064cfa04e939781485a3cb00e0809b11e9e9 Mon Sep 17 00:00:00 2001 From: eirikbacker Date: Thu, 26 Sep 2024 15:13:14 +0200 Subject: [PATCH 09/16] fix(Card): allow Card.Block in both directions --- .../_components/Card/BlogCard.module.css | 9 -- .../app/bloggen/_components/Card/BlogCard.tsx | 10 +- packages/css/card.css | 116 +++++++------- packages/react/src/components/Card/Card.mdx | 14 +- .../src/components/Card/Card.stories.tsx | 145 +++++++++++++----- .../react/src/components/Card/Card.test.tsx | 14 +- packages/react/src/components/Card/Card.tsx | 8 +- 7 files changed, 182 insertions(+), 134 deletions(-) diff --git a/apps/storefront/app/bloggen/_components/Card/BlogCard.module.css b/apps/storefront/app/bloggen/_components/Card/BlogCard.module.css index 3da6a3570a..e251f12e28 100644 --- a/apps/storefront/app/bloggen/_components/Card/BlogCard.module.css +++ b/apps/storefront/app/bloggen/_components/Card/BlogCard.module.css @@ -8,16 +8,7 @@ grid-template-columns: 1fr 1fr; } - .card[data-featured='true'] > * { - margin: var(--dsc-card-padding-invert); - } - - .card[data-featured='true'] > :first-child { - margin-right: 0; - } - .card[data-featured='true'] > :last-child { - margin-left: 0; display: flex; flex-direction: column; justify-content: center; diff --git a/apps/storefront/app/bloggen/_components/Card/BlogCard.tsx b/apps/storefront/app/bloggen/_components/Card/BlogCard.tsx index 230da0ccdf..066a80af59 100644 --- a/apps/storefront/app/bloggen/_components/Card/BlogCard.tsx +++ b/apps/storefront/app/bloggen/_components/Card/BlogCard.tsx @@ -1,6 +1,6 @@ import { Card, - CardPart, + CardBlock, Heading, Paragraph, Tag, @@ -43,10 +43,10 @@ export const BlogCard = ({ className={cl(classes.card, className)} {...props} > - + - - + + {tagText && ( {tagText} @@ -70,7 +70,7 @@ export const BlogCard = ({ ))} - + ); }; diff --git a/packages/css/card.css b/packages/css/card.css index d623f25dcc..634eebad8f 100644 --- a/packages/css/card.css +++ b/packages/css/card.css @@ -1,27 +1,23 @@ .ds-card { - --dsc-card-border-color: var(--ds-color-neutral-border-subtle); - --dsc-card-border-color--link: var(--ds-color-neutral-border-subtle); - --dsc-card-background: var(--ds-color-neutral-background-default); --dsc-card-background--active: var(--ds-color-neutral-surface-default); --dsc-card-background--hover: var(--ds-color-neutral-background-subtle); + --dsc-card-background: var(--ds-color-neutral-background-default); + --dsc-card-border-color: var(--ds-color-neutral-border-subtle); + --dsc-card-border-width: 1px; --dsc-card-color: var(--ds-color-neutral-text-default); - --dsc-card-padding: var(--ds-spacing-6); --dsc-card-gap: 1rem; + --dsc-card-padding: var(--ds-spacing-6); + all: unset; /* Reset if + ); export const WithLink: Story = (args) => ( <> + + I dette eksempelet rendrer Card med <a> (lenke) inni + tittel elementet. Dette er nyttig når Card inneholder tekst eller media, + og skal navigere til en annen side. + @@ -264,45 +278,59 @@ export const WithLink: Story = (args) => ( - - - Link Card - - - - Most provide as with carried business are much better more the perfected - designer. Writing slightly explain desk unable at supposedly about this - - Footer text + + + + Link Card + + + + Most provide as with carried business are much better more the + perfected designer. Writing slightly explain desk unable at supposedly + about this + + Footer text + + + + ); export const AsLink: Story = (args) => ( <> + + I dette eksempelet rendrer Card som <a> (lenke). Dette + er nyttig når Card inneholder lite tekst, og skal navigere til en annen + side. + - - - - Link Card + Link Card with blocks + + Most provide as with carried business are much better more the - perfected designer. Writing slightly explain desk unable at - supposedly about this + perfected designer. - Footer text @@ -317,10 +345,8 @@ export const AsLink: Story = (args) => ( Most provide as with carried business are much better more the - perfected designer. Writing slightly explain desk unable at supposedly - about this + perfected designer. - Footer text @@ -328,21 +354,29 @@ export const AsLink: Story = (args) => ( export const AsButton: Story = (args) => ( <> + + I dette eksempelet rendrer Card som <button>. Dette er + nyttig når Card inneholder lite tekst, og skal åpne en Modal eller utføre + annen handling på samme side. + @@ -353,11 +387,38 @@ export const AsButton: Story = (args) => ( Most provide as with carried business are much better more the - perfected designer. Writing slightly explain desk unable at supposedly - about this + perfected designer. - Footer text ); + +export const AsGrid: Story = (args) => ( +
+ + I dette eksempelet har Card fått display: grid for å legge + Card.Block ved siden av hverandre. + +
+ + + + Button Card with blocks + + + + + Most provide as with carried business are much better more the + perfected designer. + + + +
+); diff --git a/packages/react/src/components/Card/Card.test.tsx b/packages/react/src/components/Card/Card.test.tsx index 77ab073412..99c5a82127 100644 --- a/packages/react/src/components/Card/Card.test.tsx +++ b/packages/react/src/components/Card/Card.test.tsx @@ -2,12 +2,12 @@ import { render as renderRtl, screen } from '@testing-library/react'; import type { CardProps } from './Card'; import { Card } from './Card'; -import { CardPart } from './CardBlock'; +import { CardBlock } from './CardBlock'; const renderCard = (props?: Partial) => renderRtl( - + , ); @@ -22,12 +22,12 @@ describe('Card Component', () => { renderRtl( - + cat - - - - + + + + , ); expect(screen.getByRole('img')).toHaveAttribute('src', mediaImage); diff --git a/packages/react/src/components/Card/Card.tsx b/packages/react/src/components/Card/Card.tsx index b6480af576..fdfdd395ce 100644 --- a/packages/react/src/components/Card/Card.tsx +++ b/packages/react/src/components/Card/Card.tsx @@ -15,7 +15,7 @@ export type CardProps = { * @default false */ asChild?: boolean; - /** Instances of `Card.Part`, `Divider` or other React nodes */ + /** Instances of `Card.Block`, `Divider` or other React nodes */ children: ReactNode; } & HTMLAttributes; @@ -23,9 +23,9 @@ export type CardProps = { * Card component to present content in a structured way. * @example * - * Header - * Content - * Footer + * Header + * Content + * Footer * */ export const Card = forwardRef(function Card( From 409aa063d88e68db36ba8b64f7b661deec78588b Mon Sep 17 00:00:00 2001 From: eirikbacker Date: Thu, 26 Sep 2024 15:39:42 +0200 Subject: [PATCH 10/16] fix(Card): border between Card.Block elements --- packages/css/card.css | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/packages/css/card.css b/packages/css/card.css index 634eebad8f..63a2ba6909 100644 --- a/packages/css/card.css +++ b/packages/css/card.css @@ -3,7 +3,7 @@ --dsc-card-background--hover: var(--ds-color-neutral-background-subtle); --dsc-card-background: var(--ds-color-neutral-background-default); --dsc-card-border-color: var(--ds-color-neutral-border-subtle); - --dsc-card-border-width: 1px; + --dsc-card-border: 1px solid var(--dsc-card-border-color); --dsc-card-color: var(--ds-color-neutral-text-default); --dsc-card-gap: 1rem; --dsc-card-padding: var(--ds-spacing-6); @@ -11,10 +11,10 @@ all: unset; /* Reset if + + + + + + + + + - - - - - - - - - - - + + + + + katt + + + + Card Neutral + + + Most provide as with carried business are much better more the + perfected designer. Writing slightly explain desk unable at supposedly + about this. + + + + ); export const WithLink: Story = (args) => ( From 48ca36a30d789c9b22430a890fb412365011ac14 Mon Sep 17 00:00:00 2001 From: eirikbacker Date: Mon, 30 Sep 2024 17:37:33 +0200 Subject: [PATCH 15/16] fix(Card): move docs to mdx --- packages/css/card.css | 4 +- packages/react/src/components/Card/Card.mdx | 15 +++- .../src/components/Card/Card.stories.tsx | 72 ++++--------------- 3 files changed, 28 insertions(+), 63 deletions(-) diff --git a/packages/css/card.css b/packages/css/card.css index bc2a10353b..299498bc50 100644 --- a/packages/css/card.css +++ b/packages/css/card.css @@ -37,7 +37,7 @@ @media (hover: hover) and (pointer: fine) { &:hover { - --dsc-card-background: var(--dsc-card-background--hover); + background: var(--dsc-card-background--hover); } } @@ -47,7 +47,7 @@ } &:active { - --dsc-card-background: var(--dsc-card-background--active); + background: var(--dsc-card-background--active); } } diff --git a/packages/react/src/components/Card/Card.mdx b/packages/react/src/components/Card/Card.mdx index 6fb294d5b8..3d8ad2e4cc 100644 --- a/packages/react/src/components/Card/Card.mdx +++ b/packages/react/src/components/Card/Card.mdx @@ -37,7 +37,7 @@ Merk at innhold kan ikke plasseres direkte i `Card` dersom du bruker `Card.Block -### Link Card +### Klikkbart - `Card` kan brukes som navigasjonskort for å ta brukerne videre til en annen side. - Dersom kortet skal lenke til en annen side, kan du legge en lenke inn i kortets tittel. Hele kortet blir da automatisk klikkbart, men skjermlesere får en [bedre brukeropplevelse enn dersom hele kortet var en lenke](https://adrianroselli.com/2020/02/block-links-cards-clickable-regions-etc.html). - Dersom kortet kun innholder litt tekst, kan hele kortet bli en lenke eller knapp ved å benytte `asChild`. @@ -46,14 +46,26 @@ Merk at innhold kan ikke plasseres direkte i `Card` dersom du bruker `Card.Block
#### Kort med lenke i tittel: +I dette eksempelet rendrer Card med lenke `` inni tittel elementet. Dette er nyttig når Card inneholder tekst eller media, og skal navigere til en annen side. + #### Kort som er en lenke: +I dette eksempelet rendrer Card som lenke ``. Dette er nyttig når Card inneholder lite tekst, og skal navigere til en annen side. + #### Kort som er en knapp: + +I dette eksempelet rendrer Card som knapp `