Timeline
Hero example
⚠ component not resolved: TimelineWhen to use
Reach for the Timeline namespace when the surface is a feed of events — an entity's audit log, a Compliance view's "what changed in the last month," an Inbox of agent activity, a deal-room activity stream. Timeline is unique among Matter components: it's a namespace, not a single component. You compose feeds from the atoms (KindDot, KindChip, ActorChip, SourceChip), wire the filter controls (Search, FilterSelect, KindToggleRow) above the feed, and reach into the constants (KIND_CFG, ACTOR_TONES, SOURCE_LABEL) when you need to label something canonically.
Don't reach for Timeline when the feed is a plan still executing — that's PlanCard. Don't use it for filing checklists either — those are FilingStatusCard. Timeline is for what already happened; plan and filing surfaces are for what's happening now.
KindToggleRow to your kind-filter state and Search to your text-search state.KindDot to render a status dot elsewhere. Use StatusPill — the KindDot tones are scoped to the Timeline event vocabulary.Anatomy
Three composable layers — Timeline doesn't ship a "Timeline" container component. Authors compose the namespace into their own feed layout.
Layer 1: atoms
| Atom | Purpose | Visual |
|---|---|---|
KindDot | 8px filled dot keyed off the event kind. | Solid circle, color from KIND_CFG[kind].dotColor. |
KindChip | Mono uppercase pill carrying the kind label + dot. | Pill with leading dot + text. |
ActorChip | Avatar + name + tone-colored backdrop. | Chip with 16px avatar + name. |
SourceChip | Inline mono tag identifying the event source. | Mono chip (API / MCP / DASHBOARD / etc.). |
Layer 2: filter controls
| Control | Purpose |
|---|---|
Search | Text-search input above the feed. |
FilterSelect | Dropdown menu of FilterOption[] for actor / source / scope filters. |
KindToggleRow | Row of toggleable kind-chips for filtering by event kind. |
Layer 3: constants
| Constant | Type | Purpose |
|---|---|---|
KIND_CFG | Record<Kind, { label, dotColor }> | Canonical kind metadata. Reach for this when rendering kinds outside the Timeline atoms (legend tables, dashboard summaries). |
ACTOR_TONES | Record<ActorTone, string> | Canonical actor tone → color map. |
SOURCE_LABEL | Record<Source, string> | Human-readable source labels. |
Props
The Timeline namespace has no aggregate props — each atom has its own. See the individual atoms: KindDot, KindChip, ActorChip, SourceChip, Search, FilterSelect, KindToggleRow. Props.json introspection per atom lands in the same generator pass and surfaces under each atom's name (e.g., <PropsTable component="KindDot" /> when those atom-level pages are added in a future tranche).
States
Each atom and control has its own state contract. The two stateful primitives:
| Component | State surface |
|---|---|
Search | Empty / typing / has-value / focused / disabled. Mirrors a controlled <input>. |
FilterSelect | Closed / open / has-selection / disabled. Mirrors a controlled <select>. |
KindToggleRow | Per-kind: active / inactive. The row tracks an array of active kinds. |
Density
In compact, Search input height drops from 32px to 28px, FilterSelect trigger drops likewise. Chip and dot sizes stay constant — they're at the legibility floor.
Themes
Each atom inherits theme tokens. KindDot colors are tonally adjusted in dark; ActorChip tone families have matching dark-theme entries in ACTOR_TONES.
Tokens consumed
KindDot colors are declared in KIND_CFG and resolve to the --kind-* token family. ActorChip tones resolve from --actor-*. SourceChip mono tag uses --ink-6 for background and --fg-muted for the foreground.
Accessibility
- Keyboard interactions.
Searchis a native<input>— full keyboard support.FilterSelectopens onEnter/Space/ArrowDown, navigates options with arrows, closes onEscape.KindToggleRowchips are<button>elements —Enter/Spacetoggle them. - ARIA roles and properties. KindDot is
aria-hidden(decorative). Chips inherit text-content accessible names. Filter controls implement standard listbox semantics. - Focus order. Filter region first (Search → FilterSelect → KindToggleRow chips), then feed. Feed items themselves are non-focusable; click affordances live on row wrappers (consumer responsibility).
- Screen-reader expectations. Each event row reads as "kind, actor, action description, source, timestamp." Filter changes are announced via
aria-live="polite"on a status region (consumer wires the region). - Reduced motion. KindToggleRow active-state transition collapses to opacity. FilterSelect dropdown skips the expand animation.
- Forced colors. KindDot fills →
ButtonText. ActorChip backgrounds →Highlight. SourceChip →CanvaswithButtonBorder. - WIG rules. Mono caps on KindChip and SourceChip use
letter-spacing: 0.06em(WIG typography minimum for caps legibility). Filter controls are real<input>/<button>elements (semantic-element rule). Touch targets on filter chips ≥ 32px (compact density floor).
Do / Don't
KindToggleRow to URL state so filter selections deep-link and survive page reloads (WIG navigation-state rule).KIND_CFG and SOURCE_LABEL as the single source of truth for labels. Don't hardcode strings.constants.ts.Recipes
The Timeline namespace appears in:
- Docs corpus recipe — the activity-stream sidebar on document detail pages.
- Board recipe — the recent-resolutions feed.
Code example
import * as Timeline from "@matter/components/Timeline";
export function EntityAuditLog({ events }: { events: AuditEvent[] }) {
const [search, setSearch] = useState("");
const [activeKinds, setActiveKinds] = useState<Timeline.Kind[]>([]);
return (
<div>
<div className="timeline-filters">
<Timeline.Search onChange={setSearch} value={search} />
<Timeline.KindToggleRow active={activeKinds} onChange={setActiveKinds} />
</div>
<ul className="timeline-feed">
{events.map((event) => (
<li key={event.id}>
<Timeline.KindDot kind={event.kind} />
<Timeline.KindChip kind={event.kind} />
<Timeline.ActorChip actor={event.actor} tone={event.actorTone} />
<span>{event.summary}</span>
<Timeline.SourceChip source={event.source} />
<time>{event.occurred_at_relative}</time>
</li>
))}
</ul>
</div>
);
}Source
packages/components/src/TimelineSignatureStack
Package of documents awaiting signature — package name, status pill, per-document rows with thumb / meta / signer count / page count / size, overlapping recipient avatars, send-for-signature footer. Use when staging or tracking a multi-document signing flow.
Composer
Tahoe-glass message input with real backdrop refraction and chromatic-aberration rim. Textarea auto-grows to 200px, Enter submits, Shift+Enter newlines. Chip slot at bottom-left for attach / model / context pickers.