Dialog
- Stable
- WCAG 2.2 evidence
- RTL
- Web · iOS · Android
A short modal question that needs a decision before work continues, such as "Submit October payroll?". Built on React Aria ModalOverlay + Modal + Dialog:
a role="dialog" (or role="alertdialog" for destructive confirmations) named by its title and described by its
body; focus moves inside on open (to the secondary action when destructive), Tab stays inside while the page is
inert, Escape closes it, and focus returns to the trigger (WCAG 2.1.1, 2.1.2, 2.4.3, 3.3.4, 4.1.2). Consumer duties: a title that asks the question and labels that name the outcome; for long forms use Modal.
import { Dialog } from "@nexera-ui/react";- 8
- examples
- 22
- props
- 7
- live controls
- 3
- platforms
- 9
- WCAG criteria
- 5
- blocks use it
Try every prop. Copy the code.
Change the props and the code updates. Check light and dark, LTR and RTL, and phone width.
import { Dialog } from "@nexera-ui/react";
<Dialog />Examples 7
The same examples as Storybook, rendered live. Open Code to copy one.
Destructive
Figma Variant=Destructive: an alertdialog with the trash icon and a destructive primary action. Focus starts on Cancel, so pressing Enter by habit does not delete anything.
import { Button, Dialog } from "@nexera-ui/react";
import { LuTrash2 } from "react-icons/lu";
<Dialog
title="Delete contract?"
body="Contract 2026.pdf will be removed for Ayesha Khan. You can upload it again later."
primaryLabel="Delete"
secondaryLabel="Cancel"
trigger={<Button variant="destructive">Delete contract</Button>}
defaultOpen
variant="destructive"
icon={<LuTrash2 />}
/>;
IOS
Figma Platform=iOS: a centred alert with a row of text buttons (no icon, no close button).
import { Button, Dialog } from "@nexera-ui/react";
<Dialog
title="Submit October payroll?"
body="Rs 29,042,000 will be paid to 128 employees on 31 October. This cannot be undone."
primaryLabel="Submit"
secondaryLabel="Cancel"
trigger={<Button>Submit payroll</Button>}
defaultOpen
platform="ios"
/>;
IOS destructive
Figma Platform=iOS, Variant=Destructive: the destructive action is red.
import { Button, Dialog } from "@nexera-ui/react";
<Dialog
title="Delete contract?"
body="Contract 2026.pdf will be removed for Ayesha Khan. You can upload it again later."
primaryLabel="Delete"
secondaryLabel="Cancel"
trigger={<Button>Submit payroll</Button>}
defaultOpen
platform="ios"
variant="destructive"
/>;
Android
Figma Platform=Android: an icon above a centred title, and ghost actions at the end.
import { Button, Dialog } from "@nexera-ui/react";
import { LuWallet } from "react-icons/lu";
<Dialog
title="Submit October payroll?"
body="Rs 29,042,000 will be paid to 128 employees on 31 October. This cannot be undone."
primaryLabel="Submit"
secondaryLabel="Cancel"
trigger={<Button>Submit payroll</Button>}
defaultOpen
platform="android"
icon={<LuWallet />}
/>;
With content
Figma Show content: extra content under the body.
import { Button, Dialog } from "@nexera-ui/react";
<Dialog
title="Submit October payroll?"
body="Rs 29,042,000 will be paid to 128 employees on 31 October. This cannot be undone."
primaryLabel="Submit"
secondaryLabel="Cancel"
trigger={<Button>Submit payroll</Button>}
defaultOpen
>
{
<ul className="m-0 flex flex-col gap-1 ps-5 text-body-small text-secondary">
<li>Salaries: Rs 27,800,000</li>
<li>Allowances: Rs 1,242,000</li>
</ul>
}
</Dialog>;
Long content
Long titles, bodies and labels wrap; the footer buttons wrap when they do not fit.
import { Button, Dialog } from "@nexera-ui/react";
const BODY = "Rs 29,042,000 will be paid to 128 employees on 31 October. This cannot be undone.";
<Dialog
title="Submit the October payroll for every department, including the employees who joined this month?"
body={`${BODY} The bank processes the transfer the next working day and every employee gets a payslip by email.`}
primaryLabel="Submit payroll for all departments"
secondaryLabel="Review the department totals first"
trigger={<Button>Submit payroll</Button>}
defaultOpen
/>;
Right to left
Right-to-left: the icon and title start on the right; actions sit on the left.
import { Button, Dialog } from "@nexera-ui/react";
import { LuTrash2 } from "react-icons/lu";
<Dialog
title="حذف العقد؟"
body="ستتم إزالة العقد لعائشة خان. يمكنك رفعه مرة أخرى لاحقًا."
primaryLabel="حذف"
secondaryLabel="إلغاء"
trigger={<Button variant="destructive">حذف العقد</Button>}
defaultOpen
variant="destructive"
icon={<LuTrash2 />}
closeLabel="إغلاق"
/>;
Props 22
Press "Try it" on a card to load that prop into the playground.
22 props shown
title*NexeraReactNodeTitle: a level 2 heading that names the dialog. Ask the question ("Delete contract?").
bodyNexeraReactNodeExplanation under the title: what happens and whether it can be undone. It is
the dialog's description (aria-describedby), read out when the dialog opens.
childrenNexeraReactNodeExtra content under the body, such as a checkbox or a short summary.
iconNexeraReactNodeIcon. Web: in a 36 px circle before the title. Android: 24 dp above the title. iOS alerts have no icon, so it is not shown there. Decorative: the title names the dialog.
primaryLabel*NexerastringLabel of the main action, naming the outcome ("Submit payroll", "Delete").
onPrimaryActionNexera() => voidCalled when the main action is pressed; the dialog then closes.
secondaryLabelNexerastringLabel of the action that backs out, usually "Cancel". Shown when provided.
onSecondaryActionNexera() => voidCalled when the secondary action is pressed; the dialog then closes.
variantNexera"default" | "destructive"Visual weight of the main action. destructive uses the danger colour, makes the dialog an
alertdialog, and puts focus on the secondary action when the dialog opens, so Enter does not destroy anything.
roleNexera"dialog" | "alertdialog"ARIA role. Derived from variant; use alertdialog for any urgent confirmation.
platformNexera"web" | "ios" | "android"Platform look: web dialog, iOS alert or Android dialog. Defaults to the NexeraProvider platform.
closeLabelNexerastringAccessible name of the web close button. Translate it for your locale.
isDismissableNexerabooleanWhether a click on the scrim closes the dialog. Off by default: a dialog asks for a decision. Escape closes it
(like the secondary action) unless isKeyboardDismissDisabled.
idNexerastringId of the surface element.
classNameNexerastringExtra classes for the surface, merged last so they win over the defaults.
styleNexeraCSSPropertiesInline style for the surface.
triggerNexeraReactElement<unknown, string | JSXElementConstructor<any>>The element that opens the overlay, usually a Nexera Button. It toggles the overlay when pressed and gets focus
back when the overlay closes. Leave it out to open the overlay from your own state (isOpen + onOpenChange).
isOpenNexerabooleanWhether the overlay is open (controlled). Use with onOpenChange.
defaultOpenNexerabooleanWhether the overlay is open on first render (uncontrolled).
onOpenChangeNexera(isOpen: boolean) => voidCalled when the overlay opens or closes (Escape, the close button, a slot="close" action, a click outside).
shouldCloseOnInteractOutsideReact Aria(element: Element) => booleanWhen user interacts with the argument element outside of the overlay ref, return true if onClose should be called. This gives you a chance to filter out interaction with elements that should not dismiss the overlay. By default, onClose will always be called on interaction outside the overlay ref.
isKeyboardDismissDisabledReact AriabooleanWhether pressing the escape key to close the modal should be disabled.
* Required. React Aria props shown are the ones most apps use; the component accepts the rest of its React Aria props too.
Accessible by default.
Built on React Aria, and covered by the WCAG 2.2 evidence generated on every build.
WCAG 2.2 evidence
6 direct · 3 supporting- 1.3.1Info and RelationshipsLevel A · tested directly
- 1.4.10ReflowLevel AA · supporting test
- 1.4.12Text SpacingLevel AA · supporting test
- 2.1.1KeyboardLevel A · tested directly
- 2.1.2No Keyboard TrapLevel A · tested directly
- 2.4.3Focus OrderLevel A · tested directly
- 2.4.7Focus VisibleLevel AA · supporting test
- 3.3.4Error Prevention (Legal, Financial, Data)Level AA · tested directly
- 4.1.2Name, Role, ValueLevel A · tested directly
Fits any width.
Nexera components respond to the space they are given. Drag the corner of the frame, or pick a width.
Styling hooks
Pass className to add Tailwind classes (merged last). State is exposed as data attributes, so you can style it with variants like data-pressed:.
data-hovereddata-pressed
<Dialog className="data-hovered:opacity-90 shadow-sm" />Used in blocks
- Choose an optionForms and data entry
- Pick a colourForms and data entry
- Delete accountSettings and preferences
- Shift pickerScheduling and calendar
- Confirm a destructive actionStates and system messages
Related components
- ActionSheetAn iOS-style sheet of actions that slides up from the bottom, with a separate Cancel row.
- ActionSheetItemOne action in an `ActionSheet`.
- BottomSheetA mobile sheet that slides up from the bottom edge for a short task or a set of options.
- CommandPaletteA searchable list of pages, actions and people in a modal.
- DrawerA side panel over the page for details, filters or a secondary task.
- ModalA modal window for a task that needs the user's full attention, such as a short form.
- PopoverA short, non-modal panel anchored to a trigger.
- TooltipA short description of a control, shown on hover and keyboard focus.