Data displaystable.count
Count bubble
A small red bubble with a number of new or open items ("3 ungelesen"), on nav items, tab bar items and buttons.
Use the count bubble to say "something new needs you here": unread messages, open registrations, pending AI proposals. It sits on a nav item, a tab bar item or next to a heading.
Give it an accessible label that says what is counted ("3 offene Anmeldungen"). The visible number is hidden from screen readers and the label is read instead, so "Mitglieder 3" becomes "Mitglieder, 3 offene Anmeldungen".
With value: 0 nothing is rendered (unless showZero), so callers can always pass the current number. Large numbers are capped at max and shown as "99+".
Examples
Unread messages
Data
render({
"value": 3,
"label": "3 ungelesen"
})Markup
<span class="count"><span aria-hidden="true">3</span><span class="u-visually-hidden">3 ungelesen</span></span>Capped
Data
render({
"value": 128,
"label": "128 offene Anmeldungen"
})Markup
<span class="count"><span aria-hidden="true">99+</span><span class="u-visually-hidden">128 offene Anmeldungen</span></span>Without label (number is self-explanatory in context)
Data
render({
"value": 1
})Markup
<span class="count">1</span>Data contract
What render(data) accepts — validated against this JSON Schema in development and tests. Unknown fields are rejected. The same schema is in components.json.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
value | integer | required | — | Number of items. ≥ 0 |
label | string | optional | — | Accessible text with number and noun, e.g. "3 ungelesen", "3 offene Anmeldungen". Read instead of the bare number. Strongly recommended. min 1 chars |
max | integer | optional | 99 | Above this value the bubble shows "{max}+". The label should still contain the exact number.≥ 9 |
showZero | boolean | optional | false | Render the bubble for 0 as well (rarely useful; by default 0 renders nothing). |
JSON Schema
{
"type": "object",
"additionalProperties": false,
"required": [
"value"
],
"properties": {
"value": {
"type": "integer",
"minimum": 0,
"description": "Number of items."
},
"label": {
"type": "string",
"minLength": 1,
"description": "Accessible text with number and noun, e.g. \"3 ungelesen\", \"3 offene Anmeldungen\". Read instead of the bare number. Strongly recommended."
},
"max": {
"type": "integer",
"minimum": 9,
"default": 99,
"description": "Above this value the bubble shows \"{max}+\". The `label` should still contain the exact number."
},
"showZero": {
"type": "boolean",
"default": false,
"description": "Render the bubble for 0 as well (rarely useful; by default 0 renders nothing)."
}
}
}Markup & states
Root: span.count — usable without render() by writing the markup directly.
Parts
| Part | Description |
|---|---|
span[aria-hidden="true"] | The visible number (only when label is set). |
.u-visually-hidden | The accessible label, read instead of the number. |
Accessibility
- The number alone is meaningless to a screen reader ("Mitglieder 3"); always pass
labelunless the surrounding text already says what is counted. - The count bubble is not a live region. If counts change while the page is open, announce important changes elsewhere (e.g. a toast), not on every update.
- Text is white on
--color-danger(verified pair--color-on-status).
Guidance
Related: Status badge · App shell · Chip group