Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat!: Remove form from Dialog #1582

Merged
merged 12 commits into from
Sep 17, 2024
15 changes: 7 additions & 8 deletions packages/css/src/components/dialog/dialog.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
background-color: var(--ams-dialog-background-color);
border: var(--ams-dialog-border);
inline-size: var(--ams-dialog-inline-size);
max-block-size: var(--ams-dialog-max-block-size);
max-inline-size: var(--ams-dialog-max-inline-size);

@include reset-dialog;
Expand All @@ -24,16 +23,16 @@
}
}

.ams-dialog__form {
.ams-dialog__wrapper {
display: grid;
gap: var(--ams-dialog-form-gap);
padding-block: var(--ams-dialog-form-padding-block);
padding-inline: var(--ams-dialog-form-padding-inline);
gap: var(--ams-dialog-wrapper-gap);
grid-template-rows: auto 1fr auto;
max-block-size: var(--ams-dialog-wrapper-max-block-size);
padding-block: var(--ams-dialog-wrapper-padding-block);
padding-inline: var(--ams-dialog-wrapper-padding-inline);
}

.ams-dialog__article {
display: grid;
gap: var(--ams-space-md); /* Until we have a consistent way of spacing text elements */
.ams-dialog__content {
max-block-size: 100%; /* Safari */
overflow-y: auto;
overscroll-behavior-y: contain;
Expand Down
12 changes: 7 additions & 5 deletions packages/react/src/Dialog/Dialog.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,18 @@ describe('Dialog', () => {
expect(getByText('Test content')).toBeInTheDocument()
})

it('renders actions when provided', () => {
const { getByText } = render(<Dialog heading="Test heading" actions={<button>Click Me</button>} />)
it('renders footer when provided', () => {
const { getByText } = render(<Dialog heading="Test heading" footer={<button>Click Me</button>} />)

expect(getByText('Click Me')).toBeInTheDocument()
})

it('does not render actions when not provided', () => {
const { queryByText } = render(<Dialog heading="Test heading" />)
it('does not render footer when not provided', () => {
const { container } = render(<Dialog heading="Test heading" />)

expect(queryByText('Click Me')).not.toBeInTheDocument()
const component = container.querySelector('footer')

expect(component).not.toBeInTheDocument()
})

it('renders DialogClose button', () => {
Expand Down
12 changes: 6 additions & 6 deletions packages/react/src/Dialog/Dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { IconButton } from '../IconButton'

export type DialogProps = {
/** The button(s) in the footer. Start with a primary button. */
actions?: ReactNode
footer?: ReactNode
/** The label for the button that dismisses the Dialog. */
closeButtonLabel?: string
/** The text for the Heading. */
Expand All @@ -23,18 +23,18 @@ const openDialog = (id: string) => (document.querySelector(id) as HTMLDialogElem

const DialogRoot = forwardRef(
(
{ actions, children, className, closeButtonLabel = 'Sluiten', heading, ...restProps }: DialogProps,
{ footer, children, className, closeButtonLabel = 'Sluiten', heading, ...restProps }: DialogProps,
ref: ForwardedRef<HTMLDialogElement>,
) => (
<dialog {...restProps} ref={ref} className={clsx('ams-dialog', className)}>
<form className="ams-dialog__form" method="dialog">
<div className="ams-dialog__wrapper">
<header className="ams-dialog__header">
<Heading size="level-4">{heading}</Heading>
<IconButton label={closeButtonLabel} onClick={closeDialog} size="level-4" type="button" />
</header>
<article className="ams-dialog__article">{children}</article>
{actions && <footer className="ams-dialog__footer">{actions}</footer>}
</form>
<div className="ams-dialog__content">{children}</div>
{footer && <footer className="ams-dialog__footer">{footer}</footer>}
</div>
</dialog>
),
)
Expand Down
4 changes: 2 additions & 2 deletions proprietary/tokens/src/components/ams/dialog.tokens.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
"background-color": { "value": "{ams.color.primary-white}" },
"border": { "value": "0" },
"inline-size": { "value": "calc(100% - 2 * {ams.space.grid.md})" },
"max-block-size": { "value": "calc(100% - 2 * {ams.space.grid.md})" },
"max-inline-size": { "value": "48rem" },
"form": {
"wrapper": {
"gap": { "value": "{ams.space.md}" },
"max-block-size": { "value": "calc(100dvh - 4 * {ams.space.grid.md})" },
alimpens marked this conversation as resolved.
Show resolved Hide resolved
"padding-block": { "value": "{ams.space.grid.md}" },
"padding-inline": { "value": "{ams.space.grid.lg}" }
},
Expand Down
12 changes: 11 additions & 1 deletion storybook/src/components/Dialog/Dialog.docs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,21 @@ import README from "../../../../packages/css/src/components/dialog/README.md?raw

## Examples

### Form in a Dialog

Set `method="dialog"` when using a form in Dialog.
This closes the Dialog when submitting the form.
Pass the submit Button to the `footer` prop,
and link it to the form by passing its `id` to the Buttons `form` attribute.
The Dialog returns the value of the submit Button, so you can check which Button was clicked.
dlnr marked this conversation as resolved.
Show resolved Hide resolved

<Canvas of={DialogStories.FormDialog} />

### With scrollbar

Content taller than the dialog itself will scroll.

<Canvas of={DialogStories.WithScrollbar} className="ams-dialog-story" />
<Canvas of={DialogStories.WithScrollbar} />

### Trigger Button

Expand Down
80 changes: 62 additions & 18 deletions storybook/src/components/Dialog/Dialog.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,10 @@ const meta = {
title: 'Components/Containers/Dialog',
component: Dialog,
args: {
actions: (
<>
<Button type="submit">Doorgaan</Button>
<Button onClick={Dialog.close} variant="tertiary">
Stoppen
</Button>
</>
footer: (
<Button onClick={Dialog.close} variant="primary">
Sluiten
</Button>
),
children: (
<Paragraph>
Expand All @@ -28,7 +25,7 @@ const meta = {
heading: 'Niet alle gegevens zijn opgeslagen',
},
argTypes: {
actions: {
footer: {
table: { disable: true },
},
},
Expand Down Expand Up @@ -65,35 +62,72 @@ export const Default: Story = {
},
}

export const FormDialog: Story = {
args: {
open: true,
footer: (
<>
<Button type="submit" form="dialog1" value="continue">
alimpens marked this conversation as resolved.
Show resolved Hide resolved
Doorgaan
</Button>
<Button onClick={Dialog.close} variant="tertiary">
Stoppen
</Button>
</>
),
children: (
<form method="dialog" id="dialog1">
<Paragraph>
Weet u zeker dat u door wilt gaan met het uitvoeren van deze actie? Dat verwijdert gegevens die nog niet
opgeslagen zijn.
</Paragraph>
</form>
),
},
decorators: [
(Story) => (
<div style={{ backgroundColor: '#0006', position: 'absolute', width: '100%', height: '100%' }}>
<Story />
</div>
),
],
parameters: {
docs: {
story: { height: '32em' },
},
layout: 'fullscreen',
},
}

export const WithScrollbar: Story = {
args: {
actions: <Button onClick={Dialog.close}>Sluiten</Button>,
footer: <Button onClick={Dialog.close}>Sluiten</Button>,
children: [
<Heading level={2} size="level-5" key={1}>
<Heading level={2} size="level-5" key={1} className="ams-mb--sm">
Algemeen
</Heading>,
<Paragraph key={2}>
<Paragraph key={2} className="ams-mb--sm">
De gemeente Amsterdam verwerkt bij de uitvoering van haar taken en verplichtingen persoonsgegevens. De manier
waarop de gemeente Amsterdam om gaat met persoonsgegevens is vastgelegd in het stedelijk kader verwerken
persoonsgegevens.
</Paragraph>,
<Paragraph key={3}>
<Paragraph key={3} className="ams-mb--sm">
Deze verklaring geeft aanvullende informatie over de omgang met persoonsgegevens door de gemeente Amsterdam en
over uw mogelijkheden tot het uitoefenen van uw rechten met betrekking tot persoonsgegevens.
</Paragraph>,
<Paragraph key={4}>
<Paragraph key={4} className="ams-mb--sm">
Meer specifieke informatie over privacy en de verwerking van persoonsgegevens door de gemeente Amsterdam kunt u
op de hoofdpagina vinden.
</Paragraph>,
<Paragraph key={5}>
<Paragraph key={5} className="ams-mb--sm">
Vanwege nieuwe wetgeving of andere ontwikkelingen, past de gemeente regelmatig haar processen aan. Dit kunnen
ook wijzigingen zijn in de wijze van het verwerken van persoonsgegevens. Wij raden u daarom aan om regelmatig
deze pagina te bekijken. Deze pagina wordt doorlopend geactualiseerd.
</Paragraph>,
<Heading level={2} size="level-5" key={6}>
<Heading level={2} size="level-5" key={6} className="ams-mb--sm">
Geldende wet- en regelgeving en reikwijdte
</Heading>,
<Paragraph key={7}>
<Paragraph key={7} className="ams-mb--sm">
Vanaf 25 mei 2018 is de Algemene verordening gegevensbescherming (Avg) van toepassing op alle verwerkingen van
persoonsgegevens. Deze Europese wetgeving heeft directe werking in Nederland. Voor die zaken die nationaal
geregeld moeten worden, is de Uitvoeringswet Avg in Nederland aanvullend van toepassing. Deze wetteksten kunt u
Expand Down Expand Up @@ -134,14 +168,24 @@ export const TriggerButton: Story = {

export const VerticalButtons: Story = {
args: {
actions: (
footer: (
<>
<Button type="submit">Lange teksten op deze knoppen</Button>
<Button type="submit" form="dialog2">
Lange teksten op deze knoppen
</Button>
<Button onClick={Dialog.close} variant="tertiary">
Om verticaal stapelen te demonstreren
</Button>
</>
),
children: (
<form method="dialog" id="dialog2">
<Paragraph>
Weet u zeker dat u door wilt gaan met het uitvoeren van deze actie? Dat verwijdert gegevens die nog niet
opgeslagen zijn.
</Paragraph>
</form>
),
open: true,
},
decorators: [
Expand Down