An overlay shown above other content in the application.
The HTML <dialog> element can be used to build dialogs. However, it is not yet widely supported across browsers, and building fully accessible custom dialogs from scratch is very difficult and error prone. Dialog helps achieve accessible dialogs that can be styled as needed.
Prop | Type | Default |
---|---|---|
Space | Opens/closes the dialog. | |
Enter | Opens/closes the dialog. | |
Tab | Moves focus to the next focusable element. | |
Shift + Tab | Moves focus to the previous focusable element. | |
Esc | Closes the dialog and moves focus to the DialogTrigger. |
The DialogTrigger component does not render any DOM elements. It only passes through its children.
Prop | Type | Default | Description |
---|---|---|---|
children * | ReactNode | DialogTrigger needs at least two children: a <Button> and a <Dialog>. | |
isOpen | boolean | Whether the overlay is open by default (controlled). | |
defaultOpen | boolean | Whether the overlay is open by default (uncontrolled). |
Name | Type | Description |
---|---|---|
onOpenChange | (isOpen: boolean) => void | Handler that is called when the overlay's open state changes. |
A dialog is an overlay shown above other content in an application.
Prop | Type | Default | Description |
---|---|---|---|
alert | boolean | false | Whether the dialog is an alert dialog. |
side | 'center' | 'left' | 'right' | 'top' | 'bottom' | 'center' | Side of the screen the dialog will open from. |
children | ReactNode | (opts: DialogRenderProps) => ReactNode | Children of the dialog. A function may be provided to access a function to close the dialog. | |
className | string | (values: ButtonRenderProps) => string | The CSS className for the element. A function may be provided to compute the class based on component state. | |
style | CSSProperties | The inline style for the element. |
Name | Type | Description |
---|---|---|
id | string | The element's unique identifier. |
aria-label | string | Defines a string value that labels the current element. |
aria-labelledby | string | Identifies the element (or elements) that labels the current element. |
aria-describedby | string | Identifies the element (or elements) that describes the object. |
aria-details | string | Identifies the element (or elements) that provide a detailed, extended description for the object. |
The <DialogTitle>
has the same props as an <H2>
and is mandatory so assistive technology announces the dialog correctly.
If you want to visually hide the title, wrap it with <VisuallyHidden>
.
<DialogTrigger> <Button variant="primary">Create new post</Button> <Dialog> {({ close }) => ( <> <VisuallyHidden> <DialogTitle>What is happening?!</DialogTitle> </VisuallyHidden> <div className="flex items-start space-x-4"> <div className="flex-shrink-0"> <img className="inline-block h-10 w-10 rounded-full" src="https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt="" /> </div> <div className="min-w-0 flex-1"> <div className="border-b border-muted-200 focus-within:border-brand"> <label htmlFor="comment" className="sr-only"> What is happening?! </label> <textarea rows={3} name="comment" id="comment" className="block w-full resize-none border-0 border-b border-transparent p-0 pb-2 text-muted-900 outline-none placeholder:text-muted-400 focus:border-brand focus:ring-0 sm:text-sm sm:leading-6" placeholder="What is happening?!" defaultValue={''} /> </div> <div className="flex justify-between pt-2"> <div className="flex items-center"> <div className="flow-root"> <Button variant="ghost" size="sm" type="button" className="text-muted-400"> <Icon name="image" className="h-5 w-5" /> <span className="sr-only">Attach an image</span> </Button> <Button variant="ghost" size="sm" type="button" className="text-muted-400"> <Icon name="calendar" className="h-5 w-5" /> <span className="sr-only">Schedule</span> </Button> </div> </div> <div className="flex-shrink-0"> <Button type="submit" onPress={close}> Post </Button> </div> </div> </div> </div> </> )} </Dialog></DialogTrigger>
Here's the <Dialog />
component in action.
And here are all the variantions of the dialog.
An alert dialog should be used when the user can't continue without addressing the dialog. He can choose an option or press Escape, but he can't click away.
When the dialog opens, make sure the Cancel button has focus to avoid accidental actions.
Also don't label the cancellation button with the text "Close"; use "Cancel/Undo/etc" to make it clear for the user that the confirmation has been denied.
/* ### Modals ### */@layer components { /* Dialog */ .dialog { @apply relative outline-none; } .dialog-title { @apply my-0 text-size-2xl font-semibold leading-6 text-muted-700; }}