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
11 changes: 6 additions & 5 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,11 +23,13 @@
}
}

.ams-dialog__form {
.ams-dialog__content {
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-content-gap);
grid-template-rows: auto 1fr auto;
max-block-size: var(--ams-dialog-content-max-block-size);
padding-block: var(--ams-dialog-content-padding-block);
padding-inline: var(--ams-dialog-content-padding-inline);
}

.ams-dialog__article {
Expand Down
6 changes: 3 additions & 3 deletions packages/react/src/Dialog/Dialog.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,13 @@ 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', () => {
it('does not render footer when not provided', () => {
const { queryByText } = render(<Dialog heading="Test heading" />)

expect(queryByText('Click Me')).not.toBeInTheDocument()
alimpens marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
10 changes: 5 additions & 5 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__content">
<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>
alimpens marked this conversation as resolved.
Show resolved Hide resolved
{actions && <footer className="ams-dialog__footer">{actions}</footer>}
</form>
{footer && <footer className="ams-dialog__footer">{footer}</footer>}
</div>
</dialog>
),
)
Expand Down
6 changes: 3 additions & 3 deletions proprietary/tokens/src/components/ams/dialog.tokens.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
"dialog": {
"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})" },
"inline-size": { "value": "calc(100dvw - 2 * {ams.space.grid.md})" },
"max-inline-size": { "value": "48rem" },
"form": {
"content": {
"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: 12 additions & 0 deletions storybook/src/components/Dialog/Dialog.docs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@ import README from "../../../../packages/css/src/components/dialog/README.md?raw

## Examples

### Form dialog

The `<form method="dialog">` element is a practical way to manage dialogs.
It simplifies the process by automatically handling the closure and data submission
when a user interacts with a submit or cancel button. For more complex scenarios,
developers can opt for custom handling by adding the form as a child element.
Additionally, creating sticky buttons in a dialog's footer is achievable by placing
a submit button outside the `<form>` and associating it with the form's ID using the
`form` attribute.
dlnr marked this conversation as resolved.
Show resolved Hide resolved

<Canvas of={DialogStories.FormDialog} className="ams-dialog-story" />
alimpens marked this conversation as resolved.
Show resolved Hide resolved

### With scrollbar

Content taller than the dialog itself will scroll.
Expand Down
66 changes: 55 additions & 11 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,9 +62,46 @@ 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}>
Algemeen
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