Avara UI

Dialog (Modal)

A window overlaid on either the primary window or another dialog window, rendering the background content underneath inert.
Popovers and Dropdowns are great for quick, non-blocking actions. But when you need to force the user to make a decision or complete a complex form without distractions, you need a Dialog (Modal).
The DialogBlock component handles the complex DOM logic required for true accessibility: it automatically renders into a React Portal, locks the document.body scrollbar to prevent background scrolling, and actively listens for background clicks or the Escape key to dismiss itself smoothly.
Open each dialog from its trigger — the background scrollbar vanishes while it's open and returns exactly as it was on close.
DialogContent sizes itself from a size prop: sm through xl for panels that sit on the page, and full for a surface that takes the whole viewport with its content centred in the middle of it. Dialogs also nest — render one inside another's content and the inner window portals above its parent, with Escape and backdrop clicks reaching only whichever one is on top.

Dialog

Compose DialogTrigger and DialogContent inside a Dialog root.

defaultOpen
starts it open while leaving the state uncontrolled.

Installation

New project? Follow the installation guide to set up Tailwind CSS, shadcn, the cn helper and lucide-react, register the @algorize-ui registry once, then copy your styles from the Themes page.

Install Dialog

npx shadcn@latest add @algorize-ui/dialog

components/custom/blocks/DialogBlock.tsx is written into your project. Copy any snippet from a Usage tab above and it runs.

Install dependencies

Step 1 installs this for you. Run it yourself only if you are adding Dialog to an existing project by hand. The cn helper and lucide-react are not listed — the installation guide covers them once for every component.

copy-button is a component, not a package — the shadcn CLI installs it as source files.

npx shadcn@latest add @algorize-ui/copy-button

Examples

Form dialog

className
on DialogContent fine-tunes the width when no size step fits — drop any form markup into the body.

Size variations

Five widths, from a compact confirm up to a full-page surface.

Setsize
to sm | md | lg | xl | full — roughly 24rem, 32rem, 42rem and 56rem, then the whole viewport.
size"full"
also drops the rounding, border and height cap, so the panel really does reach every edge — and centres its content in the middle of the screen, in a column the width of md.
className
still wins over the size it is paired with — reach for it only when no step on the scale fits.

Destructive confirm

A confirmation shape: coloured title, clear consequence, two footer actions.

hideCloseButton
is worth pairing with this so the choice has to be made explicitly.

Confirm before deleting

The working version of that shape — the row is only removed once the dialog resolves.

Drive it withopen
set from the row awaiting confirmation, so one dialog serves the whole list instead of one per row.
onOpenChange
is where you refuse the dismissal while the request is in flight — Escape and backdrop clicks arrive here too.
size"sm"
suits a confirm — one question, two buttons, nothing to scan past.

Without close button

SethideCloseButton
on DialogContent to remove the built-in X, when the user must pick one of your own actions.

Controlled

Passopen
and onOpenChange to own the state, so you can keep the dialog up until async work finishes.
onOpenChange
also fires on Escape and on a backdrop click — handle those or the dialog will not close.

Dialog inside a dialog

A small dialog opens on top of the one already on screen — and Escape or a backdrop click only reaches the topmost of the two.

Nesting needs no new API —Dialog
is just rendered inside another DialogContent, and the inner one portals above its parent.
size"sm"
on the inner dialog is what makes it read as a popup over the sheet rather than a second full window.
onOpenChange
on the inner dialog is how the choice travels back out — write it into the outer form's state, then close only the inner one.

Features

Discover the Dialog component's accessible modal features, including focus trapping, outside-click dismissal, and scroll locking.

Customizable

Easily adapt the component's styling and behavior to fit your application's unique design system.

Accessible

Built with accessibility in mind, ensuring all users can interact with your application effectively.

Responsive

Fully responsive design that looks and works great across desktop, tablet, and mobile devices.

Performant

Optimized for maximum performance with minimal re-renders and efficient state management.

Best Practices & Guidelines

Usage Guidelines

Follow standard design principles when implementing this component. Ensure proper contrast, spacing, and context within your layout.

Props Reference

ComponentPropTypeDefaultDescription
Dialogopenbooleanundefined
The controlled open state of the dialog. Use this to programmatically open or close the modal from parent state.
DialogdefaultOpenbooleanfalseThe starting state of the dialog when running uncontrollably.
DialogonOpenChange(open: boolean) => voidundefined
Event handler called when the open state of the dialog changes via a user action (like pressing Escape or clicking the backdrop).
DialogContenthideCloseButtonbooleanfalse
If true, removes the built-in 'X' icon in the top right corner of the dialog content box.
DialogContentsize"sm" | "md" | "lg" | "xl" | "full""md"
Panel width: sm ~24rem, md ~32rem, lg ~42rem, xl ~56rem. full fills the viewport, drops the rounding, border and max-height cap the inset sizes use, and centres its content in an md-wide column in the middle of the screen (override with className for an edge-to-edge layout).
All ComponentsclassNamestringundefined
Standard Tailwind CSS overrides for customized styling or spacing. On DialogContent it is merged after size, so a max-w-* class here wins — use it only when no step on the size scale fits.