Badges
A badge marks an icon or a navigation item: a dot for something new, a number for a count. Only show counts people can act on.
Usage
Badges show notifications, counts or status on navigation items and icons. Place the badge next to
a 24px icon inside an element with position: relative. It then sits inside the icon
at its top trailing corner, mirrored for right-to-left text.
Small badge
Without a label a badge renders as a small dot, indicating new content.
<script lang="ts">
import { Badge } from 'noph-ui'
import { Icon } from 'noph-ui/icons'
</script>
<span style="position:relative;display:inline-flex">
<Icon>favorite</Icon>
<Badge />
</span>
Large badge
Set a label to show a number or short text. A large badge keeps its leading edge and
grows toward the trailing side. Counts above 999 show as 999+, so the badge stays at
four characters.
<script lang="ts">
import { Badge } from 'noph-ui'
import { Icon } from 'noph-ui/icons'
</script>
<div style="display:flex;gap:3rem">
<span style="position:relative;display:inline-flex">
<Icon>person</Icon>
<Badge label={6} />
</span>
<span style="position:relative;display:inline-flex">
<Icon>settings</Icon>
<Badge label={99} />
</span>
<span style="position:relative;display:inline-flex">
<Icon>mail</Icon>
<Badge label={1200} />
</span>
</div>
Positioning
Material 3 gives badges a fixed place on the icon. Only move one when its anchor is not a bare 24px icon, such as an icon button. The custom properties below accept any CSS length or keyword.
| Property | Default value | Description |
|---|---|---|
--np-badge-position | absolute | The CSS position of the badge. |
--np-badge-top | 0 small, -0.125rem large | Distance from the top of the anchor. |
--np-badge-start | calc(100% - 0.375rem) small, calc(100% - 0.75rem) large | Distance from the inline-start edge of the anchor to the badge's leading edge. |
Example
<script lang="ts">
import { Badge, IconButton } from 'noph-ui'
import { Icon } from 'noph-ui/icons'
</script>
<span style="position:relative;display:inline-flex">
<IconButton title="Mail"><Icon>mail</Icon></IconButton>
<Badge label={3} --np-badge-start="calc(100% - 1.25rem)" --np-badge-top="0.375rem" />
</span>
Theming
A badge takes its colors from the error role, so it stays legible in both color schemes. Use the custom properties below to position it when the element underneath is not a plain icon.
| Custom property | Default value |
|---|---|
--np-badge-position | absolute |
--np-badge-top | 0 small, -0.125rem large |
--np-badge-start | calc(100% - 0.375rem) small, calc(100% - 0.75rem) large |
The container color is --np-color-error and the label --np-color-on-error. Change both on an ancestor to recolor a badge. See Theming for the roles.
Accessibility
A badge is decorative by default and renders aria-hidden. The icon button or
navigation item it sits on carries the name.
In navigation bar, navigation rail and tabs, the badge is read after the destination's name as its
description: badgeAriaLabel if set, else the count, else New notification. Use badgeAriaLabel to translate that last one.
For a badge on its own, where the count is news, pass aria-label. The badge then gets role="status" with that name, and screen readers announce it when it changes. Write
the label in full: 3 unread messages, not 3.
API
Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
label | string | number | undefined | undefined | Content inside the badge. Without it, a small badge (dot) shows. |
aria-label | string | undefined | undefined | Announces the badge. Set it when the badge carries information that is not already in the
surrounding text, for example "3 unread messages". Without it the badge stays aria-hidden, which is right when it only repeats what is already labelled. |