Skip to main content

SecurityV0 · Component catalog

Every primitive in shared/components.jsx. What it's for, what props it takes, and when not to use it.

The rules exist because the design system is append-only (per §5 of the working agreement): new surfaces should compose these primitives rather than invent new ones. If a component is missing, add it here first and get sign-off.


Left rail with brand mark, environment label, primary nav, admin nav, and the reviewer's identity at the bottom.

PropTypeNotes
active"overview" | "clusters" | "chains" | "exposures" | "drift" | "inventory"Which nav item is highlighted.

Don't add more top-level nav items without a corresponding top-level surface. The nav mirrors the information architecture, not product taxonomy.

<Topbar crumbs />

Thin breadcrumb bar with the environment and last-sync label on the right.

PropTypeNotes
crumbsstring[]In order, root → leaf. The last crumb renders in on-surface color.

The topbar is 48px, no icons, no buttons. Actions live inside the page body.


Status signals

<SeverityChip severity />

Colored pill for severity. "critical" is red, "high" is amber, anything else is the warn slate.

<ActivityChip activity />

Runtime state, not severity:

  • "Active" → teal "Execution confirmed"
  • "Dormant" → slate "Dormant · standing authority"
  • anything else → slate "Standing authority"

Never conflate severity and activity — a dormant path can still be critical, and an active path can be low-severity.

<EvidenceChip state />

What kind of evidence backs the claim:

  • "proven" | "confirmed" → teal
  • "standing" → slate "Evidence · standing authority"
  • "dormant" → slate "Evidence · dormant"
  • anything else → dim

This is the companion to ActivityChip. Use on lists where the row's evidence strength matters more than its runtime state (e.g. exposures.html).

<SeverityDot severity />

Monochrome-safe severity signal: a small square + uppercase label. Used in list headers and cluster rows, where a full chip would be visually heavy.

<FounderCopyBadge /> · <DraftPendingBadge />

Disclose copy provenance. FounderCopyBadge is teal ("Founder copy"); DraftPendingBadge is slate ("Draft pending"). One of these must accompany any <Placeholder> block on a brief.


Content primitives

<Placeholder block>{copy}</Placeholder>

The marker for [founder draft pending] copy. Renders diagonal hatched background behind the text, italic, surface-toned — visible but not alarming. Pass block for a block-level placeholder, otherwise it's inline.

Use when: the layout needs prose that the founder hasn't written. The tool lays out; the writer fills. Don't use: to gloss over a decision that hasn't been made. If a decision is open, note it in QUESTIONS.md.

<Kicker tone />

Uppercase, letter-spaced eyebrow above a headline. Tones: "primary" (slate), "muted" (outline), default is tertiary (red — only for live posture).

<Dateline /> · <LabelMeta tone />

Tiny uppercase labels. Dateline is for time/location tags; LabelMeta is for field labels inside cards. Both share the same typography; the split is semantic.


Layout primitives

<MetricTile label value note tone />

A single metric tile. Value-first, label as caption, note below. tone can be "danger", "warn", or omitted.

Don't use when three or more tiles would create a "KPI strip" feel. Prefer a sentence that names the metric in context.

<ChainDiagram chain compact />

Horizontal access-chain diagram. Nodes render on a dot-grid surface with an arrow between each pair.

PropTypeNotes
chain{ kind, label, sub, danger? }[]Nodes render left-to-right in order. kind is one of workload, identity, connection, resource.
compactbooleanTighter padding for side-rail use.

Always horizontal, per DESIGN.md. Never draw a diagonal, never infer an edge the graph didn't provide.


Action

<ActionTracker story tracked owner target lastUpdate />

Right-rail card for the "safest first action" on a brief or chain page. Two states:

  • tracked={true} → teal chip "Tracked", owner/target/last-update trio.
  • tracked={false} → slate "Untracked" chip + primary "Track action" button.
PropTypeNotes
storystory objectProvides the action text.
trackedbooleanToggles the two states.
owner / target / lastUpdatestringOnly shown in tracked state.

The tracker is the only component that claims action status. List rows link to it; they never show their own "Tracked" badge that the tracker hasn't blessed.


State primitives

<Skeleton w h r style />

Flat rectangle for loading shape. No shimmer (per §4.4). w/h are CSS values; r is a border radius in px (defaults to 2).

<EmptyState title sentence lastScan /> · <ErrorState title sentence lastScan />

The two negative-space templates. Both are deterministic:

  • EmptyState says why there's no data and cites the last successful scan time.
  • ErrorState says data is withheld, not partially shown, and offers retry + diagnostics.

Copy is per-surface; see StateOverride below for the lookup table.

<StateOverride surface lastScan />

Top-level switch based on the ?state= query param. Returns <EmptyState>, <ErrorState>, a shape-skeleton, or null. Every page wraps its main content like:

{qs("state") ? <StateOverride surface="overview" lastScan="4m ago" /> : <MainContent />}

surface is one of "overview" | "brief" | "chain" | "clusters" | "exposures" | "drift" and picks the right per-surface copy.


Tweaks

<Tweaks controls values onChange />

Floating ⚙ panel bottom-right. Each control is a segmented button group.

useTweaks(pageKey, defaults)

Hook that persists tweak state to localStorage under sv0-tweaks-<pageKey>. Returns [values, setKey].

Keep the surface small. A Tweaks panel with more than four controls means the design has unresolved choices; resolve them in the main UI, not in a control panel.


Utilities

qs(name)

Read a URL query param. Returns null if missing. Used for ?state=, ?variant=, ?print=1, and ?story=.


What's intentionally missing

These do not exist, and adding them needs a written justification:

  • Charts / gauges / dials. Posture is a sentence. See UX-GUIDE §5.1.
  • Toast notifications. Every action routes through the tracker or the ticket path, not a transient banner.
  • Confirmation modals. The only destructive action in the pilot is "Revoke access," and it has a dedicated route — not a modal.
  • Icon-only buttons. Every button has a verb.
  • Borderful cards. Separation is tonal (per DESIGN.md's no-line rule). outline-variant only renders at low opacity for hair-rules inside dense tables.

If you think you need one of these, write the reason in QUESTIONS.md before adding it.