A modal is an interruption you have decided is worth it. Almost every argument about dialogs - should it be a drawer, should it close on outside click, should it be nested - is downstream of that one judgement, and most of the time the honest answer is that the interruption was not worth it and the content should have been a page.
416 public components on 21st carry the modal tag. Below is which of the four containers each job wants, and the behaviour every one of them shares.
Modal dialog
Centred, blocking, for a decision that must be made before anything else. Dialog by originui is the enhanced shadcn base.
Use it for confirmation of something destructive, for a short form that belongs to the row it was opened from, and for anything where returning to the page underneath is the expected next step. Do not use it for content someone might want to link to, print or find later.
Drawer and sheet
A panel from an edge. The same blocking behaviour with two advantages: it does not cover the middle of the screen, and it maps naturally to a phone, where a centred dialog with a form is usually a bad time.
The rule of thumb: sheet from the side for a detail panel next to a list, drawer from the bottom for anything on mobile, because the bottom of the screen is where thumbs are.
Popover
Not a dialog. Non-blocking, dismissible by clicking anywhere, and it must not contain anything the reader has to complete. If a popover has a submit button, it wanted to be a dialog.
The specialised ones
Hero Video Dialog by dillionverma is the video-in-a-modal pattern for landing pages, Modal Pricing by kokonutd puts the plan table in an overlay, Onboarding Dialog by Patrick Xin is the multi-step introduction, and Contacts Table With Modal by Isaiah is the row-detail pattern.
Nested Dialog by victorwelander is the one worth a warning. Nested dialogs work, and they are almost always a sign that the flow needs a page: two stacked interruptions means the reader has to hold two contexts to answer one question.




The behaviour, which is identical for all of them
Six requirements. Miss one and the dialog is unusable for someone.
Focus moves in. When it opens, focus goes to the first meaningful control, or to the dialog itself if there is nothing to focus. Not to the close button by default, because "Close" is a strange first thing to hear.
Focus stays in. Tab cycles inside the dialog and never reaches the page behind it. This is the single most common failure, and the reason <dialog> with showModal() is worth using: the browser does it for you, along with the top layer and the backdrop.
Escape closes. Always, and it must not also close the parent when dialogs are nested.
Focus returns. On close, focus goes back to the element that opened it. Without this a keyboard reader is returned to the top of the document.
The rest of the page is inert. inert on the background, or the native dialog's top layer, so a screen reader cannot wander into content the reader cannot see.
The scroll is locked without a jump. Setting overflow: hidden on the body removes the scrollbar and shifts the layout by its width. Compensate with scrollbar-gutter: stable or padding equal to the scrollbar width.
Where dialogs actually go wrong
Closing on outside click loses work. Fine for a preview, hostile for a form. If the dialog contains input, either do not close on the backdrop, or confirm before discarding.
It has no URL. A dialog in local state cannot be linked, survives no refresh, and turns the back button into a mystery. For anything a reader might share - a detail view, a settings section - put the state in the URL and let the route open the dialog.
It is opened on load. A modal that appears before the reader has read anything is the pattern everyone has learned to close without reading, and on mobile it is covered by specific guidance about intrusive interstitials.
It is a page in disguise. A checkout, a long form, a document. If it has more than one screen of content, it wants an address.
Where else to look
The honest list of alternatives, because the answer is not always us:
| Source | Best for | Trade-off |
|---|---|---|
<dialog> and showModal() | Focus trapping, top layer, backdrop and Escape, natively | Styling the backdrop and animating it takes learning |
| shadcn/ui | Dialog, Sheet, Drawer and AlertDialog as four distinct things | Plain by design |
| Vaul | The mobile drawer with real gesture handling | One shape, one purpose |
| Real routes | Anything with substance: a URL, a title, a back button | More plumbing than a state flag |
| 21st | Video dialogs, pricing overlays, onboarding flows, row detail | Quality varies by author, so preview before you take it |
Taking one
Every component page has a live preview and the code. Installing goes through the shadcn CLI against our registry:
That key comes from your 21st account, and installs require a membership. Set API_KEY_21ST once in your shell and the command works for anything in the catalogue. The 21st MCP covers the same ground without leaving the editor: ask Claude, Cursor or Codex for a dialog, get the previews inline, and let the agent write the file.
Frequently asked
- What does an accessible dialog need?
- Six things: focus moves into it on open, focus stays trapped inside, Escape closes it, focus returns to the trigger on close, the rest of the page is inert, and the scroll lock does not shift the layout. The native dialog element with showModal gives you most of them, including the top layer and the backdrop.
- Should a modal close when you click outside?
- Fine for a preview, hostile for a form. If the dialog contains input the reader has typed, either do not close on the backdrop or confirm before discarding. Losing five minutes of typing to a stray click is the most annoying failure a dialog has.
- Should a dialog have its own URL?
- If a reader might share, bookmark or refresh it, yes. A dialog held in local state has no address, does not survive a refresh, and turns the back button into a mystery. Put the state in the URL and let the route open the dialog for anything with substance, like a detail view or a settings section.
- Modal, drawer or popover?
- Modal for a blocking decision that must happen before anything else. Drawer or sheet for a detail panel beside a list, and from the bottom on mobile where thumbs are. Popover for non-blocking extra information with nothing to complete: if a popover has a submit button, it wanted to be a dialog.

