Signal Feed Card

v0.1.0

Item-driven feed row for prioritised work queues: severity and status chips, a stage progress chain, act-by countdown, assignee, and priority score. Takes one flat item and owns every presentation decision, so screens map their domain record and nothing else.

View as Markdown

Install

npx shadcn@latest add @signalos/signal-feed-card

Requires a configured @signalos registry and a valid SIGNALOS_REGISTRY_TOKEN - get access. Registry dependencies (@signalos/tokens, @signalos/utils, @signalos/ranked-list-card, @signalos/status-badge) are pulled automatically.

Preview

Example & code

signal-feed-card.example.tsx
// Example: a work-queue row mapped from an arbitrary domain record.
// The screen formats every value; the card owns the layout.
import { Route, Zap } from "lucide-react"

import { SignalFeedCard } from "@/components/widgets/signal-feed-card/SignalFeedCard"
import type { SignalFeedItem } from "@/components/widgets/signal-feed-card/SignalFeedCard.types"

interface QueueRecord {
  id: string
  headline: string
  priority: number
  confidence: number
  severity: "critical" | "high" | "medium" | "low"
  owner: string | null
  team: string
  dueInHours: number
}

function toItem(record: QueueRecord): SignalFeedItem {
  return {
    id: record.id,
    rank: record.priority,
    confidence: record.confidence,
    title: record.headline,
    severity: record.severity,
    status: "IN PROGRESS",
    assignee: { name: record.owner ?? undefined, role: record.team },
    deadline: {
      label:
        record.dueInHours < 0
          ? `Past due by ${Math.abs(record.dueInHours)}h`
          : `${record.dueInHours}h`,
      tone:
        record.dueInHours < 0
          ? "past-due"
          : record.dueInHours < 4
            ? "urgent"
            : "normal",
    },
    stages: [
      {
        id: "detected",
        label: "Detected",
        icon: <Zap className="h-2.5 w-2.5" />,
      },
      {
        id: "routed",
        label: "Routed",
        value: "+2m",
        icon: <Route className="h-2.5 w-2.5" />,
        emphasized: true,
      },
    ],
  }
}

const records: QueueRecord[] = [
  {
    id: "rec-1",
    headline: "Coverage collapse across multiple tenants",
    priority: 1,
    confidence: 62,
    severity: "high",
    owner: "Priya N.",
    team: "Integration",
    dueInHours: 3,
  },
]

export default function Example() {
  return (
    <div className="flex flex-col gap-3">
      {records.map((record) => (
        <SignalFeedCard
          key={record.id}
          item={toItem(record)}
          onOpen={(item) => console.info("open", item.id)}
        />
      ))}
    </div>
  )
}

Props

SignalFeedStage

PropTypeDefaultDescription
id*string-Stable key for the stage.
label*ReactNode-Stage name, e.g. "Detected" or "Assigned".
valueReactNode-Pre-formatted elapsed/relative value shown next to the label, e.g. "+37s".
iconReactNode-Optional leading icon (a ~10px glyph reads best).
emphasizedboolean | undefined-Renders the stage with the primary accent — use for the current stage.

SignalFeedDeadline

PropTypeDefaultDescription
label*ReactNode-Pre-formatted countdown, e.g. "1d 21h 55m", "Past due by 2h", "No deadline".
toneSignalFeedDeadlineTone | undefined"normal"Urgency tone.

SignalFeedAssignee

PropTypeDefaultDescription
nameReactNode-Display name of the person.
roleReactNode-Secondary line — the role, team, or queue the item was routed to.

SignalFeedHighlight

PropTypeDefaultDescription
label*ReactNode-Pre-formatted value, e.g. "max 12.4σ" or "peak 3.1x".
toneSignalFeedHighlightTone | undefined"default"Emphasis tone.

SignalFeedItem

PropTypeDefaultDescription
id*string-Stable identifier; also used as the React key by list callers.
title*ReactNode-Primary headline (clamped to two lines).
rankReactNode-Left-column rank. A `number` renders as `#2`; any other node renders verbatim. Omit to hide the entire left column.
confidencenumber | undefined-Confidence/progress arc under the rank, 0–100.
confidenceColorClassstring | undefined"text-primary"Tailwind `text-*` class driving the arc color.
severitySeverity | null | undefined-Severity chip and accent border. `null` renders a neutral "UNSET" chip.
statusReactNode-Workflow status chip, e.g. "IN PROGRESS".
referenceReactNode-Short mono identifier shown beside the chips, e.g. "A1B2C3D4".
categoryReactNode-Grouping label in the meta row, e.g. a domain or product area.
metricReactNode-Primary measurement name in the meta row, rendered as `<code>`.
signalCountnumber | undefined-Number of underlying signals; pluralised with `labels.signalNoun`.
highlightSignalFeedHighlight | undefined-Emphasised measurement in the meta row.
escalatedboolean | undefinedfalseShows the corner ribbon (e.g. an escalation flag).
deadlineSignalFeedDeadline | undefined-Act-by countdown; its tone also drives the card's urgency border.
assigneeSignalFeedAssignee | undefined-Current owner shown in the trailing column and mobile footer.
scoreReactNode-Pre-formatted priority score shown in the trailing footer, e.g. "0.746".
stagesreadonly SignalFeedStage[] | undefined-Horizontal progress chain under the title.

SignalFeedCardLabels

PropTypeDefaultDescription
rankReactNode"Rank"Caption above the rank number.
deadlineReactNode"Act by"Caption above the countdown.
assigneeReactNode"Routed to"Caption above the assignee.
escalatedReactNode"Escalated"Corner ribbon text when `item.escalated` is set.
signalNounstring | undefined"signal"Singular noun for `item.signalCount`; an "s" is appended when != 1.
scorePrefixReactNode"score"Prefix before `item.score` in the trailing footer.

SignalFeedCardProps

PropTypeDefaultDescription
item*SignalFeedItem-The record to render.
selectedboolean | undefinedfalseSelected state (primary ring + border).
onOpen((item: SignalFeedItem) => void) | undefined-Invoked on click / Enter / Space. Omit to render a non-interactive card.
labelsSignalFeedCardLabels | undefined-Caption overrides.
classNamestring | undefined-
data-testidstring | undefined"signal-feed-card"Root test id; inner elements derive from it (`-deadline`, `-deadline-mobile`, `-assignee`, `-score`, `-escalated`, `-stage-<id>`).

SignalFeedCardSkeletonProps

PropTypeDefaultDescription
classNamestring | undefined-
data-testidstring | undefined"signal-feed-card-skeleton"

Supporting types

export type SignalFeedDeadlineTone = "normal" | "urgent" | "past-due"
export type SignalFeedHighlightTone = "default" | "warning" | "error"

npm dependencies

lucide-react@^1.7.0

Changelog

signal-feed-card

0.1.0

  • Initial release: item-driven feed card for prioritised queues, built on ranked-list-card. Renders severity/status chips, a reference, a meta row (category, metric, signal count, highlight), a stage progress chain, an act-by countdown with urgency tone, assignee, and a priority score, plus a mobile footer and a loading skeleton. Every value arrives pre-formatted so the widget never guesses a locale or unit.