# Ranked List Card (`ranked-list-card`) - SignalOS widget

> Dense three-zone list card with a rank + confidence arc, header badges, a lifecycle pill chain, and trailing meta blocks. Fully props-driven and domain-agnostic, with an escalation ribbon, urgency/severity accents, selected state, and a loading skeleton.

- **Version:** 0.1.2
- **Kind:** widget · **Category:** data-display
- **Install:** `npx shadcn@latest add @signalos/ranked-list-card`
- **Registry dependencies (pulled automatically):** @signalos/tokens, @signalos/utils, @signalos/skeleton, @signalos/circular-progress, @signalos/status-badge
- **npm dependencies:** lucide-react@^1.7.0
- **Files installed:** `src/components/widgets/ranked-list-card/RankedListCard.tsx`, `src/components/widgets/ranked-list-card/RankedListCard.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 { RankedListCard } from "@/components/widgets/ranked-list-card/RankedListCard"
```

## Example

```tsx
// Example: a ranked queue item mapped from arbitrary domain data.
import { ArrowUpRight, Clock, Layers, Route, Zap } from "lucide-react"

import { RankedListCard } from "@/components/widgets/ranked-list-card/RankedListCard"
import { StatusBadge } from "@/components/widgets/status-badge/StatusBadge"

export default function Example() {
  return (
    <RankedListCard
      severity="high"
      urgency="urgent"
      ribbon={{
        label: "Escalated",
        icon: <ArrowUpRight className="h-2.5 w-2.5" />,
      }}
      rank={{ value: "#2", progress: 62, progressColorClass: "text-primary" }}
      badges={
        <>
          <StatusBadge severity="high" appearance="chip" />
          <StatusBadge appearance="chip">IN PROGRESS</StatusBadge>
          <span className="flex items-center gap-1 font-mono text-[10px] text-muted-foreground">
            <Layers className="h-2.5 w-2.5" /> 16 signals
          </span>
        </>
      }
      title="Coverage collapse across multiple tenants"
      meta={
        <>
          <span>interoperability</span>
          <span className="text-muted-foreground/30">·</span>
          <code className="text-[10.5px]">coverage_rate</code>
        </>
      }
      pills={[
        { label: "Signal", icon: <Zap className="h-2.5 w-2.5" /> },
        { label: "Hyp +1h" },
        {
          label: "Routed +37s",
          icon: <Route className="h-2.5 w-2.5" />,
          emphasized: true,
        },
      ]}
      trailing={[
        {
          label: "Act by",
          value: (
            <span className="inline-flex items-center gap-1 font-mono font-semibold text-warning-500">
              <Clock className="h-3 w-3" /> 3h 12m
            </span>
          ),
        },
        { label: "Routed to", value: "Ops reviewer", detail: "admin" },
      ]}
      trailingFooter="score 0.746"
      onOpen={() => {}}
    />
  )
}
```

## Props

### `RankedCardPill`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `label` | `ReactNode` | yes | - | Pill text. |
| `icon` | `ReactNode` | no | - | Optional leading icon. |
| `emphasized` | `boolean \| undefined` | no | `false` | Highlights the pill with the primary accent. |

### `RankedCardMetaBlock`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `label` | `ReactNode` | yes | - | Uppercased caption. |
| `value` | `ReactNode` | yes | - | Value ReactNode (string, number, or styled node). |
| `detail` | `ReactNode` | no | - | Optional secondary line under the value. |

### `RankedCardRank`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `label` | `ReactNode` | no | `"Rank"` | Caption above the rank number. |
| `value` | `ReactNode` | yes | - | The rank value, e.g. `#2`. |
| `progress` | `number \| undefined` | no | - | Optional 0–100 arc value rendered under the rank. |
| `progressColorClass` | `string \| undefined` | no | - | Tailwind text-* class driving the arc color. |

### `RankedCardRibbon`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `label` | `ReactNode` | yes | - |  |
| `icon` | `ReactNode` | no | - |  |

### `RankedListCardProps`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `severity` | `Severity \| null \| undefined` | no | - | Severity driving the accent border. When `urgency` is set it takes precedence for the border tint. |
| `urgency` | `"none" \| "past-due" \| "urgent" \| undefined` | no | - | Urgency accent, independent of severity — e.g. proximity to a deadline. `past-due` → error border, `urgent` → warning border. |
| `selected` | `boolean \| undefined` | no | - | Selected state (ring + primary border). |
| `ribbon` | `RankedCardRibbon \| undefined` | no | - | Optional corner ribbon. |
| `rank` | `RankedCardRank \| undefined` | no | - | Left-column rank + arc. Omit to hide the whole left column. |
| `badges` | `ReactNode` | no | - | Header badges/chips rendered above the title (StatusBadge, etc.). |
| `title` | `ReactNode` | yes | - | Primary title (line-clamped to 2). |
| `meta` | `ReactNode` | no | - | Sub-title meta row under the title (domain, metric, deviation…). |
| `pills` | `readonly RankedCardPill[] \| undefined` | no | - | Horizontal lifecycle pill chain. |
| `trailing` | `readonly RankedCardMetaBlock[] \| undefined` | no | - | Trailing stacked meta blocks (desktop only). |
| `trailingFooter` | `ReactNode` | no | - | Small trailing footer line under the trailing blocks (e.g. a score). |
| `mobileFooter` | `ReactNode` | no | - | Content for the mobile-only footer strip. |
| `onOpen` | `(() => void) \| undefined` | no | - | Invoked on click / Enter / Space. |
| `className` | `string \| undefined` | no | - |  |
| `data-testid` | `string \| undefined` | no | - |  |

## Changelog

# ranked-list-card
## 0.1.2
- Resolved a merge conflict.
## 0.1.1

- Format source with the repo prettier config (no behavior change).

## 0.1.0

- Initial release, genericized from the `attention-routing-01` block's
  `RoutingFeedCard`. The domain routing/hypothesis shapes are replaced by
  generic props (`rank`, `badges`, `title`, `meta`, `pills`, `trailing`,
  `ribbon`, `urgency`, `severity`), so the same three-zone card renders any
  ranked record. Ships a matching `RankedListCardSkeleton`.
