Ghost Button
How the Ghost Button works with a keyboard and assistive tech, and where it stands against WCAG 2.2 AA.
The Ghost Button is a native <button> with no fill until it is hovered, used where many actions sit side by side. Because it has no edge at rest, its label is the only thing that says it is a control, so that label has to read on its own.
Keyboard#
Moves focus to the button. A disabled button is skipped.
Moves focus to the previous focusable element.
Activates the button.
Activates the button when the key is released. A toggle flips its pressed state.
Semantics#
<button type="button">Native role and keyboard handling.
Alwaysaria-labelSet from the label, so an icon-only ghost button still has a name. Pair it with a Tooltip showing the same words.
Only iconaria-pressedPass it yourself when the button is on or off. The Active line is drawn by data-state, which assistive tech cannot see.
Toggles a tool or viewdisabledRemoved from the tab order and not announced as actionable.
Disabledaria-hiddenChevrons beside a label are decorative.
IconsColour contrast#
Every variant and state has to meet WCAG 2.2 Level AA. Measure the colours as they land on screen: a translucent hover or press wash over whatever sits behind it.
Label text · Rest, Hover, Active tint
The 16px bold label against the surface behind it. At rest that is the button's white fill (or the dark page for Inverse on dark); on hover and Active tint, a light wash of the intent.
WCAG 1.4.3 Contrast (Minimum) ↗Icon-only glyph · Only icon
The chevron that stands in for text needs 3:1 against the fill. Neutral's muted #8f8f8f measures 3.23:1 on white, so it passes for a glyph but not for a text label.
WCAG 1.4.11 Non-text Contrast ↗Active line · Active, Active tint
The 2px line is the only mark of the current tool, so it needs 3:1 against the surface. Neutral draws it #070707, other intents in their strong colour; Warning's #ff9000 line measures 2.27:1 on white. Back it with aria-pressed or aria-current so the state is not visual only.
WCAG 1.4.11 Non-text Contrast ↗WCAG 1.4.1 Use of Color ↗WCAG 4.1.2 Name, Role, Value ↗Focus indicator · Focus visible
A 2px #1a6ef8 stroke inside the box, 4.54:1 on white. Focus also darkens the label to the hover colour.
WCAG 1.4.11 Non-text Contrast ↗WCAG 2.4.13 Focus Appearance ↗Measured contrast#
Label against its own fill or wash, for every intent. Inverse on dark is measured on #2a2a2a, everything else on white. 10 of 18 pairs fall below their minimum (4.5:1 for text, 3:1 for graphics) and are marked in amber.
Motion#
- Colour changes take 150ms and the Active line slides up over 200ms. Both are turned off under prefers-reduced-motion, so the line simply appears.
Checklist#
Neutral at rest is #8f8f8f on white, below 4.5:1. It reads as muted on purpose, but the label is real text: darken it to #6d6d6d before the code library ships.
Warning (#be6a00), Success (#229a14) and Error (#ec0d33) labels sit below 4.5:1 on white and on their washes: see the table.
Every icon-only ghost button has an aria-label and a Tooltip with the same text.
A row of ghost buttons that switches views should mark the current one with aria-pressed, not only the line.
At 52px (42px icon-only) the button is well over the 24px target minimum.
