Dialog

A window overlaid on either the primary window or another dialog window.

Features

  • Supports modal and non-modal modes
  • Customizable focus management
  • Waits for pending animations before removing the dialog from the DOM
  • Pressing the escape key and interacting outside closes the dialog
  • Supports nested dialogs

Usage

import Dialog from 'corvu/dialog'
// Or
// import { Root, Trigger, ... } from 'corvu/dialog'

Anatomy

<Dialog.Root>
  <Dialog.Trigger />
  <Dialog.Portal>
    <Dialog.Overlay />
    <Dialog.Content>
      <Dialog.Close />
      <Dialog.Label />
      <Dialog.Description />
    </Dialog.Content>
  </Dialog.Portal>
</Dialog.Root>

Scrolling

By default, corvu prevents scrolling of elements outside of the dialog content while the dialog open. It will also add additional padding to the body to prevent the page from jumping when the scrollbar disappears. There is also a CSS variable called --scrollbar-width which is present when the scrollbar is hidden. You can use this to prevent any fixed element from jumping:

<header
  class="fixed top-0 inset-x-0 z-50"
  style={{
    'padding-right': 'var(--scrollbar-width, 0)',
  }}
>
  Header
</header>

Nested dialogs

Feel free to nest dialogs however you want. Corvu is aware of nested dialogs and only dismisses the top-most dialog when you press the escape key or click outside the dialog.

Accessibility

Adheres to the Dialog WAI-ARIA design pattern and Alert Dialog WAI-ARIA design pattern.

API reference

Dialog.Root

Component

Context wrapper for the dialog. Is required for every dialog you create.

Props

role

'dialog' | 'alertdialog'

The role attribute of the dialog element. *Default = 'dialog'*

open

boolean

Whether the dialog is open or not.

onOpenChange

(open: boolean) => void

Callback fired when the open state changes.

initialOpen

boolean

Whether the dialog is open initially or not. *Default = false*

modal

boolean

Whether the dialog should be rendered as a modal or not. *Default = true*

closeOnEscapeKeyDown

boolean

Whether the dialog should close when the user presses the Escape key. *Default = true*

onEscapeKeyDown

(event: KeyboardEvent) => void

Callback fired when the user presses the Escape key. Can be prevented by calling event.preventDefault.

closeOnOutsidePointerDown

boolean

Whether the dialog should be closed if the user interacts outside the bounds of <​Dialog.Content />. *Default = true if modal is true, false otherwise*

onOutsidePointerDown

(event: MouseEvent) => void

Callback fired when the user interacts outside the bounds of <​Dialog.Content />. Can be prevented by calling event.preventDefault.

noOutsidePointerEvents

boolean

Whether pointer events outside of <​Dialog.Content /> should be disabled. *Default = true if modal is true, false otherwise*

preventScroll

boolean

Whether scroll outside of the dialog should be prevented. *Default = true if modal is true, false otherwise*

hideScrollbar

boolean

Whether the scrollbar of the <​body> element should be hidden. *Default = true if modal is true, false otherwise*

preventScrollbarShift

boolean

Whether padding should be added to the <​body> element to avoid layout shift. *Default = true*

preventScrollbarShiftMode

'padding' | 'margin'

Whether padding or margin should be used to avoid layout shift. *Default = 'padding'*

trapFocus

boolean

Whether the dialog should trap focus or not. *Default = true*

restoreFocus

boolean

Whether the dialog should restore focus to the previous active element when it closes. *Default = true*

initialFocusEl

HTMLElement

The element to receive focus when the dialog opens.

onInitialFocus

(event: Event) => void

Callback fired when focus moves into the dialog. Can be prevented by calling event.preventDefault.

finalFocusEl

HTMLElement

The element to receive focus when the dialog closes.

onFinalFocus

(event: Event) => void

Callback fired when focus moves out of the dialog. Can be prevented by calling event.preventDefault.

dialogId

string

The id attribute of the dialog element. *Default = A unique id.*

labelId

string

The id attribute of the dialog label element. *Default = A unique id.*

descriptionId

string

The id attribute of the dialog description element. *Default = A unique id.*

contextId

string

The id of the dialog context. Useful if you have nested dialogs and want to create components that belong to a dialog higher up in the tree.

children

JSX.Element | (props: DialogRootChildrenProps) => JSX.Element

Dialog.Trigger

Component

Button that changes the open state of the dialog when clicked.

Props

as

ValidComponent

Default: button

Component to render the polymorphic component as. *Default = div*

asChild

boolean

Whether to render the polymorphic component as the first <​As /> component found in its children. *Default = false*

contextId

string

The id of the dialog context to use.

Data

Data attributes present on primitives/dialog.Trigger components.

data-corvu-dialog-trigger

Present on every dialog trigger element.

data-open

Present when the dialog is open.

data-closed

Present when the dialog is closed.

Dialog.Portal

Component

Portals its children at the end of the body element to ensure that the dialog always rendered on top.

Props

forceMount

boolean

Whether the dialog portal should be forced to render. Useful when using third-party animation libraries.

contextId

string

The id of the dialog context to use.

Dialog.Overlay

Component

Component which can be used to create a faded background. Can be animated.

Props

as

ValidComponent

Default: div

Component to render the polymorphic component as. *Default = div*

asChild

boolean

Whether to render the polymorphic component as the first <​As /> component found in its children. *Default = false*

forceMount

boolean

Whether the dialog overlay should be forced to render. Useful when using third-party animation libraries.

contextId

string

The id of the dialog context to use.

Data

Data attributes present on primitives/dialog.Overlay components.

data-corvu-dialog-overlay

Present on every dialog overlay element.

data-open

Present when the dialog is open.

data-closed

Present when the dialog is closed.

Dialog.Content

Component

Content of the dialog. Can be animated.

Props

as

ValidComponent

Default: div

Component to render the polymorphic component as. *Default = div*

asChild

boolean

Whether to render the polymorphic component as the first <​As /> component found in its children. *Default = false*

forceMount

boolean

Whether the dialog content should be forced to render. Useful when using third-party animation libraries.

contextId

string

The id of the dialog context to use.

Data

Data attributes present on primitives/dialog.Content components.

data-corvu-dialog-content

Present on every dialog content element.

data-open

Present when the dialog is open.

data-closed

Present when the dialog is closed.

Dialog.Close

Component

Close button that changes the open state to false when clicked.

Props

as

ValidComponent

Default: button

Component to render the polymorphic component as. *Default = div*

asChild

boolean

Whether to render the polymorphic component as the first <​As /> component found in its children. *Default = false*

contextId

string

The id of the dialog context to use.

Data

Data attributes present on primitives/dialog.Close components.

data-corvu-dialog-close

Present on every dialog close element.

Dialog.Label

Component

Label element to announce the dialog to accessibility tools.

Props

as

ValidComponent

Default: h2

Component to render the polymorphic component as. *Default = div*

asChild

boolean

Whether to render the polymorphic component as the first <​As /> component found in its children. *Default = false*

contextId

string

The id of the dialog context to use.

Data

Data attributes present on primitives/dialog.Label components.

data-corvu-dialog-label

Present on every dialog label element.

Dialog.Description

Component

Description element to announce the dialog to accessibility tools.

Props

as

ValidComponent

Default: p

Component to render the polymorphic component as. *Default = div*

asChild

boolean

Whether to render the polymorphic component as the first <​As /> component found in its children. *Default = false*

contextId

string

The id of the dialog context to use.

Data

Data attributes present on primitives/dialog.Description components.

data-corvu-dialog-description

Present on every dialog description element.

Dialog.useContext

Context

Context which exposes various properties to interact with the dialog. Optionally provide a contextId to access a keyed context.

Returns

contentRef

Accessor<HTMLElement | 'null'>

The ref of the dialog content.

overlayRef

Accessor<HTMLElement | 'null'>

The ref of the dialog overlay.

role

Accessor<'dialog' | 'alertdialog'>

The role attribute of the dialog element.

open

Accessor<boolean>

Whether the dialog is open or not.

contentPresent

Accessor<boolean>

Whether the dialog content is present. This differes from open as it tracks pending animations.

overlayPresent

Accessor<boolean>

Whether the dialog overlay is present. This differes from open as it tracks pending animations.

setOpen

Setter<boolean>

Change the open state of the dialog.

modal

Accessor<boolean>

Whether the dialog should be rendered as a modal or not.

closeOnEscapeKeyDown

Accessor<boolean>

Whether the dialog should close when the user presses the Escape key.

closeOnOutsidePointerDown

Accessor<boolean>

Whether the dialog should be closed if the user interacts outside the bounds of <​Dialog.Content />.

noOutsidePointerEvents

Accessor<boolean>

Whether pointer events outside of <​Dialog.Content /> should be disabled.

preventScroll

Accessor<boolean>

Whether scroll outside of the dialog should be prevented.

hideScrollbar

Accessor<boolean>

Whether the scrollbar of the <​body> element should be hidden.

preventScrollbarShift

Accessor<boolean>

Whether padding should be added to the <​body> element to avoid layout shift.

preventScrollbarShiftMode

Accessor<'padding' | 'margin'>

Whether padding or margin should be used to avoid layout shift.

trapFocus

Accessor<boolean>

Whether the dialog should trap focus or not.

restoreFocus

Accessor<boolean>

Whether the dialog should restore focus to the previous active element when it closes.

initialFocusEl

Accessor<HTMLElement | undefined>

The element to receive focus when the dialog opens.

finalFocusEl

Accessor<HTMLElement | undefined>

The element to receive focus when the dialog closes.

dialogId

Accessor<string>

The id attribute of the dialog element.

labelId

Accessor<string | undefined>

The id attribute of the dialog label element. Is undefined if no Dialog.Label is present.

descriptionId

Accessor<string | undefined>

The id attribute of the dialog description element. Is undefined if no Dialog.Description is present.

Dialog.RootChildrenProps

Type

Props which are passed to the Root component children function.

Props

contentRef

HTMLElement | 'null'

The ref of the dialog content.

overlayRef

HTMLElement | 'null'

The ref of the dialog overlay.

role

'dialog' | 'alertdialog'

The role attribute of the dialog element.

open

boolean

Whether the dialog is open or not.

contentPresent

boolean

Whether the dialog content is present. This differes from open as it tracks pending animations.

overlayPresent

boolean

Whether the dialog overlay is present. This differes from open as it tracks pending animations.

setOpen

Setter<boolean>

Change the open state of the dialog.

modal

boolean

Whether the dialog should be rendered as a modal or not.

closeOnEscapeKeyDown

boolean

Whether the dialog should close when the user presses the Escape key.

closeOnOutsidePointerDown

boolean

Whether the dialog should be closed if the user interacts outside the bounds of the dialog content.

noOutsidePointerEvents

boolean

Whether pointer events outside of <​Dialog.Content /> should be disabled.

preventScroll

boolean

Whether scroll outside of the dialog should be prevented.

hideScrollbar

boolean

Whether the scrollbar of the <​body> element should be hidden.

preventScrollbarShift

boolean

Whether padding should be added to the <​body> element to avoid layout shift.

preventScrollbarShiftMode

'padding' | 'margin'

Whether padding or margin should be used to avoid layout shift.

trapFocus

boolean

Whether the dialog should trap focus or not.

restoreFocus

boolean

Whether the dialog should restore focus to the previous active element when it closes.

initialFocusEl

HTMLElement

The element to receive focus when the dialog opens.

finalFocusEl

HTMLElement

The element to receive focus when the dialog closes.

dialogId

string

The id attribute of the dialog description element.

labelId

string | undefined

The id attribute of the dialog label element. Is undefined if no Dialog.Label is present.

descriptionId

string | undefined

The id attribute of the dialog description element. Is undefined if no Dialog.Description is present.

corvu@0.2.1

Developed and designed by Jasmin