# Badge List (`badge-list`) - SignalOS widget

> Wrapping row of badges for any item list, each with an optional info popover showing per-item detail rows.

- **Version:** 0.1.2
- **Kind:** widget · **Category:** data-display
- **Install:** `npx shadcn@4.1.2 add @signalos/badge-list`
- **Registry dependencies (pulled automatically):** @signalos/tokens, @signalos/utils, @signalos/badge, @signalos/popover
- **npm dependencies:** lucide-react@^1.7.0
- **Files installed:** `src/components/widgets/badge-list/BadgeList.tsx`, `src/components/widgets/badge-list/BadgeList.types.ts`

## Access

This is a private registry: pulling source requires a `SIGNALOS_REGISTRY_TOKEN`
(GitHub fine-grained PAT with read access to the signal-widgets repo) and an
`@signalos` entry in components.json `"registries"`. Previews and this document are public.

## Usage

```tsx
import { BadgeList } from "@/components/widgets/badge-list/BadgeList"
```

## Example

```tsx
// Example: the snippet shown as public example code in the catalog.
import { BadgeList } from "@/components/widgets/badge-list/BadgeList"

interface Tag {
  id: string
  label: string
  category: string
}

const tags: Tag[] = [
  { id: "tag_1", label: "payments", category: "domain" },
  { id: "tag_2", label: "risk", category: "domain" },
  { id: "tag_3", label: "beta", category: "lifecycle" },
]

export default function Example() {
  return (
    <BadgeList
      items={tags}
      label="Tags"
      getLabel={(tag) => tag.label}
      getDetailRows={(tag) => [{ label: "Category", value: tag.category }]}
    />
  )
}
```

## Props

### `BadgeListItem`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `id` | `string` | yes | - |  |
| `use_case_id` | `string \| undefined` | no | - |  |

### `BadgeListDetailRow`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `label` | `string` | yes | - |  |
| `value` | `string` | yes | - |  |

### `BadgeListProps`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `items` | `readonly TItem[]` | yes | - |  |
| `getLabel` | `((item: TItem) => string) \| undefined` | no | `(item) => item.id` | Text shown on each badge. |
| `getTitle` | `((item: TItem) => ReactNode) \| undefined` | no | - | Popover heading shown above the detail rows. Defaults to the badge label when omitted. |
| `getDescription` | `((item: TItem) => ReactNode) \| undefined` | no | - | Optional descriptive line shown under the popover heading. |
| `getDetailRows` | `((item: TItem) => BadgeListDetailRow[] \| undefined) \| undefined` | no | - | Label/value rows shown in the badge's info popover. Omit to render plain badges with no popover affordance for that item. |
| `label` | `string \| null \| undefined` | no | - | Section heading. Pass `null` to render only the badges. |
| `labelVariant` | `"plain" \| "mono" \| undefined` | no | `"plain"` | Heading typography. `mono` matches the signal-rules / equilibrium detail panels; `plain` matches glossary, relationships and cross-source. |
| `max` | `number \| undefined` | no | - | Show at most this many, then a "+N more" badge. |
| `getVariant` | `((item: TItem) => "success" \| "warning" \| "error" \| "secondary" \| undefined) \| undefined` | no | - | Colour each badge by a caller-supplied variant instead of the neutral secondary tone (e.g. status-driven colouring). Off by default so a list of tags stays visually quiet next to the status badges a row already carries. |
| `size` | `"sm" \| "md" \| undefined` | no | `"md"` | Compact sizing for dense queue rows. |
| `className` | `string \| undefined` | no | - |  |
| `data-testid` | `string \| undefined` | no | - | Test identifier rendered as `data-testid` on the root element. |

## Changelog

# badge-list

## 0.1.2

- Initial release: a wrapping row of badges built from any item list
  (`items: readonly TItem[]`, `TItem extends { id: string }`). Badge text
  comes from `getLabel`; an item optionally gets an info-popover affordance
  when `getDetailRows` returns rows for it. `getVariant` colours a badge,
  `max` caps visible badges behind a "+N more" badge, and `size`/`label`/
  `labelVariant` match the existing queue-row and detail-panel conventions.
