Base components
Badge group
A pill link that holds a small badge and a short message, for announcements at the top of a page, which eases its colors on hover and nudges its arrow toward the link target.
Live preview
Loading preview
Four badge groups above a page heading: leading "New" with "Projects now support shared views" (Pill color, Brand), trailing "Read the update" with "Version 2.4 is available" (Badge modern, Gray), and Error and Success versions at size lg. Replay hovers the first one.
Installation
Run this in your app after the one-time setup on the Getting started page.
$ npx @ganisigit/lunia-ds add badge-groupUsage
The demo above, as code.
'use client';
import * as React from 'react';
import { BadgeGroup } from './badge-group';
export default function BadgeGroupDemo({ replay = 0 }: { replay?: number }) {
const [hovered, setHovered] = React.useState(false);
// Replay shows the hover look of the first badge group for a moment.
React.useEffect(() => {
if (replay === 0) return;
setHovered(true);
const timer = window.setTimeout(() => setHovered(false), 900);
return () => window.clearTimeout(timer);
}, [replay]);
return (
<div className="flex flex-col items-center gap-4">
<BadgeGroup badge="New" color="brand" data-hovered={hovered ? '' : undefined}>
Projects now support shared views
</BadgeGroup>
<BadgeGroup badge="Read the update" badgePosition="trailing" type="badge-modern" color="gray">
Version 2.4 is available
</BadgeGroup>
<BadgeGroup badge="Error" color="error" size="lg">
Payments are paused for this account
</BadgeGroup>
<BadgeGroup badge="Done" type="badge-modern" color="success" size="lg">
Your workspace is ready
</BadgeGroup>
</div>
);
}
API
Parts: root (link or button, pill or rounded box), badge (small inner badge with its own fill and border), message (text, or a dot and text for Badge modern), arrow icon (after the message, or inside the trailing badge).
| Prop | Type | Default | Description |
|---|---|---|---|
| badge | string | undefined | Text of the inner badge, for example "New". |
| badgePosition | "leading" | "trailing" | "leading" | Side of the message where the inner badge sits. With trailing, the arrow moves into the badge. |
| type | "pill-color" | "badge-modern" | "pill-color" | pill-color: a round pill in the color set. badge-modern: a neutral rounded box with a colored dot and a small shadow. |
| color | "brand" | "gray" | "error" | "warning" | "success" | "brand" | Color set from the utility color tokens, as in Badge. |
| size | "md" | "lg" | "md" | 30 or 32px tall; Text xs or Text sm. |
| icon | boolean | true | Shows the arrow icon. |
| href | string | undefined | Renders a link. Without href the root is a button and fires click. |
| disabled | boolean | false | Turns the button off (50% opacity). Links are not disabled; hide them instead. |
| Event | Description |
|---|---|
| click | Fires on activation when there is no href. |
| Slot | Description |
|---|---|
| default | Message text. |
| icon | Replaces the arrow icon. |
Motion
Every row names a token from the Motion page. The last column says what happens when the user asks for reduced motion.
| ID | Trigger | Element | Property | From → to | Timing | Reduced motion |
|---|---|---|---|---|---|---|
| BGP1 | hover | root, inner badge | background-color, border-color | Default colors (for example utility-brand-50) → Hover colors (for example utility-brand-100) | duration-sm (200)ease-out | Swaps at once |
| BGP2 | hover | arrow icon | translate-x | 0 → distance-rise (toward the link target) | duration-sm (200)ease-out | Stays still |
| BGP3 | hover ends | arrow icon | translate-x | distance-rise → 0 | duration-xs (160)ease-exit | Stays still |
| BGP4 | press | root | scale | 1 → scale-press | duration-sm (200)ease-out | Stays still |
| BGP5 | keyboard focus | root | box-shadow | none → focus ring (2px bg-primary gap, 4px focus-ring) | duration-2xs (120)ease-out | Shows at once |
Accessibility
- With href the root is a native link; without it, a native button. The whole pill is one target and one tab stop.
- The accessible name is the badge text and the message in reading order (for example "New Projects now support shared views"); the arrow and the dot are aria-hidden.
- When color carries meaning (Error, Warning), the badge text says it in words.
- Size md is 30px tall, so the target meets the 24px minimum (WCAG 2.5.8).
- Reduced motion: colors swap at once, the arrow does not move and the pill does not scale.