Stamp Chip
A compact inline pill that pairs a short label with a timestamp under a single tone. Use it for event ledgers, audit trails, activity feeds, or anywhere you need to mark when something happened.
defaultDeployedwarningerrorinfoaccent
Customize
Tone
success
Size
md
Installation
npx shadcn@latest add https://craftbits.dev/r/stamp-chip.jsonUsage
import { StampChip } from "@craft-bits/core";
<StampChip
label="Deployed"
timestamp={1717200000000}
tone="success"
/>Drop the timestamp to render just a label pill:
<StampChip label="Featured" tone="accent" />Pass a custom formatter for relative time or any locale-stable string:
import { formatDistanceToNow } from "date-fns";
<StampChip
label="Saved"
timestamp={savedAt}
formatTimestamp={(d) => formatDistanceToNow(d, { addSuffix: true })}
/>Understanding the component
- Tone-driven palette. Six semantic combos (
default,success,warning,error,info,accent) tint the border toward the tone while the background stays on a muted surface — a row of mixed-tone chips reads as one ledger, not as a rainbow. - Timestamp normalisation.
timestampaccepts epoch milliseconds, an ISO-8601 string, or aDate. Invalid input (NaN) falls back to label-only rather than renderingInvalid Date. - Hydration-safe default formatter. The default uses
toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit" })— pinned locale, deterministic between server and client. ProvideformatTimestampfor relative time, ISO output, or a custom date library; just keep the function pure. - Semantic
<time dateTime>. When a timestamp renders, it lives inside a<time>element with the full ISO string asdateTime— parseable by screen readers, translation tools, and microdata crawlers. - Mono + tabular nums. The timestamp slot uses
font-cb-mono+tabular-numsso digit widths stay constant — a feed of stamps stays vertically aligned as minutes tick. - Stateless presentational
<span>. Unlike the source (a toggle button with sounds + sweep animation), the library version has no state, no motion, and noDate.now()call. Toggle behaviour belongs toTogglePill; this is the stamp, not the switch.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
label | ReactNode | required | Short event name. |
timestamp | number | string | Date | — | Moment the event occurred. Skipped if undefined or invalid. |
tone | 'default' | 'success' | 'warning' | 'error' | 'info' | 'accent' | 'default' | Semantic color tone. |
size | 'sm' | 'md' | 'md' | Height + padding preset. |
icon | ReactNode | — | Optional leading icon. |
formatTimestamp | (date: Date) => string | locale-stable hh:mm | Custom timestamp formatter. |
className | string | — | Merged onto the rendered <span>. |
Accessibility
- Renders as a single
<span>with the label and a<time dateTime>element. Screen readers announce both; the<time>exposes the precise ISO moment for assistive tech that surfaces it. - Icon and separator are
aria-hidden="true"so AT reads only the meaningful content. - All tone combinations meet WCAG AA against the muted surface in both light and dark themes.
- No motion is attached, so there is nothing to gate behind
prefers-reduced-motion.
Credits
- Extracted from:
AlgoFlashcards(src/platform/ui/StampChip.tsx). The source was a toggle button with sound + sweep animation; the library version reframes the primitive as a stateless timestamp chip and ships toggle behaviour throughTogglePillinstead.