add documentation for dialog component

Signed-off-by: Sofia Sjöblad <ssjoblad@spotify.com>
This commit is contained in:
Sofia Sjöblad
2025-10-09 16:48:14 +02:00
parent 68036b78e8
commit c9778ca53e
6 changed files with 338 additions and 48 deletions
+101
View File
@@ -0,0 +1,101 @@
import { PropsTable } from '@/components/PropsTable';
import { Snippet } from '@/components/Snippet';
import { CodeBlock } from '@/components/CodeBlock';
import {DialogSnippet} from '@/snippets/stories-snippets';
import {
dialogPropDefs,
dialogTriggerPropDefs,
dialogHeaderPropDefs,
dialogBodyPropDefs,
dialogFooterPropDefs,
dialogClosePropDefs,
dialogUsageSnippet,
dialogDefaultSnippet,
dialogScrollableSnippet,
dialogWithFormSnippet,
} from './dialog.props';
import { PageTitle } from '@/components/PageTitle';
import { Theming } from '@/components/Theming';
import { ChangelogComponent } from '@/components/ChangelogComponent';
<PageTitle
title="Dialog"
description="A modal dialog component that displays content in an overlay window."
/>
<Snippet
align="center"
py={4}
preview={<DialogSnippet story="Default" />}
code={dialogDefaultSnippet}
/>
## Usage
<CodeBlock code={dialogUsageSnippet} />
## API reference
### Dialog
The main dialog container that renders as a modal overlay.
<PropsTable data={dialogPropDefs} />
### DialogTrigger
Wraps a trigger element and the dialog content to handle open/close state.
<PropsTable data={dialogTriggerPropDefs} />
### DialogHeader
Displays the dialog title with a built-in close button.
<PropsTable data={dialogHeaderPropDefs} />
### DialogBody
The main content area of the dialog with optional scrolling.
<PropsTable data={dialogBodyPropDefs} />
### DialogFooter
Contains action buttons or other footer content.
<PropsTable data={dialogFooterPropDefs} />
### DialogClose
A button that closes the dialog when pressed.
<PropsTable data={dialogClosePropDefs} />
## Examples
### Scrollable Content
Dialog with a fixed height body that scrolls when content overflows.
<Snippet
align="center"
py={4}
preview={<DialogSnippet story="Scrollable" />}
code={dialogScrollableSnippet}
/>
### Dialog with Form
Dialog containing form elements for user input.
<Snippet
align="center"
py={4}
preview={<DialogSnippet story="WithForm" />}
code={dialogWithFormSnippet}
/>
<Theming component="Dialog" />
<ChangelogComponent component="dialog" />
@@ -0,0 +1,139 @@
import {
classNamePropDefs,
stylePropDefs,
type PropDef,
} from '@/utils/propDefs';
export const dialogPropDefs: Record<string, PropDef> = {
children: { type: 'enum', values: ['ReactNode'], responsive: false },
...classNamePropDefs,
...stylePropDefs,
};
export const dialogTriggerPropDefs: Record<string, PropDef> = {
children: { type: 'enum', values: ['ReactNode'], responsive: false },
};
export const dialogHeaderPropDefs: Record<string, PropDef> = {
children: { type: 'enum', values: ['ReactNode'], responsive: false },
...classNamePropDefs,
...stylePropDefs,
};
export const dialogBodyPropDefs: Record<string, PropDef> = {
children: { type: 'enum', values: ['ReactNode'], responsive: false },
height: {
type: 'enum',
values: ['number', 'string'],
responsive: false,
},
...classNamePropDefs,
...stylePropDefs,
};
export const dialogFooterPropDefs: Record<string, PropDef> = {
children: { type: 'enum', values: ['ReactNode'], responsive: false },
...classNamePropDefs,
...stylePropDefs,
};
export const dialogClosePropDefs: Record<string, PropDef> = {
variant: {
type: 'enum',
values: ['primary', 'secondary', 'tertiary'],
default: 'secondary',
responsive: false,
},
children: { type: 'enum', values: ['ReactNode'], responsive: false },
...classNamePropDefs,
...stylePropDefs,
};
export const dialogUsageSnippet = `import {
Dialog,
DialogTrigger,
DialogHeader,
DialogBody,
DialogFooter,
DialogClose
} from '@backstage/ui';
<DialogTrigger>
<Button>Open Dialog</Button>
<Dialog>
<DialogHeader>Title</DialogHeader>
<DialogBody>Content</DialogBody>
<DialogFooter>
<DialogClose>Close</DialogClose>
</DialogFooter>
</Dialog>
</DialogTrigger>`;
export const dialogDefaultSnippet = `<DialogTrigger>
<Button variant="secondary">Open Dialog</Button>
<Dialog>
<DialogHeader>Example Dialog</DialogHeader>
<DialogBody>
<Text>This is a basic dialog example with React Aria Components.</Text>
</DialogBody>
<DialogFooter>
<DialogClose>Close</DialogClose>
<DialogClose variant="primary">Save</DialogClose>
</DialogFooter>
</Dialog>
</DialogTrigger>`;
export const dialogScrollableSnippet = `<DialogTrigger>
<Button variant="secondary">Scrollable Dialog</Button>
<Dialog>
<DialogHeader>Long Content Dialog</DialogHeader>
<DialogBody height={200}>
<Text>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat.
</Text>
<Text>
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum
dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</Text>
<Text>
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium
doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore
veritatis et quasi architecto beatae vitae dicta sunt explicabo.
</Text>
</DialogBody>
<DialogFooter>
<Flex gap="2" justify="end">
<DialogClose>Cancel</DialogClose>
<DialogClose variant="primary">Accept</DialogClose>
</Flex>
</DialogFooter>
</Dialog>
</DialogTrigger>`;
export const dialogWithFormSnippet = `<DialogTrigger>
<Button variant="secondary">Create User</Button>
<Dialog>
<DialogHeader>Create New User</DialogHeader>
<DialogBody>
<Flex direction="column" gap="3">
<TextField label="Name" placeholder="Enter full name" />
<TextField label="Email" placeholder="Enter email address" />
<Select label="Role">
<SelectItem>Admin</SelectItem>
<SelectItem>User</SelectItem>
<SelectItem>Viewer</SelectItem>
</Select>
</Flex>
</DialogBody>
<DialogFooter>
<Flex gap="2" justify="end">
<DialogClose>Cancel</DialogClose>
<DialogClose variant="primary">Create User</DialogClose>
</Flex>
</DialogFooter>
</Dialog>
</DialogTrigger>`;
@@ -17,6 +17,7 @@ import * as MenuStories from '../../../packages/ui/src/components/Menu/Menu.stor
import * as LinkStories from '../../../packages/ui/src/components/Link/Link.stories';
import * as AvatarStories from '../../../packages/ui/src/components/Avatar/Avatar.stories';
import * as CollapsibleStories from '../../../packages/ui/src/components/Collapsible/Collapsible.stories';
import * as DialogStories from '../../../packages/ui/src/components/Dialog/Dialog.stories';
import * as RadioGroupStories from '../../../packages/ui/src/components/RadioGroup/RadioGroup.stories';
import * as TabsStories from '../../../packages/ui/src/components/Tabs/Tabs.stories';
import * as SwitchStories from '../../../packages/ui/src/components/Switch/Switch.stories';
@@ -60,6 +61,7 @@ export const MenuSnippet = createSnippetComponent(MenuStories);
export const LinkSnippet = createSnippetComponent(LinkStories);
export const AvatarSnippet = createSnippetComponent(AvatarStories);
export const CollapsibleSnippet = createSnippetComponent(CollapsibleStories);
export const DialogSnippet = createSnippetComponent(DialogStories);
export const RadioGroupSnippet = createSnippetComponent(RadioGroupStories);
export const TabsSnippet = createSnippetComponent(TabsStories);
export const SwitchSnippet = createSnippetComponent(SwitchStories);
+5
View File
@@ -101,6 +101,11 @@ export const components: Page[] = [
slug: 'collapsible',
status: 'alpha',
},
{
title: 'Dialog',
slug: 'dialog',
status: 'alpha',
},
{
title: 'Header',
slug: 'header',