mica
Start / Accessibility

Accessibility

Native semantics first; script only where access requires it.

Mica's accessibility position is mostly a consequence of its other choices. Styling native elements means their semantics, keyboard behavior, and assistive-tech mapping arrive intact — a <button> is announced as a button because it is one. The tokenized focus ring in mica.preset is visible on every control by default rather than something you remember to add, and dark mode is color-scheme, so native controls follow the theme without a parallel palette.

Never fake behavior in CSS

The checkbox-hack school of CSS-only components produces things that look like tabs and are unusable with a keyboard. Mica refuses that trade: if the accessible version of a pattern needs script, the script is the honest cost and ships as an opt-in Tier-2 module. That is the whole Tier 1/2 boundary — does accessibility require JS? — and it is why m-tabs and m-combobox have modules while dialogs, accordions, and menus do not.

Tier-2 modules enhance working markup; they never render it. With the module absent you get a degraded but usable page — all tab panels visible in order, a native autocomplete — not an empty container.

Visually hidden

Content some users must reach and others must not see: a table caption the layout already implies, a heading that structures the document without repeating a visible title, a description for an icon-only control. display: none and inline-size: 0 both remove it from the accessibility tree, which is the opposite of the goal.

There is a hidden sentence here. Off-screen, still announced. Nothing renders between the period and this word.

<caption data-visually-hidden>Standings by conference</caption>

It is an attribute, not a class. class stays the app's; data-* is valid HTML and needs no HTMLAttributes augmentation in React or TypeScript; and .visually-hidden / .sr-only are the most copy-pasted names in accessibility, so a project arriving with its own copy is the likely case rather than the edge case. Nothing to collide with.

focusable — the skip link

A skip link must be hidden until someone tabs to it, then visible. The variant hides only while unfocused; on focus the rule stops matching and the element keeps whatever styling you gave it — there is no undo rule fighting your CSS.

<a href="#main" data-visually-hidden="focusable">Skip to content</a>

Tab into this page from the address bar to see mica's own skip link.

What mica does not do for you

A stylesheet cannot supply an accessible name, a heading order, or a sensible tab sequence. Mica keeps the platform's semantics available and declines to break them; labelling controls, structuring headings, and testing with a screen reader remain yours.

← Presetvstack →