Alert Dialog
A modal window that alerts users with important information and awaits their acknowledgment or action.
Key Features
- Compound Component Structure: Offers a set of sub-components that work together to create a fully-featured alert dialog.
- Accessibility: Built with WAI-ARIA guidelines in mind, ensuring keyboard navigation and screen reader support.
- Customizable: Each sub-component can be styled and configured independently.
- Portal Support: Content can be rendered in a portal, ensuring proper stacking context.
- Managed Focus: Automatically manages focus, with the option to take control if needed.
- Flexible State Management: Supports both controlled and uncontrolled state, allowing for full control over the dialog's open state.
Architecture
The Alert Dialog component is composed of several sub-components, each with a specific role:
- Root: The main container component that manages the state of the dialog. Provides context for all child components.
- Trigger: A button that toggles the dialog's open state.
- Portal: Renders its children in a portal, outside the normal DOM hierarchy.
- Overlay: A backdrop that sits behind the dialog content.
- Content: The main container for the dialog's content.
- Title: Renders the dialog's title.
- Description: Renders a description or additional context for the dialog.
- Cancel: A button that closes the dialog by cancelling the action.
- Action: A button that closes the dialog by taking an action.
Structure
Reusable Components
Bits UI provides a decent number of components to construct an Alert Dialog. The idea is to provide a set of building blocks that can be used to create a variety of different components. It's recommended to use these components to build your own reusable Alert Dialog components that can be used throughout your application.
The following example shows at a high level how you might create a reusable Alert Dialog component. We've mixed and matched string props and snippets to demonstrate the flexibility of the component API. Use whatever makes sense for you.
This example is used in a few places throughout this documentation page to give you a better idea of how it's used.
You can then use the MyAlertDialog
component in your application like so:
Alternatively, you can define the snippets separately and pass them as props to the component:
Managing Open State
Bits UI offers several approaches to manage and synchronize the Alert Dialog's open state, catering to different levels of control and integration needs.
1. Two-Way Binding
For seamless state synchronization, use Svelte's bind:open
directive. This method automatically keeps your local state in sync with the dialog's internal state.
Key Benefits
- Simplifies state management
- Automatically updates isOpen when the dialog closes (e.g., via escape key)
- Allows external control (e.g., opening via a separate button)
2. Change Handler
For more granular control or to perform additional logic on state changes, use the onOpenChange
prop. This approach is useful when you need to execute custom logic alongside state updates.
Use Cases
- Implementing custom behaviors on open/close
- Integrating with external state management solutions
- Triggering side effects (e.g., logging, data fetching)
3. Fully Controlled
For complete control over the dialog's open state, use the controlledOpen
prop. This approach requires you to manually manage the open state, giving you full control over when and how the dialog responds to open/close events.
When to Use
- Implementing complex open/close logic
- Coordinating multiple UI elements
- Debugging state-related issues
Note
While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully.
For more in-depth information on controlled components and advanced state management techniques, refer to our Controlled State documentation.
Managing Focus
Focus Trap
By default, when a dialog is opened, focus will be trapped within the Dialog, preventing the user from interacting with the rest of the page. This follows the WAI-ARIA design pattern for alert dialogs.
Although it isn't recommended unless absolutely necessary, you can disabled this behavior by setting the trapFocus
prop to false
on the AlertDialog.Content
component.
Open Focus
By default, when a dialog is opened, focus will be set to the AlertDialog.Cancel
button if it exists, or the first focusable element within the AlertDialog.Content
. This ensures that users navigating my keyboard end up somewhere within the Dialog that they can interact with.
You can override this behavior using the onOpenAutoFocus
prop on the AlertDialog.Content
component. It's highly recommended that you use this prop to focus something within the Dialog.
You'll first need to cancel the default behavior of focusing the first focusable element by cancelling the event passed to the onOpenAutoFocus
callback. You can then focus whatever you wish.
Close Focus
By default, when a dialog is closed, focus will be set to the trigger element of the dialog. You can override this behavior using the onCloseAutoFocus
prop on the AlertDialog.Content
component.
You'll need to cancel the default behavior of focusing the trigger element by cancelling the event passed to the onCloseAutoFocus
callback, and then focus whatever you wish.
Advanced Behaviors
The Alert Dialog component offers several advanced features to customize its behavior and enhance user experience. This section covers scroll locking, escape key handling, and interaction outside the dialog.
Scroll Lock
By default, when an Alert Dialog opens, scrolling the body is disabled. This provides a more native-like experience, focusing user attention on the dialog content.
Customizing Scroll Behavior
To allow body scrolling while the dialog is open, use the preventScroll
prop on AlertDialog.Content
:
Note
Enabling body scroll may affect user focus and accessibility. Use this option judiciously.
Escape Key Handling
By default, pressing the Escape
key closes an open Alert Dialog. Bits UI provides two methods to customize this behavior.
Method 1: escapeKeydownBehavior
The escapeKeydownBehavior
prop allows you to customize the behavior taken by the component when the Escape
key is pressed. It accepts one of the following values:
'close'
(default): Closes the Alert Dialog immediately.'ignore'
: Prevents the Alert Dialog from closing.'defer-otherwise-close'
: If an ancestor Bits UI component also implements this prop, it will defer the closing decision to that component. Otherwise, the Alert Dialog will close immediately.'defer-otherwise-ignore'
: If an ancestor Bits UI component also implements this prop, it will defer the closing decision to that component. Otherwise, the Alert Dialog will ignore the key press and not close.
To always prevent the Alert Dialog from closing on Escape key press, set the escapeKeydownBehavior
prop to 'ignore'
on Dialog.Content
:
Method 2: onEscapeKeydown
For more granular control, override the default behavior using the onEscapeKeydown
prop:
This method allows you to implement custom logic when the Escape
key is pressed.
Interaction Outside
By default, interacting outside the Alert Dialog content area closes the Alert Dialog. Bits UI offers two ways to modify this behavior.
Method 1: interactOutsideBehavior
The interactOutsideBehavior
prop allows you to customize the behavior taken by the component when an interaction (touch, mouse, or pointer event) occurs outside the content. It accepts one of the following values:
'close'
(default): Closes the Alert Dialog immediately.'ignore'
: Prevents the Alert Dialog from closing.'defer-otherwise-close'
: If an ancestor Bits UI component also implements this prop, it will defer the closing decision to that component. Otherwise, the Alert Dialog will close immediately.'defer-otherwise-ignore'
: If an ancestor Bits UI component also implements this prop, it will defer the closing decision to that component. Otherwise, the Alert Dialog will ignore the event and not close.
To always prevent the Alert Dialog from closing on Escape key press, set the escapeKeydownBehavior
prop to 'ignore'
on Alert.Content
:
Method 2: onInteractOutside
For custom handling of outside interactions, you can override the default behavior using the onInteractOutside
prop:
This approach allows you to implement specific behaviors when users interact outside the Alert Dialog content.
Best Practices
- Scroll Lock: Consider your use case carefully before disabling scroll lock. It may be necessary for dialogs with scrollable content or for specific UX requirements.
- Escape Keydown: Overriding the default escape key behavior should be done thoughtfully. Users often expect the escape key to close modals.
- Outside Interactions: Ignoring outside interactions can be useful for important dialogs or multi-step processes, but be cautious not to trap users unintentionally.
- Accessibility: Always ensure that any customizations maintain or enhance the dialog's accessibility.
- User Expectations: Try to balance custom behaviors with common UX patterns to avoid confusing users.
By leveraging these advanced features, you can create highly customized dialog experiences while maintaining usability and accessibility standards.
Nested Dialogs
Dialogs can be nested within each other to create more complex layouts. See the Dialog component for more information on nested dialogs.
Svelte Transitions
See the Dialog component for more information on Svelte Transitions with dialog components.
Working with Forms
Form Submission
When using the AlertDialog
component, often you'll want to submit a form or perform an asynchronous action when the user clicks the Action
button.
This can be done by waiting for the asynchronous action to complete, then programmatically closing the dialog.
Inside a Form
If you're using an AlertDialog
within a form, you'll need to ensure that the Portal
is disabled or not included in the AlertDialog
structure. This is because the Portal
will render the dialog content outside of the form, which will prevent the form from being submitted correctly.
API Reference
The root component used to set and manage the state of the alert dialog.
Property | Type | Description |
---|---|---|
open $bindable | boolean | Whether or not the alert dialog is open. Default: false |
onOpenChange | function | A callback function called when the open state changes. Default: undefined |
controlledOpen | boolean | Whether or not the open state is controlled or not. If Default: false |
children | Snippet | The children content to render. Default: undefined |
The element which opens the alert dialog on press.
Property | Type | Description |
---|---|---|
ref $bindable | HTMLButtonElement | The underlying DOM element being rendered. You can bind to this to get a reference to the element. Default: undefined |
children | Snippet | The children content to render. Default: undefined |
child | Snippet | Use render delegation to render your own element. See Child Snippet docs for more information. Default: undefined |
Data Attribute | Value | Description |
---|---|---|
data-state | enum | The state of the alert dialog. |
data-alert-dialog-trigger | '' | Present on the trigger element. |
The content displayed within the alert dialog modal.
Property | Type | Description |
---|---|---|
onInteractOutside | function | Callback fired when an outside interaction event occurs, which is a Default: undefined |
onFocusOutside | function | Callback fired when focus leaves the dismissible layer. You can call Default: undefined |
interactOutsideBehavior | enum | The behavior to use when an interaction occurs outside of the floating content. Default: close |
onEscapeKeydown | function | Callback fired when an escape keydown event occurs in the floating content. You can call Default: undefined |
escapeKeydownBehavior | enum | The behavior to use when an escape keydown event occurs in the floating content. Default: close |
onOpenAutoFocus | function | Event handler called when auto-focusing the content as it is opened. Can be prevented. Default: undefined |
onCloseAutoFocus | function | Event handler called when auto-focusing the content as it is closed. Can be prevented. Default: undefined |
trapFocus | boolean | Whether or not to trap the focus within the content when open. Default: true |
forceMount | boolean | Whether or not to forcefully mount the content. This is useful if you want to use Svelte transitions or another animation library for the content. Default: false |
preventOverflowTextSelection | boolean | When Default: true |
preventScroll | boolean | When Default: true |
restoreScrollDelay | number | The delay in milliseconds before the scrollbar is restored after closing the dialog. This is only applicable when using the Default: null |
ref $bindable | HTMLDivElement | The underlying DOM element being rendered. You can bind to this to get a reference to the element. Default: undefined |
children | Snippet | The children content to render. Default: undefined |
child | Snippet | Use render delegation to render your own element. See Child Snippet docs for more information. Default: undefined |
Data Attribute | Value | Description |
---|---|---|
data-state | enum | The state of the alert dialog. |
data-alert-dialog-content | '' | Present on the content element. |
An overlay which covers the body when the alert dialog is open.
Property | Type | Description |
---|---|---|
forceMount | boolean | Whether or not to forcefully mount the content. This is useful if you want to use Svelte transitions or another animation library for the content. Default: false |
ref $bindable | HTMLDivElement | The underlying DOM element being rendered. You can bind to this to get a reference to the element. Default: undefined |
children | Snippet | The children content to render. Default: undefined |
child | Snippet | Use render delegation to render your own element. See Child Snippet docs for more information. Default: undefined |
Data Attribute | Value | Description |
---|---|---|
data-state | enum | The state of the alert dialog. |
data-alert-dialog-overlay | '' | Present on the overlay element. |
A portal which renders the alert dialog into the body when it is open.
Property | Type | Description |
---|---|---|
to | union | Where to render the content when it is open. Defaults to the body. Can be disabled by passing Default: body |
disabled | boolean | Whether the portal is disabled or not. When disabled, the content will be rendered in its original DOM location. Default: false |
children | Snippet | The children content to render. Default: undefined |
The button responsible for taking an action within the alert dialog. This button does not close the dialog out of the box. See the Form Submission documentation for more information.
Property | Type | Description |
---|---|---|
ref $bindable | HTMLButtonElement | The underlying DOM element being rendered. You can bind to this to get a reference to the element. Default: undefined |
children | Snippet | The children content to render. Default: undefined |
child | Snippet | Use render delegation to render your own element. See Child Snippet docs for more information. Default: undefined |
Data Attribute | Value | Description |
---|---|---|
data-alert-dialog-action | '' | Present on the action element. |
A button used to close the alert dialog without taking an action.
Property | Type | Description |
---|---|---|
ref $bindable | HTMLButtonElement | The underlying DOM element being rendered. You can bind to this to get a reference to the element. Default: undefined |
children | Snippet | The children content to render. Default: undefined |
child | Snippet | Use render delegation to render your own element. See Child Snippet docs for more information. Default: undefined |
Data Attribute | Value | Description |
---|---|---|
data-alert-dialog-cancel | '' | Present on the cancel element. |
An accessible title for the alert dialog.
Property | Type | Description |
---|---|---|
level | union | The heading level of the title. This will be set as the Default: 3 |
ref $bindable | HTMLDivElement | The underlying DOM element being rendered. You can bind to this to get a reference to the element. Default: undefined |
children | Snippet | The children content to render. Default: undefined |
child | Snippet | Use render delegation to render your own element. See Child Snippet docs for more information. Default: undefined |
Data Attribute | Value | Description |
---|---|---|
data-alert-dialog-title | '' | Present on the title element. |
An accessible description for the alert dialog.
Property | Type | Description |
---|---|---|
ref $bindable | HTMLDivElement | The underlying DOM element being rendered. You can bind to this to get a reference to the element. Default: undefined |
children | Snippet | The children content to render. Default: undefined |
child | Snippet | Use render delegation to render your own element. See Child Snippet docs for more information. Default: undefined |
Data Attribute | Value | Description |
---|---|---|
data-alert-dialog-description | '' | Present on the description element. |