Alert Dialog

A modal window that alerts users with important information and awaits their acknowledgment or action.

	<script lang="ts">
  import { AlertDialog } from "bits-ui";
</script>
 
<AlertDialog.Root>
  <AlertDialog.Trigger
    class="inline-flex h-12 items-center
	justify-center whitespace-nowrap rounded-input bg-dark px-[21px]
	text-[15px] font-semibold text-background shadow-mini transition-all hover:bg-dark/95 active:scale-98"
  >
    Subscribe
  </AlertDialog.Trigger>
  <AlertDialog.Portal>
    <AlertDialog.Overlay
      class="fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"
    />
    <AlertDialog.Content
      class="fixed left-[50%] top-[50%] z-50 grid w-full max-w-[94%] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-card-lg border bg-background p-7 shadow-popover outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:max-w-lg md:w-full "
    >
      <div class="flex flex-col gap-4 pb-6">
        <AlertDialog.Title class="text-lg font-semibold tracking-tight"
          >Confirm your transaction</AlertDialog.Title
        >
        <AlertDialog.Description class="text-sm text-foreground-alt">
          This action cannot be undone. This will initiate a monthly wire in the
          amount of $10,000 to Huntabyte. Do you wish to continue?
        </AlertDialog.Description>
      </div>
      <div class="flex w-full items-center justify-center gap-2">
        <AlertDialog.Cancel
          class="inline-flex h-input w-full items-center justify-center rounded-input bg-muted text-[15px] font-medium shadow-mini transition-all hover:bg-dark-10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground focus-visible:ring-offset-2 focus-visible:ring-offset-background active:scale-98"
          >Cancel</AlertDialog.Cancel
        >
        <AlertDialog.Action
          class="inline-flex h-input w-full items-center justify-center rounded-input bg-dark text-[15px] font-semibold text-background shadow-mini transition-all hover:bg-dark/95 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-dark focus-visible:ring-offset-2 focus-visible:ring-offset-background active:scale-98"
          >Continue</AlertDialog.Action
        >
      </div>
    </AlertDialog.Content>
  </AlertDialog.Portal>
</AlertDialog.Root>

Structure

	<script lang="ts">
	import { AlertDialog } from "bits-ui";
</script>
 
<AlertDialog.Root>
	<AlertDialog.Trigger />
	<AlertDialog.Portal>
		<AlertDialog.Overlay />
		<AlertDialog.Content>
			<AlertDialog.Title />
			<AlertDialog.Description />
			<AlertDialog.Cancel />
			<AlertDialog.Action />
		</AlertDialog.Content>
	</AlertDialog.Portal>
</AlertDialog.Root>

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.

MyAlertDialog.svelte
	<script lang="ts">
	import type { Snippet } from "svelte";
	import { AlertDialog, type WithoutChild } from "bits-ui";
 
	type Props = AlertDialog.RootProps & {
		buttonText: string;
		title: Snippet;
		description: Snippet;
		contentProps?: WithoutChild<AlertDialog.ContentProps>;
		// ...other component props if you wish to pass them
	};
 
	let {
		open = $bindable(false),
		children,
		buttonText,
		contentProps,
		title,
		description,
		...restProps
	}: Props = $props();
</script>
 
<AlertDialog.Root bind:open {...restProps}>
	<AlertDialog.Trigger>
		{buttonText}
	</AlertDialog.Trigger>
	<AlertDialog.Portal>
		<AlertDialog.Overlay />
		<AlertDialog.Content {...contentProps}>
			<AlertDialog.Title>
				{@render title()}
			</AlertDialog.Title>
			<AlertDialog.Description>
				{@render description()}
			</AlertDialog.Description>
			{@render children?.()}
			<AlertDialog.Cancel>Cancel</AlertDialog.Close>
			<AlertDialog.Action>Confirm</AlertDialog.Close>
		</AlertDialog.Content>
	</AlertDialog.Portal>
</AlertDialog.Root>

You can then use the MyAlertDialog component in your application like so:

+page.svelte
	<script lang="ts">
	import MyAlertDialog from "$lib/components/MyAlertDialog.svelte";
</script>
 
<MyAlertDialog buttonText="Open Dialog">
	{#snippet title()}
		Delete your account
	{/snippet}
	{#snippet description()}
		This action cannot be undone.
	{/snippet}
</MyAlertDialog>

Alternatively, you can define the snippets separately and pass them as props to the component:

+page.svelte
	<script lang="ts">
	import MyAlertDialog from "$lib/components/MyAlertDialog.svelte";
</script>
 
{#snippet title()}
	Delete your account
{/snippet}
{#snippet description()}
	This action cannot be undone.
{/snippet}
 
<MyAlertDialog buttonText="Open Dialog" {title} {description}>
	<!-- ... additional content here -->
</MyAlertDialog>

Managing Open State

Bits UI provides flexible options for controlling and synchronizing the Alert Dialog's open state.

Two-Way Binding

Use the bind:open directive for effortless two-way synchronization between your local state and the dialog's internal state.

	<script lang="ts">
	import { AlertDialog } from "bits-ui";
	let isOpen = $state(false);
</script>
 
<button on:click={() => (isOpen = true)}>Open Dialog</button>
 
<AlertDialog.Root bind:open={isOpen}>
	<!-- ...dialog components -->
</AlertDialog.Root>

This setup enables opening the dialog via the custom button and ensures the local isOpen state updates when the dialog closes through any means (e.g., escape key).

Change Handler

You can also use the onOpenChange prop to update local state when the dialog's open state changes. This is useful when you don't want two-way binding for one reason or another, or you want to perform additional logic when the dialog opens or closes.

	<script lang="ts">
	import { AlertDialog } from "bits-ui";
	let isOpen = $state(false);
</script>
 
<AlertDialog.Root
	open={isOpen}
	onOpenChange={(open) => {
		isOpen = open;
		// additional logic here.
	}}
>
	<!-- ... -->
</AlertDialog.Root>

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 beahvior by setting the trapFocus prop to false on the AlertDialog.Content component.

	<AlertDialog.Content trapFocus={false}>
	<!-- ... -->
</AlertDialog.Content>

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.

	<script lang="ts">
	import { AlertDialog } from "bits-ui";
	let nameInput = $state<HTMLInputElement>();
</script>
 
<AlertDialog.Root>
	<AlertDialog.Trigger>Open AlertDialog</AlertDialog.Trigger>
	<AlertDialog.Content
		onOpenAutoFocus={(e) => {
			e.preventDefault();
			nameInput?.focus();
		}}
	>
		<input type="text" bind:this={nameInput} />
	</AlertDialog.Content>
</AlertDialog.Root>

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.

	<script lang="ts">
	import { AlertDialog } from "bits-ui";
	let nameInput = $state<HTMLInputElement>();
</script>
 
<input type="text" bind:this={nameInput} />
<AlertDialog.Root>
	<AlertDialog.Trigger>Open AlertDialog</AlertDialog.Trigger>
	<AlertDialog.Content
		onCloseAutoFocus={(e) => {
			e.preventDefault();
			nameInput?.focus();
		}}
	>
		<!-- ... -->
	</AlertDialog.Content>
</AlertDialog.Root>

Scroll Lock

By default, when a dialog is opened, scrolling the body will be disabled, which provides a more native experience for users. If you wish to disable this behavior, you can set the preventScroll prop to false on the AlertDialog.Content component.

	<AlertDialog.Content preventScroll={false}>
	<!-- ... -->
</AlertDialog.Content>

Escape Keydown

By default, when a dialog is open, pressing the Escape key will close the dialog. Bits UI provides a couple ways to override this behavior.

escapeKeydownBehavior

You can set the escapeKeydownBehavior prop to 'ignore' on the AlertDialog.Content component to prevent the dialog from closing when the Escape key is pressed.

	<AlertDialog.Content escapeKeydownBehavior="ignore">
	<!-- ... -->
</AlertDialog.Content>

onEscapeKeydown

You can also override the default behavior by cancelling the event passed to the onEscapeKeydown callback on the AlertDialog.Content component.

	<AlertDialog.Content onEscapeKeydown={(e) => e.preventDefault()}>
	<!-- ... -->
</AlertDialog.Content>

Interact Outside

Unlike the regular Dialog, the Alert Dialog does not close when the user interacts outside the content. This is because when using an alert dialog, the user is expected to acknowledge the dialog's content before continuing.

If you wish to override this behavior, Bits UI provides a couple ways to do so.

interactOutsideBehavior

You can set the interactOutsideBehavior prop to 'close' on the AlertDialog.Content component to close the dialog when the user interacts outside the content.

	<Dialog.Content interactOutsideBehavior="ignore">
	<!-- ... -->
</Dialog.Content>

onInteractOutside

If interactOutsideBehavior is set to 'close', you can intercept the event passed to the onInteractOutside callback on the AlertDialog.Content component.

If the event is cancelled, the dialog will not close.

	<AlertDialog.Content onInteractOutside={(e) => e.preventDefault()}>
	<!-- ... -->
</AlertDialog.Content>

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.

Usage

Controlled Open

If you want to control or be aware of the open state of the dialog from outside of the component, bind to the open prop.

	<script lang="ts">
	import { AlertDialog } from "bits-ui";
	let open = $state(false);
</script>
 
<button onclick={() => (open = true)}>Open Dialog</button>
 
<AlertDialog.Root bind:open>
	<AlertDialog.Trigger />
	<AlertDialog.Portal>
		<AlertDialog.Overlay />
		<AlertDialog.Content>
			<AlertDialog.Title />
			<AlertDialog.Description />
			<AlertDialog.Cancel />
			<AlertDialog.Action />
		</AlertDialog.Content>
	</AlertDialog.Portal>
</AlertDialog.Root>

API Reference

AlertDialog.Root

The root component used to set and manage the state of the alert dialog.

Property Type Description
open bindable prop
boolean

Whether or not the alert dialog is open.

Default: false
onOpenChange
function

A callback function called when the open state changes.

Default: undefined
children
Snippet

The children content to render.

Default: undefined

AlertDialog.Trigger

The element which opens the alert dialog on press.

Property Type Description
ref bindable prop
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 delegation docs for more information.

Default: undefined

AlertDialog.Content

The content displayed within the alert dialog modal.

Property Type Description
onInteractOutside
function

Callback fired when an outside interaction event completes, which is either a pointerup, mouseup, or touchend event, depending on the user's input device. You can call event.preventDefault() to prevent the default behavior of handling the outside interaction.

Default: undefined
onInteractOutsideStart
function

Callback fired when an outside interaction event starts, which is either a pointerdown, mousedown, or touchstart event, depending on the user's input device. You can call event.preventDefault() to prevent the continuation of the outside interaction.

Default: undefined
onFocusOutside
function

Callback fired when focus leaves the dismissable layer. You can call event.preventDefault() to prevent the default behavior on focus leaving the layer.

Default: undefined
interactOutsideBehavior
enum

The behavior to use when an interaction occurs outside of the floating content. 'close' will close the content immediately. 'ignore' will prevent the content from closing. 'defer-otherwise-close' will defer to the parent element if it exists, otherwise it will close the content. 'defer-otherwise-ignore' will defer to the parent element if it exists, otherwise it will ignore the interaction.

Default: close
onEscapeKeydown
function

Callback fired when an escape keydown event occurs in the floating content. You can call event.preventDefault() to prevent the default behavior of handling the escape keydown event.

Default: undefined
escapeKeydownBehavior
enum

The behavior to use when an escape keydown event occurs in the floating content. 'close' will close the content immediately. 'ignore' will prevent the content from closing. 'defer-otherwise-close' will defer to the parent element if it exists, otherwise it will close the content. 'defer-otherwise-ignore' will defer to the parent element if it exists, otherwise it will ignore the interaction.

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 true, prevents the text selection from overflowing the bounds of the element.

Default: true
preventScroll
boolean

When true, prevents the body from scrolling when the content is open. This is useful when you want to use the content as a modal.

Default: true
ref bindable prop
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 delegation docs for more information.

Default: undefined

AlertDialog.Overlay

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 prop
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 delegation docs for more information.

Default: undefined

AlertDialog.Portal

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 null

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

AlertDialog.Action

A button used to close the alert dialog by taking an action.

Property Type Description
ref bindable prop
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 delegation docs for more information.

Default: undefined

AlertDialog.Cancel

A button used to close the alert dialog without taking an action.

Property Type Description
ref bindable prop
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 delegation docs for more information.

Default: undefined

AlertDialog.Title

An accessibile title for the alert dialog.

Property Type Description
level
union

The heading level of the title. This will be set as the aria-level attribute.

Default: 3
ref bindable prop
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 delegation docs for more information.

Default: undefined

AlertDialog.Description

An accessibile description for the alert dialog.

Property Type Description
ref bindable prop
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 delegation docs for more information.

Default: undefined