---
title: Status Dot
description: A dot in the line beside a value, which carries a state in its color, names it for a screen reader and explains it in a tooltip
visibility: guest
draft: false
---

# Status Dot

A small dot that sits in the line beside a value, such as a stock figure in a table cell, and carries
a state in its color. Its `label` is what the dot means: the name a screen reader reads, and the text
of a tooltip that opens on hover and on keyboard focus.

Use it where a word would crowd the value it belongs to. Where there is room for the word, a
[badge](/components/badge) says it on screen. To pin a dot to the corner of an avatar or an icon, place
it in an [indicator](/components/indicator).

## Basic Usage

:::preview{title="Beside a number in a table"}
<x-wirekit::table>
    <x-wirekit::table.head>
        <x-wirekit::table.row>
            <x-wirekit::table.th>Product</x-wirekit::table.th>
            <x-wirekit::table.th align="right">Stock</x-wirekit::table.th>
        </x-wirekit::table.row>
    </x-wirekit::table.head>
    <x-wirekit::table.body>
        <x-wirekit::table.row>
            <x-wirekit::table.td>Espresso beans 1kg</x-wirekit::table.td>
            <x-wirekit::table.td align="right">42</x-wirekit::table.td>
        </x-wirekit::table.row>
        <x-wirekit::table.row>
            <x-wirekit::table.td>Oat milk 1l</x-wirekit::table.td>
            <x-wirekit::table.td align="right">3 <x-wirekit::status-dot intent="warning" label="Low stock: fewer than 5 left" /></x-wirekit::table.td>
        </x-wirekit::table.row>
        <x-wirekit::table.row>
            <x-wirekit::table.td>Paper cups 300ml</x-wirekit::table.td>
            <x-wirekit::table.td align="right">-1 <x-wirekit::status-dot intent="danger" label="Oversold: more sold than in stock" /></x-wirekit::table.td>
        </x-wirekit::table.row>
    </x-wirekit::table.body>
</x-wirekit::table>
:::

The tooltip opens above the dot by default. Beside a number in a right-aligned cell, a tooltip that
opens to the side covers the number it explains. `placement` moves it.

## Intents

The dot takes the intents a badge takes. Each one paints in the color its intent uses for text, which
the shipped themes tune to read on the page, so a dot stays at 3:1 or more against it.

:::preview{title="Every intent"}
<x-wirekit::row gap="md">
    <x-wirekit::status-dot intent="primary" label="Primary" />
    <x-wirekit::status-dot intent="accent" label="Accent" />
    <x-wirekit::status-dot intent="success" label="Success" />
    <x-wirekit::status-dot intent="warning" label="Warning" />
    <x-wirekit::status-dot intent="danger" label="Danger" />
    <x-wirekit::status-dot intent="info" label="Info" />
    <x-wirekit::status-dot label="Neutral" />
</x-wirekit::row>
:::

## Sizes

`sm` is 6px, `md` (the default) 8px and `lg` 10px.

:::preview{title="Three sizes"}
<x-wirekit::row gap="md">
    <x-wirekit::status-dot intent="success" size="sm" label="Online" />
    <x-wirekit::status-dot intent="success" label="Online" />
    <x-wirekit::status-dot intent="success" size="lg" label="Online" />
</x-wirekit::row>
:::

## Inside a link or a button

A dot with a tooltip takes a tab stop of its own, so a keyboard reaches the tooltip. Inside a link or
a button that is a second tab stop inside the first. Set `:focusable="false"` there: the control is
the tab stop, the dot's label becomes part of the control's name, and the tooltip still opens on
hover.

:::preview{title="A tab with unsaved changes"}
<x-wirekit::link href="#">Order 1042 <x-wirekit::status-dot intent="warning" label="Unsaved changes" :focusable="false" /></x-wirekit::link>
:::

## Without a label

A dot without a `label` is decorative: it is hidden from assistive technology and has no tooltip. Say
what it means in text beside it, or it means nothing to anybody who cannot see the color.

```blade
<x-wirekit::status-dot intent="success" />
<span class="sr-only">Online</span>
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `intent` | `string` | `'neutral'` | `primary`, `accent`, `success`, `warning`, `danger`, `info` or `neutral` |
| `label` | `string\|null` | `null` | What the dot means: its accessible name and the text of its tooltip. Without it the dot is decorative |
| `tooltip` | `bool` | `true` | Show the label in a tooltip on hover and keyboard focus. A dot without a label has none |
| `placement` | `string` | `'top'` | Where the tooltip opens, as the [tooltip](/components/tooltip) takes it |
| `focusable` | `bool` | `true` | Whether a dot with a tooltip takes a tab stop of its own. Set `false` inside a link or a button |
| `size` | `string` | `'md'` | `sm` (6px), `md` (8px) or `lg` (10px) |
| `scope` | `string\|null` | `null` | Scoped personalization name |

## Accessibility

- **A labeled dot is an image with a name.** It renders `role="img"` with the label as its
  `aria-label`, so a screen reader reads the state where the dot stands, in browse mode as well as on
  focus. An `aria-label` or `aria-labelledby` you write replaces the label as the name, and the label
  then describes the dot through its tooltip. A `role` you write replaces `img`.
- **The tooltip does not repeat the name.** Its text is the label, which the dot already carries as
  its name, so it is not added as a description as well.
- **Color is not the only signal.** The label says in words what the color shows, and a dot without
  one is hidden from assistive technology rather than left as a color nobody can name.
- **Contrast.** A dot that carries information needs 3:1 against the page (WCAG 1.4.11). Each intent
  paints in its color for text, which reaches that in the light and the dark theme. The fill colors do
  not: the warning fill falls under it on a light page.
- **Forced colors.** The system repaints every fill in the page's own color, which would take the dot
  away. The dot keeps a fill in the text color there; its hue is gone in that mode, and its name and
  tooltip carry what it means.

## Keyboard Interaction

| Key | Action |
| --- | --- |
| `Tab` | Moves focus to a dot that has a tooltip and is focusable, and opens the tooltip |
| `Escape` | Closes the tooltip |

A dot without a tooltip, or with `:focusable="false"`, takes no focus.

## Pitfalls

- **Don't rely on the color alone.** A dot without a `label` says nothing to a screen reader or to
  anybody who cannot tell the colors apart. Give it a label, or write the state beside it.
- **Don't leave a focusable dot inside a link or a button.** It is a tab stop inside a tab stop. Use
  `:focusable="false"` there.

## Design Tokens

| Token | Purpose |
| --- | --- |
| `--color-wk-accent-text` | Dot of `primary` and `accent` |
| `--color-wk-success-text` / `--color-wk-warning-text` / `--color-wk-danger-text` / `--color-wk-info-text` | Dot of `success`, `warning`, `danger` and `info` |
| `--color-wk-text-muted` | Dot of `neutral` |

The tooltip takes the [tooltip](/components/tooltip)'s tokens.

## Further Reading

- [WCAG 1.4.1: Use of Color](https://www.w3.org/WAI/WCAG21/Understanding/use-of-color.html)
- [WCAG 1.4.11: Non-text Contrast](https://www.w3.org/WAI/WCAG21/Understanding/non-text-contrast.html)
- [MDN: ARIA `img` role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/img_role)
