Skip to content

Commit

Permalink
feat(dropdownmenu): streamline API (#2432)
Browse files Browse the repository at this point in the history
part of #2221
I changed to using our `Popover`, which means we can handle testing
state there.
New API is this:
```tsx
import { DropdownMenu } from '@digdir/designsystemet-react';

// med context
<DropdownMenu.Context>
  <DropdownMenu.Trigger>Trigger</DropdownMenu.Trigger>
  <DropdownMenu>
    <DropdownMenu.Heading>Heading</DropdownMenu.Heading>
    <DropdownMenu.List>
      <DropdownMenu.Item>Item</DropdownMenu.Item>
    </DropdownMenu.List>
  </DropdownMenu>
</DropdownMenu.Context>

// uten context
<Button popovertarget="my-dropdown">Trigger</Button>
<Dropdown id="my-dropdown">
  <DropdownMenu.Heading>Heading</DropdownMenu.Heading>
  <DropdownMenu.List>
    <DropdownMenu.Item>Item</DropdownMenu.Item>
  </DropdownMenu.List>
</Dropdown>
```
  • Loading branch information
Barsnes authored Sep 18, 2024
1 parent 4b3b1bc commit 7dceadd
Show file tree
Hide file tree
Showing 31 changed files with 578 additions and 853 deletions.
10 changes: 10 additions & 0 deletions .changeset/proud-walls-flash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
"@digdir/designsystemet-css": patch
"@digdir/designsystemet-react": patch
---

DropdownMenu:
- Rename from `DropdownMenu` to `Dropdown`
- Change API and structure
- Rename `.Root` to `.Context`
- Rename `.Content` to `Dropdown`
4 changes: 2 additions & 2 deletions apps/storefront/app/komponenter/component-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ export const data = [
},
{
title: 'Dropdown Menu',
image: 'DropdownMenu.svg',
url: 'https://storybook.designsystemet.no/?path=/docs/komponenter-dropdownmenu--docs',
image: 'Dropdown.svg',
url: 'https://storybook.designsystemet.no/?path=/docs/komponenter-dropdown--docs',
},
{
title: 'Error Summary',
Expand Down
50 changes: 25 additions & 25 deletions apps/storefront/components/Tokens/TokenList/TokenList.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';
import {
DropdownMenu,
Dropdown,
Heading,
Link,
Paragraph,
Expand Down Expand Up @@ -220,40 +220,40 @@ const TokenList = ({
{(showThemePicker || showModeSwitcher) && (
<div className={classes.toggleGroup}>
{showThemePicker && (
<DropdownMenu.Root>
<DropdownMenu.Trigger variant='secondary'>
<Dropdown.Context>
<Dropdown.Trigger variant='secondary'>
Brand: {capitalizeString(brand)}
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Item onClick={() => setBrand('digdir')}>
</Dropdown.Trigger>
<Dropdown>
<Dropdown.Item onClick={() => setBrand('digdir')}>
Digdir
</DropdownMenu.Item>
<DropdownMenu.Item onClick={() => setBrand('altinn')}>
</Dropdown.Item>
<Dropdown.Item onClick={() => setBrand('altinn')}>
Altinn
</DropdownMenu.Item>
<DropdownMenu.Item onClick={() => setBrand('tilsynet')}>
</Dropdown.Item>
<Dropdown.Item onClick={() => setBrand('tilsynet')}>
Tilsynet
</DropdownMenu.Item>
<DropdownMenu.Item onClick={() => setBrand('portal')}>
</Dropdown.Item>
<Dropdown.Item onClick={() => setBrand('portal')}>
Brreg
</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu.Root>
</Dropdown.Item>
</Dropdown>
</Dropdown.Context>
)}
{showModeSwitcher && (
<DropdownMenu.Root>
<DropdownMenu.Trigger variant='secondary'>
<Dropdown.Context>
<Dropdown.Trigger variant='secondary'>
Mode: {capitalizeString(mode)}
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Item onClick={() => setMode('light')}>
</Dropdown.Trigger>
<Dropdown>
<Dropdown.Item onClick={() => setMode('light')}>
Light
</DropdownMenu.Item>
<DropdownMenu.Item onClick={() => setMode('dark')}>
</Dropdown.Item>
<Dropdown.Item onClick={() => setMode('dark')}>
Dark
</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu.Root>
</Dropdown.Item>
</Dropdown>
</Dropdown.Context>
)}
</div>
)}
Expand Down
20 changes: 10 additions & 10 deletions apps/theme/components/Previews/Components/Components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
Checkbox,
Chip,
Combobox,
DropdownMenu,
Dropdown,
Fieldset,
Heading,
HelpText,
Expand Down Expand Up @@ -390,18 +390,18 @@ export const Components = () => {
</Alert>
</div>
<div className={cl(classes.card, classes.dropdown)}>
<DropdownMenu.Root placement='top'>
<DropdownMenu.Trigger>Velg språk</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Item>Norsk</DropdownMenu.Item>
<DropdownMenu.Item>Engelsk</DropdownMenu.Item>
<DropdownMenu.Item>Spansk</DropdownMenu.Item>
<DropdownMenu.Item>Fransk</DropdownMenu.Item>
</DropdownMenu.Content>
<Dropdown.Context>
<Dropdown.Trigger>Velg språk</Dropdown.Trigger>
<Dropdown placement='top'>
<Dropdown.Item>Norsk</Dropdown.Item>
<Dropdown.Item>Engelsk</Dropdown.Item>
<Dropdown.Item>Spansk</Dropdown.Item>
<Dropdown.Item>Fransk</Dropdown.Item>
</Dropdown>
<HelpText title='Du har ikke valgt språk'>
Velg språk for å endre innholdet på siden
</HelpText>
</DropdownMenu.Root>
</Dropdown.Context>
</div>
<div className={cl(classes.card, classes.loaders)}>
<div className={classes.loadersRest}>
Expand Down
45 changes: 45 additions & 0 deletions packages/css/dropdown.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
.ds-dropdown {
--dsc-dropdown-padding: var(--ds-spacing-3) var(--ds-spacing-2);
--dsc-dropdown-min-width: 16rem;
--dsc-dropdown-item-padding: 0 var(--ds-spacing-4);
--dsc-dropdown-header-padding: var(--ds-spacing-2) var(--ds-spacing-4);

padding: var(--dsc-dropdown-padding);
list-style: none;
border-radius: min(1rem, var(--ds-border-radius-md));
box-shadow: var(--ds-shadow-md);
background-color: var(--ds-color-neutral-background-default);
border: 1px solid var(--ds-color-neutral-border-subtle);
min-width: var(--dsc-dropdown-min-width);

/* Remove popover arrow */
&::before {
display: none;
}

&[data-size='sm'] {
--dsc-dropdown-padding: var(--ds-spacing-2);
--dsc-dropdown-min-width: 15rem;
}

&[data-size='lg'] {
--dsc-dropdown-padding: var(--ds-spacing-4) var(--ds-spacing-2);
--dsc-dropdown-min-width: 18rem;
}

& :is(a, button, [role='button']) {
justify-content: start;
padding: var(--dsc-dropdown-item-padding);
width: 100%;
}

.ds-dropdown__list {
margin: 0;
padding: 0;
list-style: none;
}

.ds-dropdown__heading {
padding: var(--dsc-dropdown-header-padding);
}
}
43 changes: 0 additions & 43 deletions packages/css/dropdownmenu.css

This file was deleted.

4 changes: 2 additions & 2 deletions packages/css/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
@import url('./utilities.css') layer(ds.utilities);
@import url('./button.css') layer(ds.components);
@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('./switch.css') layer(ds.components);
Expand All @@ -27,12 +28,11 @@
@import url('./card.css') layer(ds.components);
@import url('./link.css') layer(ds.components);
@import url('./fieldset.css') layer(ds.components);
@import url('./dropdownmenu.css') layer(ds.components);
@import url('./dropdown.css') layer(ds.components);
@import url('./chip') layer(ds.components);
@import url('./divider.css') layer(ds.components);
@import url('./tabs.css') layer(ds.components);
@import url('./pagination.css') layer(ds.components);
@import url('./popover.css') layer(ds.components);
@import url('./skeleton.css') layer(ds.components);
@import url('./tag.css') layer(ds.components);
@import url('./error-summary.css') layer(ds.components);
Expand Down
2 changes: 1 addition & 1 deletion packages/react/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline

### Bug Fixes

- **DropDownMenuItem:** add list style none ([#1190](https://github.com/digdir/designsystemet/issues/1190)) ([11bd19b](https://github.com/digdir/designsystemet/commit/11bd19bfb6ac76b2c697a22e876117c4128be3bd))
- **DropdownMenuItem:** add list style none ([#1190](https://github.com/digdir/designsystemet/issues/1190)) ([11bd19b](https://github.com/digdir/designsystemet/commit/11bd19bfb6ac76b2c697a22e876117c4128be3bd))
- **List:** Wrap in `div` to allow access to `Heading` ([#1217](https://github.com/digdir/designsystemet/issues/1217)) ([afcadb7](https://github.com/digdir/designsystemet/commit/afcadb7c4cb4b368d247af0c41ed8debf53c4b66))
- **Pagination:** Only use needed space for buttons ([#1220](https://github.com/digdir/designsystemet/issues/1220)) ([4bf3d74](https://github.com/digdir/designsystemet/commit/4bf3d745888f500259df5aadf4edee97ec4f95bc))
- **Select:** Select not working properly in Modal ([#1195](https://github.com/digdir/designsystemet/issues/1195)) ([fb8be6a](https://github.com/digdir/designsystemet/commit/fb8be6a647ba0da8b5b23e65813508f34e09c8c1))
Expand Down
29 changes: 15 additions & 14 deletions packages/react/src/components/Avatar/Avatar.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { Meta, StoryFn } from '@storybook/react';

import { BriefcaseIcon } from '@navikt/aksel-icons';
import { Avatar } from '.';
import { Badge, DropdownMenu } from '../';
import { Badge, Dropdown } from '../';

type Story = StoryFn<typeof Avatar>;

Expand Down Expand Up @@ -93,33 +93,34 @@ export const WithImage: Story = () => (
</Avatar>
);

export const InDropdownMenu: Story = () => (
<DropdownMenu.Root placement='bottom-end' size='md' portal>
<DropdownMenu.Trigger variant='tertiary'>
export const InDropdown: Story = () => (
<Dropdown.Context>
<Dropdown.Trigger variant='tertiary'>
<Avatar aria-label='Ola Nordmann' size='sm'>
ON
</Avatar>
Velg Profil
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Group heading='Alle kontoer'>
<DropdownMenu.Item>
</Dropdown.Trigger>
<Dropdown placement='bottom-end' size='md'>
<Dropdown.Heading>Alle kontoer</Dropdown.Heading>
<Dropdown.List>
<Dropdown.Item>
<Badge overlap='circle' color='danger' size='sm'>
<Avatar aria-label='Ola Nordmann' size='xs'>
ON
</Avatar>
</Badge>
Ola Nordmann
</DropdownMenu.Item>
<DropdownMenu.Item>
</Dropdown.Item>
<Dropdown.Item>
<Avatar size='xs' color='brand1' aria-label='Sogndal Kommune'>
<BriefcaseIcon fontSize='5em' />
</Avatar>
Sogndal kommune
</DropdownMenu.Item>
</DropdownMenu.Group>
</DropdownMenu.Content>
</DropdownMenu.Root>
</Dropdown.Item>
</Dropdown.List>
</Dropdown>
</Dropdown.Context>
);

export const AsLink: Story = () => (
Expand Down
81 changes: 81 additions & 0 deletions packages/react/src/components/Dropdown/Dropdown.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { Meta, Canvas, Controls, Primary, ArgTypes } from '@storybook/blocks';

import * as DropdownStories from './Dropdown.stories';

import { Dropdown } from './';

<Meta of={DropdownStories} />

# Dropdown

<Primary />
<Controls />

## Slik bruker du `Dropdown`

```tsx
import { Dropdown } from '@digdir/designsystemet-react';

// med context
<Dropdown.Context>
<Dropdown.Trigger>Trigger</Dropdown.Trigger>
<Dropdown>
<Dropdown.Heading>Heading</Dropdown.Heading>
<Dropdown.List>
<Dropdown.Item>Item</Dropdown.Item>
</Dropdown.List>
</Dropdown>
</Dropdown.Context>

// uten context
<Button popovertarget="my-dropdown">Trigger</Button>
<Dropdown id="my-dropdown">
<Dropdown.Heading>Heading</Dropdown.Heading>
<Dropdown.List>
<Dropdown.Item>Item</Dropdown.Item>
</Dropdown.List>
</Dropdown>
```

## Eksempler på bruk

### Kontrollert

Dersom du sender inn `open`, så bruker du `Dropdown` kontrollert. Du kan bruke `onClose` for å få beskjed når `Dropdown` vil lukkes.

<Canvas of={DropdownStories.Controlled} />

### Ikoner

Du kan legge ikon rett inn i `Dropdown.Item`, dersom det blir mye mellomrom til kanten kan du legge på din egen klasse og endre på `padding`.

<Canvas of={DropdownStories.Icons} />

### Uten Trigger

`Dropdown` bruker popover APIet, så du kan bruke `Dropdown` uten `Dropdown.Trigger`.
Du må da legge til `popovertarget={id}``Dropdown`, og `id``Dropdown`.

<Canvas of={DropdownStories.WithoutTrigger} />

## Tilgjengelighet

Det er innebygd tilgjengelighet i `Dropdown.Trigger` med `aria-expanded={true/false}` i henhold til åpne/lukket tilstand, og `aria-haspopup='menu'`.

### `Dropdown.List`

<ArgTypes of={Dropdown.List} />

### `Dropdown.Trigger`

Triggeren er en [Button](/docs/komponenter-button--docs) som standard.

Bruk `Dropdown.Trigger` til å aktivere `Dropdown`. Du kan bruke `asChild` for å endre `Dropdown.Trigger` elementet.
Dersom du skal legge på funksjoner som `onClick`, legg det på ditt element, og legg `asChild``Dropdown.Trigger`.

### Referanser

Vi bruker `ul` og `li` tags i dropdownen, valget er basert på denne:

- https://www.w3.org/WAI/tutorials/menus/flyout/#flyoutnavkbbtn
- https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/../Dropdown.stories.
Loading

0 comments on commit 7dceadd

Please sign in to comment.