Dialog

Composable modal Dialog and AlertDialog that portal to the body over a blurred backdrop, scale the panel up and exit faster, trap focus, close on Escape, lock page scroll without layout shift and hand focus back to the trigger, with controlled/uncontrolled open, a bottom-sheet layout below sm, an alertdialog that ignores outside clicks and focuses Cancel first, and an optional type-to-confirm field that shakes when Delete is pressed too early.

Preview

Dialog preview width

Install

Add it with the shadcn CLI, or copy the source manually.

$ bunx --bun shadcn add @karaui/dialog
@karaui not found? Add it to components.json
{
  "registries": {
    "@karaui": "https://karaui.kamisama-v0.my.id/r/{name}.json"
  }
}

@karaui is in shadcn's public registry directory, so the latest CLI needs no setup. On an older CLI, merge this into the existing file once and every @karaui/… install resolves.

API Reference

Dialog

open?
boolean

Controlled open state.

—
defaultOpen?
boolean

Initial open state when uncontrolled.

—
onOpenChange?
((open: boolean) => void)
—

AlertDialog

confirmText?
string

Require the user to type this exact text (e.g. the project name) into `AlertDialogConfirmInput` before `AlertDialogAction` goes through.

—
open?
boolean

Controlled open state.

—
defaultOpen?
boolean

Initial open state when uncontrolled.

—
onOpenChange?
((open: boolean) => void)
—

DialogContent

className?
string
—
overlayClassName?
string

Class for the dimmed, blurred backdrop.

—
showCloseButton?
boolean

Show the corner close (X) button. Default true for Dialog, false for AlertDialog.

—
closeLabel?
string
—
closeOnOutsideClick?
boolean

Close when the backdrop is pressed. Default true for Dialog; AlertDialog ignores it and never closes on an outside press.

—
initialFocus?
RefObject<HTMLElement | null>

Element to focus on open. Falls back to `[data-dialog-autofocus]`, then the first focusable.

—
sheetOnMobile?
boolean

Become a bottom-anchored sheet below the `sm` breakpoint. Default true.

—
aria-label?
string

Accessible name, when the content has no `DialogTitle`.

—

DialogHeader

className?
string
—

DialogFooter

className?
string
—

DialogTitle

className?
string
—

DialogDescription

className?
string
—

AlertDialogContent

className?
string
—
aria-label?
string

Accessible name, when the content has no `DialogTitle`.

—
overlayClassName?
string

Class for the dimmed, blurred backdrop.

—
showCloseButton?
boolean

Show the corner close (X) button. Default true for Dialog, false for AlertDialog.

—
closeLabel?
string
—
initialFocus?
RefObject<HTMLElement | null>

Element to focus on open. Falls back to `[data-dialog-autofocus]`, then the first focusable.

—
sheetOnMobile?
boolean

Become a bottom-anchored sheet below the `sm` breakpoint. Default true.

—

AlertDialogConfirmInput

mismatchMessage?
string

Message shown when confirming with a mismatch.

That doesn't match. Check the spelling and try again.
className?
string
—
success?
boolean
—
label?
string
—
leftIcon?
ReactNode
—
rightIcon?
ReactNode
—
classNames?
InputClassNames
—

DialogTrigger

className?
string
—
variant?
"primary" | "secondary" | "ghost" | "outline"
outline
size?
"sm" | "md" | "lg" | "icon"
—
pressScale?
number
—
ripple?
boolean

Spawn a Material-style ripple from the press point. Off by default.

—
asChild?
boolean

Merge behaviour onto the single child element instead of rendering a `Button`.

—

DialogClose

className?
string
—
variant?
"primary" | "secondary" | "ghost" | "outline"
outline
size?
"sm" | "md" | "lg" | "icon"
—
pressScale?
number
—
ripple?
boolean

Spawn a Material-style ripple from the press point. Off by default.

—
asChild?
boolean

Merge behaviour onto the single child element instead of rendering a `Button`.

—

AlertDialogTrigger

className?
string
—
variant?
"primary" | "secondary" | "ghost" | "outline"
outline
size?
"sm" | "md" | "lg" | "icon"
—
pressScale?
number
—
ripple?
boolean

Spawn a Material-style ripple from the press point. Off by default.

—
asChild?
boolean

Merge behaviour onto the single child element instead of rendering a `Button`.

—

AlertDialogHeader

className?
string
—

AlertDialogFooter

className?
string
—

AlertDialogTitle

className?
string
—

AlertDialogDescription

className?
string
—

AlertDialogCancel

className?
string
—
variant?
"primary" | "secondary" | "ghost" | "outline"
outline
size?
"sm" | "md" | "lg" | "icon"
—
pressScale?
number
—
ripple?
boolean

Spawn a Material-style ripple from the press point. Off by default.

—

AlertDialogAction

className?
string
—
variant?
"primary" | "secondary" | "ghost" | "outline"
outline
size?
"sm" | "md" | "lg" | "icon"
—
pressScale?
number
—
ripple?
boolean

Spawn a Material-style ripple from the press point. Off by default.

—
tone?
"default" | "destructive"

`destructive` (default) paints the button in the destructive token.

destructive

Updated