Indicator
Pins a small thing — an unread count, a status dot, a "NEW" ribbon — to the corner of any target: a bell icon, an avatar, a card, a button.
It exists so you stop hand-rolling absolute positioning with negative corner
offsets on every one of them. That pattern is exactly the raw-div scaffolding a
component library is supposed to replace — and it silently breaks in RTL.
Basic Usage
Corners
position is logical: end is the right corner in LTR and the left
corner in RTL, so the badge follows the reading direction on its own.
Offset
By default the badge is centered on the corner. offset nudges it further out.
Naming the badge
The badge must say what it means. A bare "3" next to a bell tells a screen-reader user nothing.
{{-- 1. A count: name it, and hide the raw number from assistive tech --}}
<x-wirekit::indicator>
<x-wirekit::button icon-only aria-label="Notifications">
<x-wirekit::icon name="bell" size="md" />
</x-wirekit::button>
<x-slot:badge>
<x-wirekit::badge intent="danger" size="sm">
<span aria-hidden="true">{{ $unread }}</span>
<span class="sr-only">{{ $unread }} unread notifications</span>
</x-wirekit::badge>
</x-slot:badge>
</x-wirekit::indicator>
{{-- 2. A purely decorative presence dot: hide it, and say it elsewhere --}}
<x-wirekit::indicator position="bottom-end">
<x-wirekit::avatar :alt="$user->name" />
<x-slot:badge>
<span aria-hidden="true" style="width:.625rem;height:.625rem;border-radius:9999px;background:var(--color-wk-success);display:block"></span>
</x-slot:badge>
</x-wirekit::indicator>
<span class="sr-only">{{ $user->name }} is online</span>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
position |
string | 'top-end' |
top-end, top-start, bottom-end, bottom-start — logical, so end follows the reading direction |
offset |
string|null | null |
Nudge the badge further out (any CSS length); default centers it on the corner |
scope |
string|null | null |
Scoped personalization name |
Slots
| Slot | Description |
|---|---|
| default | The target being decorated |
badge |
The thing anchored to the corner |
Accessibility
- The badge carries its own meaning. Indicator only positions it. A count
needs a real name (
3 unread notifications), and a decorative dot needsaria-hiddenplus the state stated elsewhere — see the examples above. - The badge is
pointer-events: none, so it never swallows a click meant for the target underneath. Anything genuinely interactive inside it (a link, a button) gets pointer events back automatically. - The badge is out of flow, so decorating a target never resizes it — no layout shift, no touch target shrinking.
- RTL is automatic: placement uses logical insets, so
endmoves to the left corner underdir="rtl"with no extra rules.
Keyboard Interaction
This component is presentational and does not respond to keyboard input. The target and any control inside the badge keep their own keyboard behavior.
Pitfalls
- Do not leave a bare number as the whole badge. "3" is not an accessible name — say "3 unread notifications".
- Do not put your main action in the badge. It is a decoration on the target, not a second control competing for the same corner.
- Do not hand-roll the absolute-corner-offset pattern. That is what this replaces — and it does not mirror in RTL.
Design Tokens
| Element | Token |
|---|---|
| Corner nudge | --indicator-wk-offset (default 0px) |
The badge's own colors and shape come from whatever you place in the slot — usually Badge.