Interactive demoInteractive UIIntro
Modal dialogs
Focus trapping, escape handling, and the difference between dismissible and destructive dialogs.
Built withRadix DialogReact
Before you try it
What it needs
Nothing to configure. It runs the same everywhere.
Mode right now
ReadyThe provider is configured here; nobody has watched the real path succeed on this deployment yet.
A safe failure to try
Open the destructive confirm and press Escape: nothing is deleted, and focus returns to the button that opened it.
Uncontrolled dialog
Radix holds the open state internally. Right for the common case: a dialog that opens from a trigger and closes on Escape, backdrop click, or a close button.
Controlled destructive confirm
Irreversible actions get friction on purpose. Typing the resource name defeats muscle-memory clicking in a way a plain “Are you sure?” does not.
Try it with the keyboard
These behaviors are what the dependency buys us. Hand-rolling them correctly is genuinely hard, and getting them wrong locks some people out of the feature entirely.
- TabCycles only within the dialog — focus cannot leak to the page behind.
- EscapeCloses the dialog without touching the mouse.
- On openFocus moves into the dialog automatically.
- On closeFocus returns to the trigger button you came from.
What this demonstrates
- Focus moves into the dialog and returns to the trigger on close
- The page behind a modal is hidden from screen readers
- Destructive actions require an explicit, differently-worded confirmation
- Controlled vs uncontrolled open state, and when each is appropriate
Where the code lives
src/experiments/modals/demo.tsxRegistered in src/experiments/registry.ts and loaded on demand by loader.tsx.
Also in Interactive UI