From 2b14e9606a8d924d3fb99dce77a1d2c551020ac4 Mon Sep 17 00:00:00 2001 From: Eirik Backer Date: Tue, 26 Nov 2024 14:50:38 +0100 Subject: [PATCH] fix(Accordion): rename to details (#2824) - Fixes #2364 - `data-color` throws an type error in `showcase.tsx` but this is not related to this branch - Color of details/cards will be adjusted by design, but they wanted to move forward with the currently implemented logic for now --------- Co-authored-by: Tobias Barsnes --- .../_components/src/ColorModal/ColorModal.tsx | 16 +-- apps/_components/src/Showcase/Showcase.tsx | 42 +++--- .../app/bloggen/2024/v1rc1/page.mdx | 2 +- .../app/komponenter/component-list.ts | 6 +- .../app/monstre/feilmeldinger/page.mdx | 22 +-- .../MdxContent/MdxContent.module.css | 4 +- .../{Accordion.svg => Details.svg} | 0 packages/cli/src/migrations/beta-to-v1.ts | 2 +- packages/css/src/accordion.css | 129 ----------------- packages/css/src/card.css | 9 +- packages/css/src/details.css | 108 ++++++++++++++ packages/css/src/index.css | 2 +- .../src/components/Accordion/Accordion.mdx | 131 ----------------- .../components/Accordion/Accordion.test.tsx | 80 ----------- .../src/components/Accordion/Accordion.tsx | 44 ------ .../components/Accordion/AccordionContent.tsx | 16 --- .../react/src/components/Accordion/index.ts | 36 ----- .../src/components/Card/Card.stories.tsx | 50 ++++++- .../react/src/components/Details/Details.mdx | 120 ++++++++++++++++ .../Details.stories.tsx} | 136 ++++++++---------- .../src/components/Details/Details.test.tsx | 77 ++++++++++ .../AccordionItem.tsx => Details/Details.tsx} | 24 ++-- .../src/components/Details/DetailsContent.tsx | 15 ++ .../DetailsSummary.tsx} | 10 +- .../react/src/components/Details/index.ts | 24 ++++ packages/react/src/components/index.ts | 2 +- packages/react/stories/bruk.mdx | 40 +++--- packages/react/stories/testing.stories.tsx | 18 +-- 28 files changed, 549 insertions(+), 616 deletions(-) rename apps/storefront/public/img/component-previews/{Accordion.svg => Details.svg} (100%) delete mode 100644 packages/css/src/accordion.css create mode 100644 packages/css/src/details.css delete mode 100644 packages/react/src/components/Accordion/Accordion.mdx delete mode 100644 packages/react/src/components/Accordion/Accordion.test.tsx delete mode 100644 packages/react/src/components/Accordion/Accordion.tsx delete mode 100644 packages/react/src/components/Accordion/AccordionContent.tsx delete mode 100644 packages/react/src/components/Accordion/index.ts create mode 100644 packages/react/src/components/Details/Details.mdx rename packages/react/src/components/{Accordion/Accordion.stories.tsx => Details/Details.stories.tsx} (66%) create mode 100644 packages/react/src/components/Details/Details.test.tsx rename packages/react/src/components/{Accordion/AccordionItem.tsx => Details/Details.tsx} (73%) create mode 100644 packages/react/src/components/Details/DetailsContent.tsx rename packages/react/src/components/{Accordion/AccordionHeading.tsx => Details/DetailsSummary.tsx} (51%) create mode 100644 packages/react/src/components/Details/index.ts diff --git a/apps/_components/src/ColorModal/ColorModal.tsx b/apps/_components/src/ColorModal/ColorModal.tsx index e6707a42c0..eb561e000a 100644 --- a/apps/_components/src/ColorModal/ColorModal.tsx +++ b/apps/_components/src/ColorModal/ColorModal.tsx @@ -97,25 +97,25 @@ export const ColorModal = ({
- {/* - - + Vis kontrastgrenser mot relevante farger - - + + - - - */} + + + */} ); diff --git a/apps/_components/src/Showcase/Showcase.tsx b/apps/_components/src/Showcase/Showcase.tsx index 79d7c1d713..be943da93e 100644 --- a/apps/_components/src/Showcase/Showcase.tsx +++ b/apps/_components/src/Showcase/Showcase.tsx @@ -1,11 +1,11 @@ 'use client'; import { - Accordion, Avatar, Button, Card, Checkbox, Combobox, + Details, Divider, Fieldset, Heading, @@ -280,40 +280,40 @@ export function Showcase({ className, ...props }: ShowcaseProps) {
Ofte stillte spørsmål - - - + +
+ Hvem kan registrere seg i Frivillighetsregisteret? - - + + For å kunne bli registrert i Frivillighetsregisteret, må organisasjonen drive frivillig virksomhet. Det er bare foreninger, stiftelser og aksjeselskap som kan registreres. Virksomheten kan ikke dele ut midler til fysiske personer. Virksomheten må ha et styre. - - - - + +
+
+ Hvordan går jeg fram for å registrere i Frivillighetsregisteret? - - + + Virksomheten må være registrert i Enhetsregisteret før den kan bli registrert i Frivillighetsregisteret. Du kan registrere i begge registrene samtidig i Samordnet registermelding. - - - - + +
+
+ Hvordan går jeg fram for å registrere i Frivillighetsregisteret? - - + + Virksomheten må være registrert i Enhetsregisteret før den kan bli registrert i Frivillighetsregisteret. Du kan registrere i begge registrene samtidig i Samordnet registermelding. - - - + +
+
); diff --git a/apps/storefront/app/bloggen/2024/v1rc1/page.mdx b/apps/storefront/app/bloggen/2024/v1rc1/page.mdx index 00db28fd12..78fad43b5f 100644 --- a/apps/storefront/app/bloggen/2024/v1rc1/page.mdx +++ b/apps/storefront/app/bloggen/2024/v1rc1/page.mdx @@ -98,7 +98,7 @@ Denne installerer alle tre pakken, og inneholder tokens, CSS og React komponente Denne kan legges hvor som helst, og endrer alle barn til modusen du har valgt. - {`...`} + {`
...
`}
#### Design-tokens templat diff --git a/apps/storefront/app/komponenter/component-list.ts b/apps/storefront/app/komponenter/component-list.ts index 0fa3f662c3..6903be3bf0 100644 --- a/apps/storefront/app/komponenter/component-list.ts +++ b/apps/storefront/app/komponenter/component-list.ts @@ -1,8 +1,8 @@ export const data = [ { - title: 'Accordion', - image: 'Accordion.svg', - url: 'https://storybook.designsystemet.no/?path=/docs/komponenter-accordion--docs', + title: 'Details', + image: 'Details.svg', + url: 'https://storybook.designsystemet.no/?path=/docs/komponenter-details--docs', }, { title: 'Alert', diff --git a/apps/storefront/app/monstre/feilmeldinger/page.mdx b/apps/storefront/app/monstre/feilmeldinger/page.mdx index d7ec70abe0..ac966b551d 100644 --- a/apps/storefront/app/monstre/feilmeldinger/page.mdx +++ b/apps/storefront/app/monstre/feilmeldinger/page.mdx @@ -3,10 +3,10 @@ import { CardContent, Heading, Paragraph, - Accordion, - AccordionItem, - AccordionContent, - AccordionHeading + Details, + DetailsItem, + DetailsContent, + DetailsSummary } from '@digdir/designsystemet-react'; import { Image } from '@components'; @@ -184,12 +184,12 @@ Her må vi gjøre det så tydelig som mulig for brukeren at flere felt påvirker I dette eksempelet har vi en gruppe med felt, der brukeren ikke nødvendigvis har alle opplysningene, men må fylle ut minst ett felt. - - - Eksempel på feilmelding som gjelder flere felt - + Eksempel på feilmelding som gjelder flere felt + - - - + + + ## Kode diff --git a/apps/storefront/components/MdxContent/MdxContent.module.css b/apps/storefront/components/MdxContent/MdxContent.module.css index 8a18e0c531..5969fbe527 100644 --- a/apps/storefront/components/MdxContent/MdxContent.module.css +++ b/apps/storefront/components/MdxContent/MdxContent.module.css @@ -148,7 +148,7 @@ & :not([data-unstyled]) { &:is(p, h2, h3, h4, ul, ol), - &[class~='ds-accordion'], + &[class~='ds-accordion'] /* TODO: EIRIK */, &[class~='ds-card'] { max-width: 740px; } @@ -175,7 +175,7 @@ & h4, & ul, & ol, - & [class~='ds-accordion'], + & [class~='ds-accordion'] /* TODO: EIRIK */, & [class~='ds-card'] { max-width: unset; } diff --git a/apps/storefront/public/img/component-previews/Accordion.svg b/apps/storefront/public/img/component-previews/Details.svg similarity index 100% rename from apps/storefront/public/img/component-previews/Accordion.svg rename to apps/storefront/public/img/component-previews/Details.svg diff --git a/packages/cli/src/migrations/beta-to-v1.ts b/packages/cli/src/migrations/beta-to-v1.ts index e027754c4a..296845da4f 100644 --- a/packages/cli/src/migrations/beta-to-v1.ts +++ b/packages/cli/src/migrations/beta-to-v1.ts @@ -10,7 +10,7 @@ export default (glob?: string) => }), // New component token prefixes cssVarRename({ - '--fds-accordion': '--dsc-accordion', + '--fds-accordion': '--dsc-accordion' /* TODO: EIRIK */, '--fds-alert': '--dsc-alert', '--fds-btn': '--dsc-btn', '--fds-checkbox': '--dsc-checkbox', diff --git a/packages/css/src/accordion.css b/packages/css/src/accordion.css deleted file mode 100644 index db86d286fa..0000000000 --- a/packages/css/src/accordion.css +++ /dev/null @@ -1,129 +0,0 @@ -.ds-accordion-group { - /* default color: neutral */ - --dsc-accordion-background: var(--ds-color-neutral-background-default); - --dsc-accordion-heading-background--hover: var(--ds-color-neutral-surface-default); - --dsc-accordion-heading-background--open: var(--ds-color-neutral-background-subtle); - --dsc-accordion-heading-background: var(--ds-color-neutral-background-default); - --dsc-accordion-border-color: var(--ds-color-neutral-border-subtle); - - &[data-color]:where(:not([data-color='subtle'])) { - --dsc-accordion-background: var(--ds-color-background-subtle); - --dsc-accordion-heading-background--hover: var(--ds-color-surface-hover); - --dsc-accordion-heading-background--open: var(--ds-color-surface-default); - --dsc-accordion-heading-background: var(--ds-color-surface-default); - --dsc-accordion-border-color: var(--ds-color-border-subtle); - } - - &[data-color='neutral'] { - --dsc-accordion-background: var(--ds-color-background-default); - --dsc-accordion-heading-background--hover: var(--ds-color-surface-default); - --dsc-accordion-heading-background--open: var(--ds-color-background-subtle); - --dsc-accordion-heading-background: var(--ds-color-background-default); - } - - &[data-color='subtle'] { - --dsc-accordion-background: var(--ds-color-neutral-background-subtle); - --dsc-accordion-heading-background--hover: var(--ds-color-neutral-surface-hover); - --dsc-accordion-heading-background--open: var(--ds-color-neutral-surface-default); - --dsc-accordion-heading-background: var(--ds-color-neutral-background-subtle); - } - - --dsc-accordion-border: 1px solid var(--dsc-accordion-border-color); - --dsc-accordion-border-radius: var(--ds-border-radius-md); - --dsc-accordion-chevron-gap: var(--ds-spacing-2); - --dsc-accordion-chevron-size: var(--ds-spacing-6); - --dsc-accordion-chevron-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5.97 9.47a.75.75 0 0 1 1.06 0L12 14.44l4.97-4.97a.75.75 0 1 1 1.06 1.06l-5.5 5.5a.75.75 0 0 1-1.06 0l-5.5-5.5a.75.75 0 0 1 0-1.06'/%3E%3C/svg%3E"); - - --dsc-accordion-padding: var(--ds-spacing-2) var(--ds-spacing-4); - --dsc-accordion-size: var(--ds-sizing-14); - - &[data-border] > * { - border: var(--dsc-accordion-border); - - &:first-child, - &:first-child > :is(summary, u-summary) { - border-top-left-radius: var(--dsc-accordion-border-radius); - border-top-right-radius: var(--dsc-accordion-border-radius); - } - - &:last-child, - &:last-child:not([open]) > :is(summary, u-summary) { - border-bottom-left-radius: var(--dsc-accordion-border-radius); - border-bottom-right-radius: var(--dsc-accordion-border-radius); - } - } -} - -.ds-accordion__item { - background: var(--dsc-accordion-background); - border-block: var(--dsc-accordion-border); - box-sizing: border-box; - - & > :is(summary, u-summary) { - align-items: center; - background: var(--dsc-accordion-heading-background); - box-sizing: border-box; - cursor: pointer; - display: flex; - list-style: none; - min-height: var(--dsc-accordion-size); - gap: var(--dsc-accordion-chevron-gap); - outline: none; - padding: var(--dsc-accordion-padding); - position: relative; - - @composes ds-focus from './base.css'; - - &:focus-visible { - position: relative; /* Ensure foucs outline renders on top */ - } - - &::before { - background: currentcolor; - border-radius: var(--ds-border-radius-md); - content: ''; - flex-shrink: 0; - height: var(--dsc-accordion-chevron-size); - mask: 50% / contain no-repeat var(--dsc-accordion-chevron-url); - width: var(--dsc-accordion-chevron-size); - } - } - - & + & { - border-top: 0; /* Skip border-top when .accordion__item is followed by .accordion__item */ - } - - & > :not(summary, u-summary) { - border-radius: inherit; - padding: var(--ds-spacing-5, 1rem); - } - - &[open] > :is(summary, u-summary) { - background: var(--dsc-accordion-heading-background--open); - - &::before { - rotate: 180deg; - } - } - - @media (hover: hover) and (pointer: fine) { - & > :is(summary, u-summary):hover { - background: var(--dsc-accordion-heading-background--hover); - } - } - - @media (prefers-reduced-motion: no-preference) { - /* biome-ignore lint/correctness/noUnknownProperty: biome does not know about this property yet */ - interpolate-size: allow-keywords; - } - - &::part(details-content) { - block-size: 0; - overflow-y: clip; - transition: content-visibility 400ms allow-discrete, height 400ms; - } - - &[open]::part(details-content) { - height: auto; - } -} diff --git a/packages/css/src/card.css b/packages/css/src/card.css index ff4d6d94b7..19b2590339 100644 --- a/packages/css/src/card.css +++ b/packages/css/src/card.css @@ -71,9 +71,16 @@ } } - &:has(> .ds-card__block) { + &:has(> .ds-card__block, .ds-details) { padding: 0; /* Let Card.Block own the padding */ } + + & > .ds-details:first-child { + border-top: 0; + } + & > .ds-details:last-child { + border-bottom: 0; + } } /* Using :where to overwrite user agent CSS, but not our own CSS */ diff --git a/packages/css/src/details.css b/packages/css/src/details.css new file mode 100644 index 0000000000..3ff48a3eb3 --- /dev/null +++ b/packages/css/src/details.css @@ -0,0 +1,108 @@ +.ds-details { + --dsc-details-border: 1px solid var(--dsc-details-border-color); + --dsc-details-chevron-gap: var(--ds-spacing-2); + --dsc-details-chevron-size: var(--ds-spacing-6); + --dsc-details-chevron-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5.97 9.47a.75.75 0 0 1 1.06 0L12 14.44l4.97-4.97a.75.75 0 1 1 1.06 1.06l-5.5 5.5a.75.75 0 0 1-1.06 0l-5.5-5.5a.75.75 0 0 1 0-1.06'/%3E%3C/svg%3E"); + --dsc-details-padding: var(--ds-spacing-2) var(--ds-spacing-4); + --dsc-details-size: var(--ds-sizing-14); + + /* default color: neutral */ + --dsc-details-heading-background--hover: var(--ds-color-neutral-surface-default); + --dsc-details-heading-background--open: var(--ds-color-neutral-background-subtle); + --dsc-details-heading-background: var(--ds-color-neutral-background-default); + --dsc-details-border-color: var(--ds-color-neutral-border-subtle); + + /* with color */ + [data-color]:where(:not([data-color='neutral'])) &, + &[data-color]:where(:not([data-color='neutral'])) { + --dsc-details-background: var(--ds-color-background-subtle); + --dsc-details-heading-background--hover: var(--ds-color-surface-hover); + --dsc-details-heading-background--open: var(--ds-color-surface-default); + --dsc-details-heading-background: var(--ds-color-surface-default); + --dsc-details-border-color: var(--ds-color-border-subtle); + } + + /* with subtle */ + [data-color='subtle'] &, + &[data-color='subtle'] { + --dsc-details-background: var(--ds-color-neutral-background-subtle); + --dsc-details-heading-background--hover: var(--ds-color-neutral-surface-hover); + --dsc-details-heading-background--open: var(--ds-color-neutral-surface-default); + --dsc-details-heading-background: var(--ds-color-neutral-background-subtle); + --dsc-details-border-color: var(--ds-color-neutral-border-subtle); + } + + background: var(--dsc-details-background); + border-block: var(--dsc-details-border); + box-sizing: border-box; + + & > :is(summary, u-summary) { + align-items: center; + background: var(--dsc-details-heading-background); + box-sizing: border-box; + cursor: pointer; + display: flex; + list-style: none; + min-height: var(--dsc-details-size); + gap: var(--dsc-details-chevron-gap); + outline: none; + padding: var(--dsc-details-padding); + position: relative; + + /* Render focus inside so it is easier to make full window width and place in overflow: hidden containers */ + &:focus-visible { + box-shadow: inset 0 0 0 var(--dsc-focus-border-width) var(--ds-color-focus-outer); + outline: var(--ds-color-focus-inner) solid var(--dsc-focus-border-width); + outline-offset: calc(var(--dsc-focus-border-width) * -2); + } + + &::before { + background: currentcolor; + border-radius: var(--ds-border-radius-md); + content: ''; + flex-shrink: 0; + height: var(--dsc-details-chevron-size); + mask: 50% / contain no-repeat var(--dsc-details-chevron-url); + width: var(--dsc-details-chevron-size); + } + } + + & + & { + border-top: 0; /* Skip border-top when .ds-details is followed by .ds-details */ + margin-top: 0; /* Prevent gap when places as child of .ds-card */ + } + + & > :not(summary, u-summary) { + border-radius: inherit; + padding: var(--ds-spacing-5, 1rem); + } + + &[open] > :is(summary, u-summary) { + background: var(--dsc-details-heading-background--open); + + &::before { + rotate: 180deg; + } + } + + @media (hover: hover) and (pointer: fine) { + & > :is(summary, u-summary):hover { + background: var(--dsc-details-heading-background--hover); + } + } + + @media (prefers-reduced-motion: no-preference) { + /* biome-ignore lint/correctness/noUnknownProperty: biome does not know about this property yet */ + interpolate-size: allow-keywords; + } + + &::part(details-content) { + block-size: 0; + overflow-y: clip; + transition: content-visibility 400ms allow-discrete, height 400ms; + } + + &[open]::part(details-content) { + height: auto; + } +} diff --git a/packages/css/src/index.css b/packages/css/src/index.css index 1173337da8..590bdb88d3 100644 --- a/packages/css/src/index.css +++ b/packages/css/src/index.css @@ -14,7 +14,7 @@ @import url('./alert.css') layer(ds.components); @import url('./popover.css') layer(ds.components); @import url('./skiplink.css') layer(ds.components); -@import url('./accordion.css') layer(ds.components); +@import url('./details.css') layer(ds.components); @import url('./search.css') layer(ds.components); @import url('./textfield.css') layer(ds.components); @import url('./helptext.css') layer(ds.components); diff --git a/packages/react/src/components/Accordion/Accordion.mdx b/packages/react/src/components/Accordion/Accordion.mdx deleted file mode 100644 index b8e34606d4..0000000000 --- a/packages/react/src/components/Accordion/Accordion.mdx +++ /dev/null @@ -1,131 +0,0 @@ -import { Meta, Canvas, Controls, Primary, ArgTypes } from '@storybook/blocks'; -import { CssVariables } from '@doc-components'; - -import * as AccordionStories from './Accordion.stories'; - -import { Accordion } from '.'; -import css from '@digdir/designsystemet-css/accordion.css?inline'; - - - -# Accordion - -Med `Accordion` kan du presentere mye innhold på liten plass i en eller flere rader. Hele raden er klikkbar og lar brukere åpne eller lukke visningen av innholdet under. - -**Vær oppmerksom på:** - -- Ved å legge innhold i `Accordion` risikerer du at det ikke blir sett av brukerne. Innhold som er viktig bør _ikke_ skjules. -- Ikke legg en `Accordion` inni en annen. - -
- - - - -## Bruk - -```tsx -import { Accordion } from '@digdir/designsystemet-react'; - - - - Accordion heading text - Accordion content - - - Accordion heading text - Accordion content - -; -``` - -## Eksempler - -
-### Med ramme - -`Accordion` kan vises med ramme. Dette kan passe i tilfeller der accordions ikke fyller hele siden, eller når det kun er en rad. - - - -### Med farger - -`Accordion` kan vises i farger fra ditt brand. - - - -#### Kontrollert - -`Accordion` har egen tilstand på åpen/lukker, men dette kan kontrolleres utenfra. - - - -
- -## Retningslinjer - -Tester viser at brukerne sjeldnere ser på skjult innhold, enn det som er synlig direkte på siden. Ikke bruk `Accordion` til å skjule innhold for å gjøre siden "ryddigere". Finn ut om du faktisk må skjule innhold og vær klar over hvorfor du gjør det. Tenk over om det er lurt å vise det viktigste innholdet i åpen status når brukeren kommer inn på siden. - -Hvis innholdet er for langt eller komplisert, bør du heller omformulere teksten og/eller eventuelt fordele den på flere sider. - -### Egnet til - -- samle innhold som er litt lengre -- gjøre det frivillig å se innhold som er litt mindre viktig enn alltid synlig innhold -- vise ofte stilte spørsmål -- vise tilleggsinformasjon som kan være til hjelp for brukerne - -### Ikke egnet til - -- vise små mengder innhold -- vise informasjon hvis det bare er ett element -- vise viktig innhold som alle bør se når de kommer til siden (for eksempel feilmeldinger) -- gi mer informasjon om et spørsmål i et skjema – det innholdet bør brukeren se med en gang -- velge mellom ulike alternativer -- skjule innhold fra søkeresultater eller oversikter/tabeller -- dele opp en logisk flyt eller en rekke med handlinger, da bør du heller bruke en trinnvis liste - -### Unngå - -- Ikke legg en `Accordion` inni en annen, det vi kaller nøstede lister. - -
- -## Tekst i komponenten - -Accordion skal brukes til maksimalt to avsnitt innenfor hvert nedtrekk. Sørg for at overskriften gir en god beskrivelse av hva innholdet i accordion er. En tydelig og beskrivende overskrift skal gjøre brukerne nysgjerrige på innholdet. Overskriftene til accordion kan ha stor betydning for om brukerne finner det de trenger, om innholdet blir lest og om det kan regnes som tilgjengelig for alle brukere. «Vis mer» eller «Les mer her» er ikke gode nok titler. Har du en accordion med mange nedtrekk, kan du ha en hovedoverskrift eller temaoverskrift over hele listen. - -
- -## Tilgjengelighet - -Som standard er `Accordion.Heading` et `h1` element. Du må selv velge riktig overskriftsnivå for din side. Hvis `Accordion.Heading` er en del av en større overskrift, kan du bruke `h2`, `h3` osv. for å opprettholde en logisk rekkefølge. - -[`Chevron`](https://aksel.nav.no/ikoner/ChevronDown)-ikonet er bevisst plassert til venstre for teksten, av hensyn til brukerer med nedsatt synsfelt. Der er det lettere for brukeren å se det (fordi vi leser fra venstre). Mange brukere tror at de må peke på og velge ikonet for å åpne. - -Ikke plasser andre interaktive elementer inn i `Accordion`-heading, da hele raden skal være klikkbar. Ikonet og teksten skal _ikke_ lenke til ulike handlinger (for eksempel at teksten går videre til en side, mens ikonet åpner listen). Brukerne forventer ikke at ikon og tekst skal gi ulikt resultat når de velger dem. - -`Tab` : Flytter fokus til neste element som kan ha fokus \ -`Shift` + `Tab` : Flytter fokus til forrige element som kan ha fokus \ -`Space` : Aktiverer knapp \ -`Enter` : Aktiverer knapp - -
- -## Andre props - -### Accordion.Item - - - -### Accordion.Heading - - - -### Accordion.Content - - - -## CSS Variabler - - diff --git a/packages/react/src/components/Accordion/Accordion.test.tsx b/packages/react/src/components/Accordion/Accordion.test.tsx deleted file mode 100644 index 355898ef66..0000000000 --- a/packages/react/src/components/Accordion/Accordion.test.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { render, screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import { act } from 'react'; - -import type { AccordionItemProps } from './'; -import { Accordion } from './'; - -const user = userEvent.setup(); -const VOID = () => {}; - -const TestComponent = (rest: AccordionItemProps): JSX.Element => { - return ( - - - Accordion Header Title Text - - The fantastic accordion content text - - - - ); -}; - -describe('Accordion', () => { - test('accordion should have heading, Content and be closed by default', () => { - render(); - const accordionExpandButton = screen.getByRole('button'); - - expect(screen.getByText('The fantastic accordion content text')); - expect(screen.getByText('Accordion Header Title Text')); - expect(accordionExpandButton).toHaveAttribute('aria-expanded', 'false'); - }); - - test('should render accordion with open state as controlled', () => { - render(); - const accordionExpandButton = screen.getByRole('button'); - expect(accordionExpandButton).toHaveAttribute('aria-expanded', 'true'); - }); - - test('Should be able to set defaultOpen on uncontrolled', () => { - render(); - - const accordionExpandButton = screen.getByRole('button'); - expect(accordionExpandButton).toHaveAttribute('aria-expanded', 'true'); - }); - - test('should be able to render AccordionItem as controlled', () => { - render(); - - const accordionExpandButton = screen.getByRole('button'); - expect(accordionExpandButton).toHaveAttribute('aria-expanded', 'true'); - }); -}); - -describe('Accordion Accessibility', () => { - test('should toggle aria-expanded based on user action (uncontrolled)', async () => { - render(); - - const accordionExpandButton = screen.getByRole('button'); - expect(accordionExpandButton).toHaveAttribute('aria-expanded', 'false'); - - await act(async () => await user.click(accordionExpandButton)); - expect(accordionExpandButton).toHaveAttribute('aria-expanded', 'true'); - - await act(async () => await user.click(accordionExpandButton)); - expect(accordionExpandButton).toHaveAttribute('aria-expanded', 'false'); - }); - - test('should have correct aria-expanded when controlled', () => { - const { rerender, container } = render( - , - ); - - const accordionExpandButton = screen.getByRole('button'); - expect(accordionExpandButton).toHaveAttribute('aria-expanded', 'true'); - - rerender(); - expect(accordionExpandButton).toHaveAttribute('aria-expanded', 'false'); - }); -}); diff --git a/packages/react/src/components/Accordion/Accordion.tsx b/packages/react/src/components/Accordion/Accordion.tsx deleted file mode 100644 index 9d3019ed9d..0000000000 --- a/packages/react/src/components/Accordion/Accordion.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import cl from 'clsx/lite'; -import type { HTMLAttributes, ReactNode } from 'react'; -import { forwardRef } from 'react'; -import type { Color } from '../../colors'; -import type { DefaultProps } from '../../types'; -import type { MergeRight } from '../../utilities'; - -export type AccordionProps = MergeRight< - DefaultProps & HTMLAttributes, - { - /** - * Accordion background color. - * @default neutral - */ - 'data-color'?: 'subtle' | Color; - /** - * Show border - * @default false - **/ - border?: boolean; - /** Instances of `Accordion.Item` */ - children: ReactNode; - } ->; - -/** - * Accordion component, contains `Accordion.Item` components. - */ -export const Accordion = forwardRef( - function Accordion( - { border = false, 'data-color': color = 'neutral', className, ...rest }, - ref, - ) { - return ( -
- ); - }, -); diff --git a/packages/react/src/components/Accordion/AccordionContent.tsx b/packages/react/src/components/Accordion/AccordionContent.tsx deleted file mode 100644 index ce87ad9fe7..0000000000 --- a/packages/react/src/components/Accordion/AccordionContent.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import type { HTMLAttributes } from 'react'; -import { forwardRef } from 'react'; - -export type AccordionContentProps = HTMLAttributes; - -/** - * Accordion content component, contains the content of the accordion item. - * @example - * Content - */ -export const AccordionContent = forwardRef< - HTMLDivElement, - AccordionContentProps ->(function AccordionContent(rest, ref) { - return
; -}); diff --git a/packages/react/src/components/Accordion/index.ts b/packages/react/src/components/Accordion/index.ts deleted file mode 100644 index 96e67026ce..0000000000 --- a/packages/react/src/components/Accordion/index.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { Accordion as AccordionParent } from './Accordion'; -import { AccordionContent } from './AccordionContent'; -import { AccordionHeading } from './AccordionHeading'; -import { AccordionItem } from './AccordionItem'; - -type AccordionComponent = typeof AccordionParent & { - Item: typeof AccordionItem; - Heading: typeof AccordionHeading; - Content: typeof AccordionContent; -}; - -/** - * Accordions are used to toggle the visibility of content. - * @example - * - * - * Heading 1 - * Content 1 - * - * - */ -const Accordion = AccordionParent as AccordionComponent; - -Accordion.Heading = AccordionHeading; -Accordion.Content = AccordionContent; -Accordion.Item = AccordionItem; - -Accordion.Heading.displayName = 'Accordion.Heading'; -Accordion.Content.displayName = 'Accordion.Content'; -Accordion.Item.displayName = 'Accordion.Item'; - -export type { AccordionContentProps } from './AccordionContent'; -export type { AccordionHeadingProps } from './AccordionHeading'; -export type { AccordionItemProps } from './AccordionItem'; -export type { AccordionProps } from './Accordion'; -export { Accordion, AccordionItem, AccordionContent, AccordionHeading }; diff --git a/packages/react/src/components/Card/Card.stories.tsx b/packages/react/src/components/Card/Card.stories.tsx index ab2a4b7a66..146e3a830f 100644 --- a/packages/react/src/components/Card/Card.stories.tsx +++ b/packages/react/src/components/Card/Card.stories.tsx @@ -57,7 +57,15 @@ 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 @@ -70,7 +78,15 @@ export const Variants: StoryFn = () => ( 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 @@ -83,7 +99,15 @@ export const Variants: StoryFn = () => ( 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 @@ -96,7 +120,15 @@ export const Variants: StoryFn = () => ( 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 @@ -109,7 +141,15 @@ export const Variants: StoryFn = () => ( 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 diff --git a/packages/react/src/components/Details/Details.mdx b/packages/react/src/components/Details/Details.mdx new file mode 100644 index 0000000000..5b85b83d7d --- /dev/null +++ b/packages/react/src/components/Details/Details.mdx @@ -0,0 +1,120 @@ +import { Meta, Canvas, Controls, Primary, ArgTypes } from '@storybook/blocks'; +import { CssVariables } from '@doc-components'; + +import * as DetailsStories from './Details.stories'; + +import { Details } from '.'; +import css from '@digdir/designsystemet-css/details.css?inline'; + + + +# Details + +Med `Details` kan du presentere mye innhold på liten plass i en eller flere rader. Hele raden er klikkbar og lar brukere åpne eller lukke visningen av innholdet under. + +**Vær oppmerksom på:** + +- Ved å legge innhold i `Details` risikerer du at det ikke blir sett av brukerne. Innhold som er viktig bør _ikke_ skjules. +- Ikke legg en `Details` inni en annen. + +
+ + + + +## Bruk + +```tsx +import { Details } from '@digdir/designsystemet-react'; + +
+ Details heading text + Details content +
+``` + +## Eksempler + +
+### Med ramme + +`Details` kan vises med ramme ved å plasseres i et `Card`. +Dette kan passe i tilfeller der details ikke fyller hele siden, eller når det kun er en rad. + + + +### Med farger + +`Details` kan vises i farger fra ditt tema. + + + +#### Kontrollert + +`Details` har egen tilstand på åpen/lukket, men dette kan kontrolleres utenfra. + + + +
+ +## Retningslinjer + +Tester viser at brukerne sjeldnere ser på skjult innhold, enn det som er synlig direkte på siden. Ikke bruk `Details` til å skjule innhold for å gjøre siden "ryddigere". Finn ut om du faktisk må skjule innhold og vær klar over hvorfor du gjør det. Tenk over om det er lurt å vise det viktigste innholdet i åpen status når brukeren kommer inn på siden. + +Hvis innholdet er for langt eller komplisert, bør du heller omformulere teksten og/eller eventuelt fordele den på flere sider. + +### Egnet til + +- samle innhold som er litt lengre +- gjøre det frivillig å se innhold som er litt mindre viktig enn alltid synlig innhold +- vise ofte stilte spørsmål +- vise tilleggsinformasjon som kan være til hjelp for brukerne + +### Ikke egnet til + +- vise små mengder innhold +- vise informasjon hvis det bare er ett element +- vise viktig innhold som alle bør se når de kommer til siden (for eksempel feilmeldinger) +- gi mer informasjon om et spørsmål i et skjema – det innholdet bør brukeren se med en gang +- velge mellom ulike alternativer +- skjule innhold fra søkeresultater eller oversikter/tabeller +- dele opp en logisk flyt eller en rekke med handlinger, da bør du heller bruke en trinnvis liste + +### Unngå + +- Ikke legg en `Details` inni en annen, det vi kaller nøstede lister. + +
+ +## Tekst i komponenten + +Details skal brukes til maksimalt to avsnitt innenfor hvert nedtrekk. Sørg for at overskriften gir en god beskrivelse av hva innholdet i details er. En tydelig og beskrivende overskrift skal gjøre brukerne nysgjerrige på innholdet. Overskriftene til details kan ha stor betydning for om brukerne finner det de trenger, om innholdet blir lest og om det kan regnes som tilgjengelig for alle brukere. «Vis mer» eller «Les mer her» er ikke gode nok titler. Har du en details med mange nedtrekk, kan du ha en hovedoverskrift eller temaoverskrift over hele listen. + +
+ +## Tilgjengelighet + +[`Chevron`](https://aksel.nav.no/ikoner/ChevronDown)-ikonet er bevisst plassert til venstre for teksten, av hensyn til brukerer med nedsatt synsfelt. Der er det lettere for brukeren å se det (fordi vi leser fra venstre). Mange brukere tror at de må peke på og velge ikonet for å åpne. + +Ikke plasser andre interaktive elementer inn i `Details.Summary`, da hele raden skal være klikkbar. Ikonet og teksten skal _ikke_ lenke til ulike handlinger (for eksempel at teksten går videre til en side, mens ikonet åpner listen). Brukerne forventer ikke at ikon og tekst skal gi ulikt resultat når de velger dem. + +`Tab` : Flytter fokus til neste element som kan ha fokus \ +`Shift` + `Tab` : Flytter fokus til forrige element som kan ha fokus \ +`Space` : Aktiverer knapp \ +`Enter` : Aktiverer knapp + +
+ +## Andre props + +### Details.Summary + + + +### Details.Content + + + +## CSS Variabler + + diff --git a/packages/react/src/components/Accordion/Accordion.stories.tsx b/packages/react/src/components/Details/Details.stories.tsx similarity index 66% rename from packages/react/src/components/Accordion/Accordion.stories.tsx rename to packages/react/src/components/Details/Details.stories.tsx index fe42f5e542..879720b9e6 100644 --- a/packages/react/src/components/Accordion/Accordion.stories.tsx +++ b/packages/react/src/components/Details/Details.stories.tsx @@ -1,69 +1,57 @@ import type { Meta, StoryFn } from '@storybook/react'; import { useState } from 'react'; -import { Button, Link } from '../'; - -import { Accordion } from '.'; +import { Button, Card, Details, Link } from '../'; export default { - title: 'Komponenter/Accordion', - component: Accordion, + title: 'Komponenter/Details', + component: Details, parameters: { layout: 'padded', }, } as Meta; -export const Preview: StoryFn = (args) => ( - - - - Hvem kan registrere seg i Frivillighetsregisteret? - - - For å kunne bli registrert i Frivillighetsregisteret, må organisasjonen - drive frivillig virksomhet. Det er bare foreninger, stiftelser og - aksjeselskap som kan registreres. Virksomheten kan ikke dele ut midler - til fysiske personer. Virksomheten må ha et styre. - - - - - Hvordan går jeg fram for å registrere i Frivillighetsregisteret? - - - Virksomheten må være registrert i Enhetsregisteret før den kan bli - registrert i Frivillighetsregisteret. Du kan registrere i begge - registrene samtidig i Samordnet registermelding. - - - +export const Preview: StoryFn = (args) => ( +
+ + Hvem kan registrere seg i Frivillighetsregisteret? + + + For å kunne bli registrert i Frivillighetsregisteret, må organisasjonen + drive frivillig virksomhet. Det er bare foreninger, stiftelser og + aksjeselskap som kan registreres. Virksomheten kan ikke dele ut midler til + fysiske personer. Virksomheten må ha et styre. + +
); +// Default values are selected in Controls +Preview.args = { + 'data-color': 'neutral', +}; -export const AccordionBorder: StoryFn = () => ( - - - Vedlegg - Vedlegg 1, vedlegg 2, vedlegg 3 - - +export const InCard: StoryFn = () => ( + +
+ Vedlegg + Vedlegg 1, vedlegg 2, vedlegg 3 +
+
); -export const AccordionColor: StoryFn = () => ( - - - - Hvordan får jeg tildelt et jegernummer? - - +export const InCardWithColor: StoryFn = () => ( + +
+ Hvordan får jeg tildelt et jegernummer? + Du vil automatisk få tildelt jegernummer og bli registrert i Jegerregisteret når du har bestått jegerprøven. - - - - + +
+
+ Jeg har glemt jegernummeret mitt. Hvor finner jeg dette? - - + +

Du kan finne dette ved å logge inn på{' '} Min side @@ -127,18 +115,12 @@ export const AccordionColor: StoryFn = () => ( sodales a arcu. Phasellus ornare, lorem nec aliquam venenatis, augue eros sagittis quam, at sagittis tellus ante in metus.

- - - +
+
+
); -// Default values are selected in Controls -Preview.args = { - border: false, - 'data-color': 'neutral', -}; - -export const Controlled: StoryFn = () => { +export const Controlled: StoryFn = () => { const [open1, setOpen1] = useState(false); const [open2, setOpen2] = useState(false); const [open3, setOpen3] = useState(false); @@ -151,39 +133,39 @@ export const Controlled: StoryFn = () => { return ( <> - +
- - setOpen1(!open1)}> - Enkeltpersonforetak - + <> +
setOpen1(!open1)}> + Enkeltpersonforetak + Skal du starte for deg selv? Enkeltpersonforetak er ofte den enkleste måten å etablere bedrift på. Denne organisasjonsformen har både fordeler og ulemper. Det gir deg stor grad av frihet, men kan også gi betydelig risiko fordi du har personlig ansvar for økonomien. - - - setOpen2(!open2)}> - Aksjeselskap (AS) - + +
+
setOpen2(!open2)}> + Aksjeselskap (AS) + Planlegger du å starte næringsvirksomhet alene eller sammen med andre? Innebærer næringsvirksomheten en økonomisk risiko? Vil du ha rettigheter som arbeidstaker og muligheten til at andre kan investere i selskapet ditt? Da kan aksjeselskap være en hensiktsmessig organisasjonsform. - - - setOpen3(!open3)}> - Ansvarlig selskap (ANS/DA) - + +
+
setOpen3(!open3)}> + Ansvarlig selskap (ANS/DA) + Er dere minst to personer som skal starte opp egen virksomhet? Samarbeider du godt med den/de som du skal starte opp sammen med? Krever virksomheten få investeringer og tar du liten økonomisk risiko? Da kan du vurdere å etablere et ansvarlig selskap. - - - + +
+ ); }; diff --git a/packages/react/src/components/Details/Details.test.tsx b/packages/react/src/components/Details/Details.test.tsx new file mode 100644 index 0000000000..96b7a15150 --- /dev/null +++ b/packages/react/src/components/Details/Details.test.tsx @@ -0,0 +1,77 @@ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { act } from 'react'; + +import { Details, type DetailsProps } from './'; + +const user = userEvent.setup(); +const VOID = () => {}; + +const TestComponent = (rest: DetailsProps): JSX.Element => { + return ( + <> +
+ Details Header Title Text + The fantastic details content text +
+ + ); +}; + +describe('Details', () => { + test('details should have heading, Content and be closed by default', () => { + render(); + const detailsExpandButton = screen.getByRole('button'); + + expect(screen.getByText('The fantastic details content text')); + expect(screen.getByText('Details Header Title Text')); + expect(detailsExpandButton).toHaveAttribute('aria-expanded', 'false'); + }); + + test('should render details with open state as controlled', () => { + render(); + const detailsExpandButton = screen.getByRole('button'); + expect(detailsExpandButton).toHaveAttribute('aria-expanded', 'true'); + }); + + test('Should be able to set defaultOpen on uncontrolled', () => { + render(); + + const detailsExpandButton = screen.getByRole('button'); + expect(detailsExpandButton).toHaveAttribute('aria-expanded', 'true'); + }); + + test('should be able to render Details as controlled', () => { + render(); + + const detailsExpandButton = screen.getByRole('button'); + expect(detailsExpandButton).toHaveAttribute('aria-expanded', 'true'); + }); +}); + +describe('Details Accessibility', () => { + test('should toggle aria-expanded based on user action (uncontrolled)', async () => { + render(); + + const detailsExpandButton = screen.getByRole('button'); + expect(detailsExpandButton).toHaveAttribute('aria-expanded', 'false'); + + await act(async () => await user.click(detailsExpandButton)); + expect(detailsExpandButton).toHaveAttribute('aria-expanded', 'true'); + + await act(async () => await user.click(detailsExpandButton)); + expect(detailsExpandButton).toHaveAttribute('aria-expanded', 'false'); + }); + + test('should have correct aria-expanded when controlled', () => { + const { rerender, container } = render( + , + ); + + const detailsExpandButton = screen.getByRole('button'); + expect(detailsExpandButton).toHaveAttribute('aria-expanded', 'true'); + + rerender(); + expect(detailsExpandButton).toHaveAttribute('aria-expanded', 'false'); + }); +}); diff --git a/packages/react/src/components/Accordion/AccordionItem.tsx b/packages/react/src/components/Details/Details.tsx similarity index 73% rename from packages/react/src/components/Accordion/AccordionItem.tsx rename to packages/react/src/components/Details/Details.tsx index ecea56b65a..da2f1295de 100644 --- a/packages/react/src/components/Accordion/AccordionItem.tsx +++ b/packages/react/src/components/Details/Details.tsx @@ -4,7 +4,7 @@ import type { HTMLAttributes, ReactNode } from 'react'; import { forwardRef, useEffect, useRef } from 'react'; import '@u-elements/u-details'; -export type AccordionItemProps = { +export type DetailsProps = { /** * Controls open-state. * @@ -14,13 +14,13 @@ export type AccordionItemProps = { */ open?: boolean; /** - * Defaults the accordion to open if not controlled + * Defaults the details to open if not controlled * @default false */ defaultOpen?: boolean; - /** Callback function when AccordionItem toggles due to click on summary or find in page-search */ + /** Callback function when Details toggles due to click on summary or find in page-search */ onToggle?: (event: Event) => void; - /** Content should be one `` and `` */ + /** Content should be one `` and `` */ children?: ReactNode; } & Omit, 'onToggle'> & ( @@ -29,15 +29,15 @@ export type AccordionItemProps = { ); /** - * Accordion item component, contains `Accordion.Heading` and `Accordion.Content` components. + * Details component, contains `Details.Summary` and `Details.Content` components. * @example - * - * Header - * Content - * + *
+ * Header + * Content + *
*/ -export const AccordionItem = forwardRef( - function AccordionItem( +export const Details = forwardRef( + function Details( { className, open, defaultOpen = false, onToggle, ...rest }, ref, ) { @@ -64,7 +64,7 @@ export const AccordionItem = forwardRef( return ( ; + +/** + * Details content component, contains the content of the details item. + * @example + * Content + */ +export const DetailsContent = forwardRef( + function DetailsContent(rest, ref) { + return
; + }, +); diff --git a/packages/react/src/components/Accordion/AccordionHeading.tsx b/packages/react/src/components/Details/DetailsSummary.tsx similarity index 51% rename from packages/react/src/components/Accordion/AccordionHeading.tsx rename to packages/react/src/components/Details/DetailsSummary.tsx index ece30e5878..0713c34c92 100644 --- a/packages/react/src/components/Accordion/AccordionHeading.tsx +++ b/packages/react/src/components/Details/DetailsSummary.tsx @@ -1,18 +1,18 @@ import type { HTMLAttributes, ReactNode } from 'react'; import { forwardRef } from 'react'; -export type AccordionHeadingProps = { +export type DetailsSummaryProps = { /** Heading text */ children: ReactNode; } & HTMLAttributes; /** - * Accordion heading component, contains a button to toggle the content. + * Details summary component, contains a the heading to toggle the content. * @example - * Heading + * Heading */ -export const AccordionHeading = forwardRef( - function AccordionHeading({ className, ...rest }, ref) { +export const DetailsSummary = forwardRef( + function DetailsSummary({ className, ...rest }, ref) { /* Set `className` as `class` so react is happy */ return ; }, diff --git a/packages/react/src/components/Details/index.ts b/packages/react/src/components/Details/index.ts new file mode 100644 index 0000000000..33280b5276 --- /dev/null +++ b/packages/react/src/components/Details/index.ts @@ -0,0 +1,24 @@ +import { Details as DetailsParent } from './Details'; +import { DetailsContent } from './DetailsContent'; +import { DetailsSummary } from './DetailsSummary'; + +/** + * Details are used to toggle the visibility of content. + * @example + *
+ * Heading 1 + * Content 1 + *
+ */ +const Details = Object.assign(DetailsParent, { + Summary: DetailsSummary, + Content: DetailsContent, +}); + +Details.Summary.displayName = 'Details.Summary'; +Details.Content.displayName = 'Details.Content'; + +export type { DetailsContentProps } from './DetailsContent'; +export type { DetailsSummaryProps } from './DetailsSummary'; +export type { DetailsProps } from './Details'; +export { Details, DetailsContent, DetailsSummary }; diff --git a/packages/react/src/components/index.ts b/packages/react/src/components/index.ts index d89e66ea27..1b785d6472 100644 --- a/packages/react/src/components/index.ts +++ b/packages/react/src/components/index.ts @@ -11,7 +11,7 @@ export * from './Label'; export * from './Heading'; export * from './Paragraph'; export * from './ValidationMessage'; -export * from './Accordion'; +export * from './Details'; export * from './form/Select'; export * from './Alert'; export * from './Tag'; diff --git a/packages/react/stories/bruk.mdx b/packages/react/stories/bruk.mdx index 9774f12e11..c3062df21a 100644 --- a/packages/react/stories/bruk.mdx +++ b/packages/react/stories/bruk.mdx @@ -61,21 +61,19 @@ Vil bli til: Alle våre komponenter er klient komponenter, og bruker `"use client"`. Dersom du ønsker å bruke våre komponenter i dine server komponenter, så kan du ikke bruke dot-notation. -Dette betyr at du ikke kan skrive ``, men må skrive ``. Grunnen for dette er at serveren ikke kan få tak i noe -som ligger i en klient komponent, som `Accordion` er. +Dette betyr at du ikke kan skrive ``, men må skrive ``. Grunnen for dette er at serveren ikke kan få tak i noe +som ligger i en klient komponent, som `Details` er. #### I en server komponent: {` -import { Accordion, AccordionHeading, AccordionItem, AccordionContent } from '@digdir/designsystemet-react'; - - - - ... - ... - - +import { Details, DetailsSummary, DetailsContent } from '@digdir/designsystemet-react'; + +
+ ... + ... +
`}
@@ -83,22 +81,20 @@ import { Accordion, AccordionHeading, AccordionItem, AccordionContent } from '@d {` -import { Accordion } from '@digdir/designsystemet-react'; - - - - ... - ... - - +import { Details } from '@digdir/designsystemet-react'; + +
+ ... + ... +
`}
-### Komponenter med `.Root` +### Komponenter med `.TriggerContext` -Noen komponenter har en `.Root` komponent, som må wrappes rundt barn. Disse må brukes for at komponenten skal funke. -Accordion har f.eks en `Accordion` komponent som må wrappes rundt `Accordion.Item` komponentene. -Dette er for å få riktig funksjonalitet gjennom komponenten. +Noen komponenter har en `.TriggerContext`, som kan wrappes rundt komponenten pluss en `.Trigger`. +Disse kan brukes for å automatisk koble komponenten til en trigger - typisk en knapp. +Modal har f.eks en `Modal.TriggerContext` komponent som kan wrappes rundt `Modal.Trigger` og `Modal` komponentene.

diff --git a/packages/react/stories/testing.stories.tsx b/packages/react/stories/testing.stories.tsx index a74e22669f..c0f7d83158 100644 --- a/packages/react/stories/testing.stories.tsx +++ b/packages/react/stories/testing.stories.tsx @@ -2,7 +2,6 @@ import { PrinterSmallIcon } from '@navikt/aksel-icons'; import type { Meta, StoryFn } from '@storybook/react'; import { useState } from 'react'; import { - Accordion, Alert, Avatar, Badge, @@ -12,6 +11,7 @@ import { Checkbox, Chip, Combobox, + Details, Dropdown, ErrorSummary, Field, @@ -180,20 +180,20 @@ export const Sizes: StoryFn = () => {
))} {sizes.map((size) => ( - - - + +
+ Hvem kan registrere seg i Frivillighetsregisteret? - - + + For å kunne bli registrert i Frivillighetsregisteret, må organisasjonen drive frivillig virksomhet. Det er bare foreninger, stiftelser og aksjeselskap som kan registreres. Virksomheten kan ikke dele ut midler til fysiske personer. Virksomheten må ha et styre. - - - + +
+
))} {sizes.map((size) => (