PixelBadgeGroup

Inline row of badges with automatic "+N" overflow popover when the count exceeds max.

  • Renders the first max - 1 badges inline; remaining items collapse into a "+N" trigger.
  • Overflow trigger opens a PixelPopover with the hidden badges, surface-matched.
  • Wrapper becomes role="group" when an accessible name (aria-label or aria-labelledby) is provided.
  • Surface-aware: pixel chamfered radius + pixel font or linear pill, propagated to the popover.
Status
stable
Category
data
Since
v1.9.0

API

import { PixelBadgeGroup } from '@pxlkit/ui-kit';
PropTypeDefaultDescription
maxnumber5Most places the row shows; beyond it, the last place becomes a "+N" button that opens a popover with the rest.
surface'pixel' | 'linear'—Surface override, for the row and its popover; defaults to the nearest provider.
aria-labelstring—Optional accessible name for the group. When provided, the wrapper renders role="group" so SR users can navigate the landmark; otherwise it stays a plain div to avoid an unlabeled group announcement.
aria-labelledbystring—Id of the element that names the group, in place of aria-label.
children (required)React.ReactNode—The badges.

Also takes the native attributes and event handlers of <div> (HTMLAttributes<HTMLDivElement>).

ref points to <div>.

Accessibility

WCAG target: 2.1 AA

  • group
  • disclosure

Group landmark is only emitted when an accessible name is supplied to avoid an unlabeled "group" announcement. The overflow button carries aria-label="Show N more", aria-expanded, aria-haspopup="dialog", and aria-controls wired by PixelPopover; it also names the popover dialog through aria-labelledby.

Keyboard

KeyActionWhen
EnterOpens the overflow popover.focus on +N trigger
SpaceOpens the overflow popover.focus on +N trigger
EscapeCloses the overflow popover.overflow popover is open

Usage

import { PixelBadgeGroup, PixelBadge } from '@pxlkit/ui-kit';

export function Default() {
  return (
    <PixelBadgeGroup aria-label="Tags">
      <PixelBadge tone="cyan">react</PixelBadge>
      <PixelBadge tone="green">typescript</PixelBadge>
      <PixelBadge tone="gold">design</PixelBadge>
    </PixelBadgeGroup>
  );
}

Examples

Default

import { PixelBadgeGroup, PixelBadge } from '@pxlkit/ui-kit';

export function Default() {
  return (
    <PixelBadgeGroup aria-label="Tags">
      <PixelBadge tone="cyan">react</PixelBadge>
      <PixelBadge tone="green">typescript</PixelBadge>
      <PixelBadge tone="gold">design</PixelBadge>
    </PixelBadgeGroup>
  );
}

Overflow +N

import { PixelBadgeGroup, PixelBadge } from '@pxlkit/ui-kit';

export function Overflow() {
  return (
    <PixelBadgeGroup aria-label="Stack" max={3}>
      <PixelBadge tone="cyan">react</PixelBadge>
      <PixelBadge tone="green">typescript</PixelBadge>
      <PixelBadge tone="gold">design</PixelBadge>
      <PixelBadge tone="purple">tailwind</PixelBadge>
      <PixelBadge tone="pink">motion</PixelBadge>
      <PixelBadge tone="red">vitest</PixelBadge>
    </PixelBadgeGroup>
  );
}

Surfaces

import { PixelBadgeGroup, PixelBadge } from '@pxlkit/ui-kit';

export function Surfaces() {
  return (
    <div className="flex flex-col gap-3">
      <PixelBadgeGroup aria-label="Pixel tags" surface="pixel">
        <PixelBadge tone="cyan">pixel</PixelBadge>
        <PixelBadge tone="green">chamfered</PixelBadge>
        <PixelBadge tone="gold">retro</PixelBadge>
      </PixelBadgeGroup>
      <PixelBadgeGroup aria-label="Linear tags" surface="linear">
        <PixelBadge tone="cyan">linear</PixelBadge>
        <PixelBadge tone="green">pill</PixelBadge>
        <PixelBadge tone="gold">modern</PixelBadge>
      </PixelBadgeGroup>
    </div>
  );
}

Related