Overlays

  • Showing and answering
  • 3 min
  • components: 8
  • pairs: 3

Eleven components put content above the page. The choice between them is a choice about focus — who has it, where it returns, and what Escape closes.

Reviewed 2026-09-05

On this page

What it solves

Putting something above the page is easy. What is hard, and what every overlay bug is about, is the three questions that follow: does the background still work, where does the keyboard go, and what happens when the person presses Escape.

The library answers all three in one place — a shared layer stack — so the answers are the same for every overlay on the page. That matters most when there are two.

Anatomy

Choose by what the content is, not by how it should look. The library states the condition for each:

  1. Your own layout above the page — GrModal. The base every modal thing is built on; take it when the ready-made shapes do not fit.
  2. A window with a header, a body and a footer — GrDialog. The shape you need nine times out of ten.
  3. The action is irreversible — GrConfirmDialog. A separate component, not a dialog with a red button: the question and the danger are its subject.
  4. One value is needed — GrPromptDialog. A whole form for a single field is a form you now have to lay out.
  5. A panel arrives from the edge — GrDrawer. Modal or not; see below, because that flag changes the keyboard.
  6. Your own content at an anchor — GrPopover. Tied to the trigger, not to the centre of the screen.
  7. A menu of its own items — GrDropdown. A list of actions next to what they act on.
  8. Actions over a row or a tree node — GrContextMenu. Brings them to the pointer instead of making the person travel to a toolbar.

The two axes underneath: modal or not (does the background keep working) and anchored or centred (is it about one element or about the page).

Example

Do and don’t

Do — Let the stack return focus

Closing returns focus to the trigger, and the layer stack does that itself. Moving focus by hand through nextTick or a timeout competes with it — and loses on the second overlay, where the winner depends on timing.

Don’t — Open an overlay from an overlay for no reason

Two layers deep, «back» stops meaning anything: Escape closes the top one, and the person expected the whole thing to go. If the second layer is a confirmation, that is the case it was built for; anything else is a wizard wearing a stack.

Do — Non-modal drawer when the page is still the point

:modal="false" removes the focus trap: Tab goes back to the page, which is what a filter panel or an inspector is for. The overlay is help, not a wall.

Don’t — Trap focus in something that is not a decision

A modal drawer over a table means the table cannot be reached with the keyboard until the drawer closes. If the person is meant to look at both, the trap is the bug — not the layout.

Do — Ask the dangerous question in its own component

GrConfirmDialog exists because «delete» and «save» must not look like the same dialog with a different colour. The component carries the question, the wording of consequences and the emphasis on the safe answer.

Don’t — Confirm everything

A confirmation on a reversible action teaches people to dismiss confirmations, and then the one that mattered is dismissed too. Undo beats confirm wherever undo is possible.

Accessibility

Overlays are the place where keyboard support is most often half-finished, and a half-finished pattern is worse than none: a screen reader announces a role the behaviour does not match.

Escape closes the top layer, not all of them. With two overlays open, one press should not clear the screen — the person is undoing one step.

The focus trap is a property of modality. GrModal and everything built on it — GrDialog, GrConfirmDialog, GrPromptDialog — cycle Tab inside. A drawer with :modal="false" deliberately does not, and that is the whole point of the flag.

Return is not optional. The keyboard cannot be left at the top of the document after closing; the person was somewhere, and that somewhere is where the work continues.

The contracts below come from the library and are tested there. What no component can decide for you is how many layers a screen deserves — and the honest answer is usually one.

Components in this pattern

The list is built from frontmatter, not from links in the prose: renaming a slug does not lose it.

Keyboard

Contracts come from the library. The pattern does not restate them — it points at them.