P-05 · Primitives · Primitives
All elements · Pressable on the Primitives page
Last checked 2026-10-22 · Awaiting approval · Accessibility tests
Approve Pressable
Approving as
The single interaction target: focus ring, keyboard activation, hover/press/selected state, disabled
semantics. Button, Chip, Tab, Menu.Item and list rows are all Pressables. Use a real
<button> or <a>.
| Axis | Values |
|---|---|
data-shape |
circle |
data-icon-only · data-size |
square hit target / xs · sm · md |
data-block |
full width, start-aligned (list rows) |
aria-pressed · aria-selected · :disabled |
state |
Guidance
When to use
- Build a custom interactive target that needs the shared hover, press, selected, disabled and focus states.
-
Make an icon-only action, such as a row's more or close control, with
data-icon-only. - Make a full-width, start-aligned row in a list or nav with
data-block. - Serve as the base for Button, Chip, Tab, Menu items and list rows.
When to consider something else
- When you need a standard labeled action with variants and colors, use Button. See Button.
- When the action opens a list of commands, use Menu on a Button trigger. See Menu.
- When the target toggles a setting on and off, use Toggle. See Toggle.
- When the clickable element is a whole card or tile, use Card or an interactive Surface built on a real button. See Card.
Usability
-
Use a real
<button>for actions and<a href>for navigation. - Give every icon-only Pressable an
aria-labeland a Tooltip with the same name. -
Prefer
data-size="md"or the default for touch and dense lists alike; reservexsfor tight table cells. -
Use
aria-pressedfor toggles andaria-selectedfor selection inside a list or tab set.
- Don't put
qf-pressableon adivorspan. - Don't use
data-statein product code; it only pins states for the catalog. - Don't hide a disabled action that users need to discover; explain why it is unavailable.
Accessibility
Keyboard
| Keys | Action |
|---|---|
| Tab | Moves focus to the Pressable; Shift+Tab moves back. |
| Enter | Activates a button or follows a link. |
| Space | Activates a button (not a link). |
Roles and names
-
Native
buttonoragives the role. A button that is not in a form needstype="button". -
State is
aria-pressed,aria-selected,:disabledoraria-disabled="true"; never a class. -
Icon-only Pressables need an accessible name with
aria-label; the inner icon isaria-hidden. - The visible label must be part of the accessible name (2.5.3).
Focus
-
The global
:focus-visiblerule draws--qf-focus-ringaround the Pressable (2.4.7). -
:disabledremoves the Pressable from the tab order; usearia-disabled="true"when it must stay focusable to explain why. The CSS setspointer-events: noneon both, so the binding must also block activation by keyboard foraria-disabled.
Other requirements
-
Icon-only sizes come from
--qf-control-height-*:xsis 1.5rem (24px on desktop), the minimum for 2.5.8;smis 32px andmd44px. Do not shrink belowxs. - Selected and hover backgrounds are not enough by themselves; selected also changes the text to the primary color, and the state must be exposed in ARIA (4.1.2).
- Disabled text is exempt from contrast, but enabled text and icons need 4.5:1 and 3:1 (1.4.3, 1.4.11).
-
State changes animate for
--qf-duration-fast;prefers-reduced-motionremoves the transition.
Test your implementation too. This guidance covers the element as specified here. How a screen composes it (labels, order, announcements) still needs its own keyboard and screen reader check.
Accessibility tests
Passed the gate (run 358b316 on 2026-10-22): no finding in any theme. Awaiting a person’s approval of the checklist below.
| Area | Automated | A person checks |
|---|---|---|
| General | Passed | Color is never the only cue, text alternatives say the same thing as the graphic, and the element reads the same in the light and the dark theme. |
| Zoom | Passed | At 200% zoom, at 320 CSS pixels wide and with the WCAG text-spacing overrides, nothing is lost, clipped or overlapping. |
| Keyboard | Passed | Every row of the Keyboard table works, focus is always visible and never trapped, and the tab order follows the reading order. (3 rows) |
| Screen reader | Passed | With NVDA or JAWS on Windows and VoiceOver on macOS, names, roles and states are announced as Roles and names says, and changes are announced once. (4 items) |
Approving. When the checklist passes on the checked run, record it with
bun run a11y:approve -- pressable --by "Your name" and commit
a11y/approvals.json with the rebuilt pages.
All test status
Package
Consumers link one stylesheet, css/classic/index.css, which includes every element. The
files below are where this element is defined.
Latest updates
No recorded changes yet.