/// Utilities
VisuallyHidden
Hides content visually while keeping it in the accessibility tree.
import { VisuallyHidden } from "@protocore/pds";Basics
The classic use: an icon-only control. The visible glyph carries no text, so a VisuallyHidden label gives screen-reader users a name without adding visible chrome.
Extra spoken context
Add a hidden heading to structure a region for assistive tech, or spell out a terse visible value ("99.98%") so it isn't announced without context. The hidden text stays fully in the accessibility tree.
99.98%
uptime over the last 30 daysuptime
When to use it
VisuallyHidden removes content from view while leaving it available to screen readers — the opposite of aria-hidden (which hides from assistive tech but not the eye). Reach for it to name icon-only controls, add skip links, label form regions, or supply context to a terse value. It renders a <span> using the shared .pds-VisuallyHidden primitive (the standard clip technique — not display:none, which would drop it from the a11y tree). Prefer a direct aria-label when the element accepts one; use VisuallyHidden when you need *real text content* in the tree (e.g. inside a button that also has an icon, or a link whose visible text is an icon).
Usage
Do
- Name icon-only buttons and links with a VisuallyHidden label (or an `aria-label`).
- Use it for skip links that become visible on focus.
- Add spoken context to terse values and stat numbers.
- Keep the hidden text concise and meaningful — it is read verbatim.
Don't
- Don't use `display:none` or `visibility:hidden` for this — those remove the text from the a11y tree.
- Don't hide genuinely important, sighted-user-relevant content with it.
- Don't duplicate a label that's already announced, causing double reading.
- Don't put interactive elements inside it expecting them to be reachable — hidden focusable content is a trap; use a focus-revealing skip link pattern instead.
Accessibility
- Uses the clip/off-screen technique, so content stays in the accessibility tree and is announced normally.
- It does not remove elements from tab order — avoid placing focusable controls inside unless you intend a focus-revealed skip link.
- This is the same primitive Radix uses internally to label its components; safe to compose with Radix triggers.
- For content that should be hidden from *screen readers* but visible on screen, use `aria-hidden` instead — VisuallyHidden is the inverse.
VisuallyHidden props
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | |
style | CSSProperties | — |