Dismiss

.alert[role="alert"][data-ui="dismiss"]

Dismiss — closing something that can be closed, and putting focus somewhere real afterwards.

How this differs from what it looks like

Not alert

They are not alternatives — they are two halves of the same thing. alert is the message: the box, the tint, the glyph, the title and the close button, all of it CSS. dismiss is the behaviour behind that close button, and it exists because removing the alert is the easy part and putting focus somewhere real afterwards is not: the button the user pressed was inside the thing that vanished, so focus goes to <body>, the next Tab starts from the top of the document, and a screen reader user is returned to nowhere and told nothing. Almost every dismissible component on the web ships that bug. Use alert alone for a message that stays; add data-ui="dismiss" when it has a close button.

Examples

An alert that closes

View “An alert that closes” as
<div class="alert alert-warning" role="alert" data-ui="dismiss">
  <p class="alert-title">Your session expires in one minute</p>
  <p class="alert-text">Save anything unsaved, or sign in again to continue.</p>
  <button class="btn btn-sm btn-quiet alert-close" type="button">
    <span class="sr-only">Dismiss this message</span>
  </button>
</div>

data-ui="dismiss" goes on the element that disappears, not on the button.

The reason this is a module rather than two lines is focus: the user just pressed a button inside the thing being removed, so without deliberate handling focus falls to <body> and a keyboard user is dumped at the top of the document. That is the bug every dismissible component ships.

Tokens 0

Level 2, declared on .dismiss itself. Set any of them on that selector to restyle this component without touching the skin.

None. It reads the skin's tokens directly.

Variants and states

Variants

None. It is one shape, and the page does the rest.

State it reads

None.

Before you ship it

This one needs a script. Opt the markup in with data-ui="dismiss" and import import 'mostlycss/js/components/dismiss' — that specifier and not the package root, which is a bundle carrying a second copy of the registry, so a page holding both initialises every element twice. What you lose without the script is listed below — for some components that is only polish, for others it is the whole interaction.

What you have to do 3 requirements

  1. Give the close button an accessible name on the button itself — its glyph is aria-hidden, and "Dismiss" alone is enough only when one thing on the page can be dismissed.
  2. Decide where focus goes. The default lands it somewhere sensible, and data-dismiss-focus names the element when your page knows better. Removing the focused element without saying is how focus ends up on <body> and the next Tab restarts from the top of the document.
  3. Keep the thing being dismissed dismissible some other way too, when it carries information the user may still need: dismissal is not undo.

src/js/components/dismiss.ts · npx mostlycss add dismiss