Merge branch 'master' into bui-fix-table-sorting
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -0,0 +1,107 @@
|
||||
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,
|
||||
dialogFixedWidthAndHeightSnippet,
|
||||
dialogWithFormSnippet,
|
||||
dialogWithNoTriggerSnippet,
|
||||
dialogCloseSnippet,
|
||||
} 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
|
||||
|
||||
### DialogTrigger
|
||||
|
||||
Wraps a trigger element and the dialog content to handle open/close state.
|
||||
|
||||
<PropsTable data={dialogTriggerPropDefs} />
|
||||
|
||||
### Dialog
|
||||
|
||||
The main dialog container that renders as a modal overlay.
|
||||
|
||||
<PropsTable data={dialogPropDefs} />
|
||||
|
||||
### 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} />
|
||||
|
||||
If you want to close the dialog while pressing a button, you can use the `slot="close"` prop on the button.
|
||||
|
||||
<CodeBlock code={dialogCloseSnippet} />
|
||||
|
||||
## Examples
|
||||
|
||||
### Fixed Width and Height
|
||||
|
||||
Dialog with a fixed height body that scrolls when content overflows.
|
||||
|
||||
<Snippet
|
||||
align="center"
|
||||
py={4}
|
||||
preview={<DialogSnippet story="PreviewFixedWidthAndHeight" />}
|
||||
code={dialogFixedWidthAndHeightSnippet}
|
||||
/>
|
||||
|
||||
### Dialog with Form
|
||||
|
||||
Dialog containing form elements for user input.
|
||||
|
||||
<Snippet
|
||||
align="center"
|
||||
py={4}
|
||||
preview={<DialogSnippet story="PreviewWithForm" />}
|
||||
code={dialogWithFormSnippet}
|
||||
/>
|
||||
|
||||
### Dialog with no trigger and controlled by props
|
||||
|
||||
You can also control the dialog using your own states.
|
||||
|
||||
<CodeBlock code={dialogWithNoTriggerSnippet} />
|
||||
|
||||
<Theming component="Dialog" />
|
||||
|
||||
<ChangelogComponent component="dialog" />
|
||||
@@ -0,0 +1,172 @@
|
||||
import {
|
||||
classNamePropDefs,
|
||||
stylePropDefs,
|
||||
type PropDef,
|
||||
} from '@/utils/propDefs';
|
||||
|
||||
export const dialogTriggerPropDefs: Record<string, PropDef> = {
|
||||
children: { type: 'enum', values: ['ReactNode'], responsive: false },
|
||||
isOpen: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the overlay is open by default (controlled).',
|
||||
},
|
||||
defaultOpen: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the overlay is open by default (uncontrolled).',
|
||||
},
|
||||
onOpenChange: {
|
||||
type: 'enum',
|
||||
values: ['(isOpen: boolean) => void'],
|
||||
description:
|
||||
"Handler that is called when the overlay's open state changes.",
|
||||
},
|
||||
};
|
||||
|
||||
export const dialogPropDefs: Record<string, PropDef> = {
|
||||
children: { type: 'enum', values: ['ReactNode'], responsive: false },
|
||||
isOpen: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the overlay is open by default (controlled).',
|
||||
},
|
||||
defaultOpen: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the overlay is open by default (uncontrolled).',
|
||||
},
|
||||
onOpenChange: {
|
||||
type: 'enum',
|
||||
values: ['(isOpen: boolean) => void'],
|
||||
description:
|
||||
"Handler that is called when the overlay's open state changes.",
|
||||
},
|
||||
width: {
|
||||
type: 'enum',
|
||||
values: ['number', 'string'],
|
||||
responsive: false,
|
||||
},
|
||||
height: {
|
||||
type: 'enum',
|
||||
values: ['number', 'string'],
|
||||
responsive: false,
|
||||
},
|
||||
...classNamePropDefs,
|
||||
...stylePropDefs,
|
||||
};
|
||||
|
||||
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,
|
||||
} from '@backstage/ui';
|
||||
|
||||
<DialogTrigger>
|
||||
<Button>Open Dialog</Button>
|
||||
<Dialog>
|
||||
<DialogHeader>Title</DialogHeader>
|
||||
<DialogBody>Content</DialogBody>
|
||||
<DialogFooter>
|
||||
<Button variant="secondary" slot="close">Close</Button>
|
||||
</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.</Text>
|
||||
</DialogBody>
|
||||
<DialogFooter>
|
||||
<Button variant="secondary" slot="close">Close</Button>
|
||||
<Button variant="primary" slot="close">Save</Button>
|
||||
</DialogFooter>
|
||||
</Dialog>
|
||||
</DialogTrigger>`;
|
||||
|
||||
export const dialogFixedWidthAndHeightSnippet = `<DialogTrigger>
|
||||
<Button variant="secondary">Scrollable Dialog</Button>
|
||||
<Dialog>
|
||||
<DialogHeader>Long Content Dialog</DialogHeader>
|
||||
<DialogBody width={600} height={400}>
|
||||
...
|
||||
</DialogBody>
|
||||
<DialogFooter>
|
||||
<Button variant="secondary" slot="close">Cancel</Button>
|
||||
<Button variant="primary" slot="close">Accept</Button>
|
||||
</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>
|
||||
<Button variant="secondary" slot="close">Cancel</Button>
|
||||
<Button variant="primary" slot="close">Create User</Button>
|
||||
</DialogFooter>
|
||||
</Dialog>
|
||||
</DialogTrigger>`;
|
||||
|
||||
export const dialogWithNoTriggerSnippet = `const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
<Dialog isOpen={isOpen} onOpenChange={setIsOpen}>
|
||||
<DialogHeader>Create New User</DialogHeader>
|
||||
<DialogBody>
|
||||
Your content
|
||||
</DialogBody>
|
||||
<DialogFooter>
|
||||
<Button variant="secondary" slot="close">Cancel</Button>
|
||||
<Button variant="primary" slot="close">Create User</Button>
|
||||
</DialogFooter>
|
||||
</Dialog>`;
|
||||
|
||||
export const dialogCloseSnippet = `<Button slot="close">Close</Button>`;
|
||||
@@ -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';
|
||||
@@ -63,6 +64,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);
|
||||
|
||||
@@ -101,6 +101,11 @@ export const components: Page[] = [
|
||||
slug: 'collapsible',
|
||||
status: 'alpha',
|
||||
},
|
||||
{
|
||||
title: 'Dialog',
|
||||
slug: 'dialog',
|
||||
status: 'alpha',
|
||||
},
|
||||
{
|
||||
title: 'Header',
|
||||
slug: 'header',
|
||||
|
||||
Reference in New Issue
Block a user