PixelBadge

Compact status indicator that labels objects with tone, variant, and optional icon — renders as a pill (linear) or chamfered tag (pixel).

  • Four variants — soft (default), solid, outline, ghost — across all tone keys.
  • Three sizes (sm/md/lg) with consistent vertical rhythm and font scale.
  • Optional iconLeft slot for status dots, glyphs, or counters.
  • Becomes a native <button> with focus ring and hover when it handles clicks (onClick in React, @click in Vue, <button pxlBadge> in Angular).
  • Surface-aware: pixel chamfered border + pixel font, or linear pill.
Status
stable
Category
data
Since
v1.0.0

API

import { PixelBadge } from '@pxlkit/ui-kit';
PropTypeDefaultDescription
children (required)React.ReactNode—Badge content.
tone'green' | 'cyan' | 'gold' | 'red' | 'purple' | 'pink' | 'neutral''green'Tone tint. Defaults to 'green'.
surface'pixel' | 'linear'—Visual surface override.
variant'soft' | 'solid' | 'outline' | 'ghost''soft'Variant axis: soft (default), solid, outline, ghost.
size'sm' | 'md' | 'lg''md'Size scale. Defaults to 'md'.
iconLeftReact.ReactNode—Optional leading icon.
onClickReact.MouseEventHandler<HTMLElement>—When provided the root renders as a <button> for keyboard / SR parity.

Also takes the native attributes and event handlers of its element (HTMLAttributes<HTMLElement>).

ref points to its element (HTMLElement).

Accessibility

WCAG target: 2.1 AA

  • status

Default render is non-interactive. When it handles clicks (onClick, @click in Vue, button[pxlBadge] in Angular), the root is a native <button type="button"> with a visible focus ring (focus-visible:ring-2 ring-offset). iconLeft is marked aria-hidden via inline-flex wrapper — convey meaning through the badge text, not the icon alone. For live status changes (e.g., "online" → "offline"), wrap the badge in a parent with aria-live="polite".

Keyboard

KeyActionWhen
EnterActivates the badge when onClick is provided.interactive (onClick set)
SpaceActivates the badge when onClick is provided.interactive (onClick set)

Usage

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

export function Default() {
  return <PixelBadge>NEW</PixelBadge>;
}

Examples

Default

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

export function Default() {
  return <PixelBadge>NEW</PixelBadge>;
}

Tones

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

export function Tones() {
  return (
    <div className="flex flex-wrap items-center gap-2">
      <PixelBadge tone="neutral">neutral</PixelBadge>
      <PixelBadge tone="green">green</PixelBadge>
      <PixelBadge tone="cyan">cyan</PixelBadge>
      <PixelBadge tone="gold">gold</PixelBadge>
      <PixelBadge tone="red">red</PixelBadge>
      <PixelBadge tone="purple">purple</PixelBadge>
      <PixelBadge tone="pink">pink</PixelBadge>
    </div>
  );
}

Sizes

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

export function Sizes() {
  return (
    <div className="flex flex-wrap items-center gap-2">
      <PixelBadge size="sm" tone="cyan">small</PixelBadge>
      <PixelBadge size="md" tone="cyan">medium</PixelBadge>
      <PixelBadge size="lg" tone="cyan">large</PixelBadge>
    </div>
  );
}

Variants

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

export function Variants() {
  return (
    <div className="flex flex-wrap items-center gap-2">
      <PixelBadge variant="soft" tone="green">soft</PixelBadge>
      <PixelBadge variant="solid" tone="green">solid</PixelBadge>
      <PixelBadge variant="outline" tone="green">outline</PixelBadge>
      <PixelBadge variant="ghost" tone="green">ghost</PixelBadge>
    </div>
  );
}

Surfaces

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

export function Surfaces() {
  return (
    <div className="flex flex-wrap items-center gap-3">
      <PixelBadge surface="pixel" tone="gold">pixel</PixelBadge>
      <PixelBadge surface="linear" tone="gold">linear</PixelBadge>
    </div>
  );
}

With Icon

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

const DotIcon = () => (
  <span
    aria-hidden
    style={{ width: 6, height: 6, borderRadius: 9999, background: 'currentColor', display: 'inline-block' }}
  />
);

export function WithIcon() {
  return (
    <div className="flex flex-wrap items-center gap-2">
      <PixelBadge tone="green" iconLeft={<DotIcon />}>online</PixelBadge>
      <PixelBadge tone="red" iconLeft={<DotIcon />}>error</PixelBadge>
      <PixelBadge tone="gold" iconLeft={<DotIcon />}>warn</PixelBadge>
    </div>
  );
}

Clickable

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

export function Clickable() {
  return (
    <PixelBadge tone="cyan" variant="outline" onClick={() => undefined}>
      click me
    </PixelBadge>
  );
}

Related