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.

PropertyDefault valueDescription
--np-badge-positionabsoluteThe CSS position of the badge.
--np-badge-top0 small, -0.125rem largeDistance from the top of the anchor.
--np-badge-startcalc(100% - 0.375rem) small, calc(100% - 0.75rem) largeDistance 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 propertyDefault value
--np-badge-positionabsolute
--np-badge-top0 small, -0.125rem large
--np-badge-startcalc(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

AttributeTypeDefaultDescription
labelstring | number | undefinedundefinedContent inside the badge. Without it, a small badge (dot) shows.
aria-labelstring | undefinedundefinedAnnounces 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.