# Data Primitives (`data-primitives`) - SignalOS widget

> Domain-agnostic presentational atoms for dense data surfaces: SectionLabel, MetaBox, EmptyState, TagList, and DataListRow. Pure props-in rendering, composable across any domain.

- **Version:** 0.1.1
- **Kind:** widget · **Category:** data-display
- **Install:** `npx shadcn@latest add @signalos/data-primitives`
- **Registry dependencies (pulled automatically):** @signalos/tokens, @signalos/utils, @signalos/badge
- **npm dependencies:** none
- **Files installed:** `src/components/widgets/data-primitives/DataPrimitives.tsx`, `src/components/widgets/data-primitives/DataPrimitives.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 { DataListRow, EmptyState, MetaBox, SectionLabel, TagList } from "@/components/widgets/data-primitives/DataPrimitives"
```

## Example

```tsx
// Example: dense data atoms composed inside a detail-panel section.
import { Link2, Tag, Zap } from "lucide-react"

import {
  DataListRow,
  EmptyState,
  MetaBox,
  SectionLabel,
  TagList,
} from "@/components/widgets/data-primitives/DataPrimitives"
import { StatusBadge } from "@/components/widgets/status-badge/StatusBadge"

export default function Example() {
  return (
    <div className="flex max-w-md flex-col gap-4">
      <div>
        <SectionLabel icon={<Zap className="h-3 w-3" />}>
          Contributing metrics
        </SectionLabel>
        <div className="mt-2">
          <TagList
            items={[
              "coverage_rate",
              "latency_p95",
              "error_rate",
              "queue_depth",
            ]}
            max={3}
          />
        </div>
      </div>

      <div className="grid grid-cols-3 gap-2">
        <MetaBox label="Age" value="3d 1h" />
        <MetaBox label="Routed" value="+37s" />
        <MetaBox label="Signals" value="16" />
      </div>

      <div>
        <SectionLabel icon={<Link2 className="h-3 w-3" />}>
          Related
        </SectionLabel>
        <ul className="mt-2 flex flex-col gap-1.5">
          <DataListRow
            leading={<StatusBadge severity="high" appearance="chip" />}
            eyebrow="6E7F3696"
            primary="Coverage collapse across tenants"
            badges={[{ label: "EXPIRED" }]}
            meta="2d ago"
            onSelect={() => {}}
          />
        </ul>
      </div>

      <div>
        <SectionLabel icon={<Tag className="h-3 w-3" />}>
          Transfers
        </SectionLabel>
        <div className="mt-2">
          <EmptyState
            icon={<Tag className="h-5 w-5" />}
            label="No transfers recorded."
          />
        </div>
      </div>
    </div>
  )
}
```

## Props

### `SectionLabelProps`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `icon` | `ReactNode` | no | - | Optional leading icon (typically a 12px lucide glyph). |
| `children` | `ReactNode` | yes | - | Uppercased mono eyebrow text. |
| `className` | `string \| undefined` | no | - |  |

### `MetaBoxProps`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `label` | `ReactNode` | yes | - | Small uppercased caption. |
| `value` | `ReactNode` | yes | - | Emphasised mono value. |
| `className` | `string \| undefined` | no | - |  |

### `EmptyStateProps`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `icon` | `ReactNode` | no | - | Optional muted illustration/icon. |
| `label` | `ReactNode` | yes | - | Primary message. |
| `description` | `ReactNode` | no | - | Optional supporting copy under the label. |
| `className` | `string \| undefined` | no | - |  |

### `TagListProps`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `items` | `readonly ReactNode[]` | yes | - | Values rendered as mono code chips. |
| `max` | `number \| undefined` | no | - | Cap the number of visible chips; the remainder collapses into a "+N" counter. Omit to show all. |
| `className` | `string \| undefined` | no | - |  |

### `DataListRowBadge`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `label` | `ReactNode` | yes | - |  |
| `variant` | `"default" \| "secondary" \| "outline" \| undefined` | no | `"secondary"` | Maps to the underlying Badge variant. |

### `DataListRowProps`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `leading` | `ReactNode` | no | - | Leading slot — a status badge, icon, or severity chip. |
| `eyebrow` | `ReactNode` | no | - | Optional mono identifier shown before the primary text. |
| `primary` | `ReactNode` | yes | - | Primary, truncating text. |
| `badges` | `readonly DataListRowBadge[] \| undefined` | no | - | Optional trailing pills (e.g. a status). |
| `meta` | `ReactNode` | no | - | Optional trailing meta (e.g. a relative timestamp). |
| `onSelect` | `(() => void) \| undefined` | no | - | Makes the row interactive with button semantics. |
| `className` | `string \| undefined` | no | - |  |

## Changelog

# data-primitives

## 0.1.1

- Add the missing `"use client"` directive - `DataListRow` wires
  `onClick`/`onKeyDown`, which crashes in a server-component tree without it.
## 0.1.0

- Initial release, extracted from the `attention-routing-01` block's local
  components. Ships five domain-agnostic atoms — `SectionLabel`, `MetaBox`,
  `EmptyState`, `TagList`, and `DataListRow` — as reusable, props-driven
  building blocks for dense data surfaces (cards, detail panels, list rows).
