Component
Modal
A focused, interrupting dialog built on the native dialog element.
Plain-text source, for agents and clipboard use: /components/source/modal.txt
When to use it
Use when a decision must be made before anything else can continue — confirming a destructive action, or completing a short, self-contained task.
Not this
Do not use a modal for content the user might want to keep beside the page, for long forms, or for non-urgent information. Stacked modals are always a design failure.
Examples
Confirmation
Built on <dialog>, so focus trapping, Escape to close, inertness of the page behind and the backdrop all come from the platform.
html
<dialog class="flux-modal" open>
<div class="flux-modal__header">
<h2 class="flux-modal__title">Cancel booking KB-104928?</h2>
</div>
<div class="flux-modal__body">
<p>The supplier will be notified and the deposit refund will follow your cancellation policy. This cannot be undone.</p>
</div>
<div class="flux-modal__footer">
<button class="flux-button flux-button--ghost">Keep booking</button>
<button class="flux-button flux-button--danger">Cancel booking</button>
</div>
</dialog>Anatomy
| Part | Description |
|---|---|
| Backdrop | surface-backdrop, from the theme. |
| Header | Title and a divider. |
| Body | Secondary text. Scrolls if it must. |
| Footer | Right-aligned. Cancel first, primary action last. |
API
| Name | Kind | Description |
|---|---|---|
dialog | element | Use the native element. Open with showModal(), never by toggling a class. |
flux-modal | class | The dialog surface, including its ::backdrop. |
flux-modal__header | class | Divided title row. |
flux-modal__body | class | Content region. |
flux-modal__footer | class | Right-aligned action row. |
States
| State | Treatment |
|---|---|
| Closed | Not rendered and not focusable. |
| Open | Page behind is inert; focus moves into the dialog. |
Keyboard
| Keys | Action |
|---|---|
Escape | Closes the dialog. Native behaviour — do not prevent it. |
Tab | Cycles within the dialog only. |
Accessibility
- showModal() gives focus trapping, page inertness and Escape for free. A div-based modal has to reimplement all three and usually reimplements none.
- Give the dialog an accessible name via aria-labelledby pointing at the title.
- Return focus to the control that opened the dialog when it closes.
- The title states the consequence, so a screen-reader user hears what is at stake before the buttons.
Tokens
The tier-3 and tier-2 tokens this component binds to. Change the token, not the component.
- --flux-modal-radius
- --flux-modal-bg
- --flux-modal-shadow
- --flux-modal-backdrop
- --flux-modal-width-sm | -md | -lg
Do and don’t
Do
- Name the consequence in the title, not "Are you sure?".
- Label the confirm button with the action itself, so it reads correctly out of context.
Don’t
- Do not tint the backdrop with a brand colour.
- Do not open a modal from a modal.
- Do not put a form longer than a few fields inside one.