Data & tables
Recovery Ledger
Version history timeline & state recovery ledger
detent-recovery-ledger
Port status
- Catalog status
- implemented
- Origin
- upstream
- Phase
- 3
- Wave
- phase-3-data
- Group
- Data & tables
7.9 KB gzip for the class module · inlines the shared spring
Variants
The ledger in the main preview uses the default timeline variant: a rail, timeline pips and a tinted
Current Head card. The one above uses variant="compact", which hides the rail and the
pips. Use the disclosure button on any snapshot to open its diff and metadata drawer; the revert button emits
detent-restore and enters the documented loading state until endRestore() is
called. Sample snapshots are local data: nothing is fetched, and the simulated revert only re-marks the current entry.
No snapshot has been expanded yet.
Recorded states
loadingrecorded state; no setteractiverecorded state; no setter
Usage
Import
import '/components/recovery-ledger/define.js';
// or register it yourself
import { DetentRecoveryLedger } from '/components/recovery-ledger/recovery-ledger.js';
Attributes
current-entry-idvariant
Properties
entriesonRestoreonSelect
Slots
No slots are recorded for this component.
Events
detent-restore— {}detent-select— {}
Example
Runnable example: site/examples/recovery-ledger.ts. The snippet below is generated from the catalogued attributes.
<detent-recovery-ledger
current-entry-id
variant="timeline"
></detent-recovery-ledger>
Property-only values
const element = document.querySelector('detent-recovery-ledger');
if (element !== null) {
// entries: LedgerEntry[]
element.entries = [];
// onRestore: (id: string) => Promise<void> | void
element.onRestore = () => {};
// onSelect: (id: string) => void
element.onSelect = () => {};
}
Source
The pinned upstream source for this row:
src/components/ui/RecoveryLedger.tsxsha256 866a7fb1af2c…
Native files
The native module and its artifacts:
src/components/recovery-ledger/recovery-ledger.tssrc/components/recovery-ledger/styles.csssrc/components/recovery-ledger/define.tsdocs/components/recovery-ledger.mdsite/examples/recovery-ledger.tstests/browser/recovery-ledger.spec.tsevidence/components/recovery-ledger.md
API
Boolean attributes follow HTML presence semantics: present means true, absent means false, and disabled="false" still means disabled.
Attributes
| Attribute | Property | Type | Default | Notes |
|---|---|---|---|---|
current-entry-id | currentEntryId | string | undefined | Kebab-case attribute; camelCase property. |
variant | variant | 'timeline' | 'compact' | 'timeline' | Kebab-case attribute; camelCase property. |
Properties
| Property | Type | Default | Notes |
|---|---|---|---|
entries | LedgerEntry[] | — | Property-only: assign from script; not accepted as an attribute. |
onRestore | (id: string) => Promise<void> | void | undefined | Property-only: assign from script; not accepted as an attribute. |
onSelect | (id: string) => void | undefined | Property-only: assign from script; not accepted as an attribute. |
Events
| Event | Upstream prop | Payload type | Notes |
|---|---|---|---|
detent-restore | onRestore | (id: string) => Promise<void> | void | Composed, bubbles; fires only for a user action. |
detent-select | onSelect | (id: string) => void | Composed, bubbles; fires only for a user action. |
Slots
No slots are recorded for this component.
CSS customisation
- React callback props become typed composed CustomEvents; programmatic state assignment emits none.
- Framer Motion springs/AnimatePresence ported to CSS transitions, WAAPI or the shared rAF spring helper.
- `lucide-react` icon components replaced with local SVG assets (ISC notice retained).
- React state/hooks replaced by element-owned state with pre-upgrade property preservation.
- React children/ReactNode props become DOM slots; this row has none, so no content slot exists. className is replaced by the documented parts and custom properties (no Tailwind in consumers).
- entries defaults to []; upstream declares it required with no default.
- onSelect / onRestore become the composed events detent-select { id } and detent-restore { id }; programmatic writes emit none (PC-6.5).
- onRestore's Promise return cannot be awaited across dispatchEvent, so the loading state ends through the documented endRestore() method, or implicitly when the consumer replaces entries/currentEntryId.
- Upstream shows the revert button only when an onRestore prop exists. A custom element cannot observe listeners reliably, so the button is rendered for every restorable, non-current entry and the consumer decides whether to act.
- The revert label is Revert to version <id> (contains the visible Revert); upstream used Restore version <id> with the visible word Revert, a WCAG 2.5.3 failure.
- The drawer's springSmooth (200/28/0.85) height/opacity presence runs on the shared spring helper: a closing drawer is inert at once and hidden when the spring settles. Newly mounted entries rise in idx x 50 ms apart on framer-motion 13's default transition (y spring 500/25/1 on the shared helper, which settles on its own threshold rather than Framer's restSpeed 10; opacity a 0.3 s cubic-bezier(0.25, 0.1, 0.35, 1) tween via WAAPI). The chevron turns 180 degrees on springSnappy through the shared spring helper. Motion fidelity remains a manual gate; reduced motion jumps the drawer and removes the remaining transitions.
- Upstream's dark-only palette (bg-[#0E0E0E]) is replaced by theme tokens so both colour schemes meet AA.
- lucide-react icons (RotateCcw, ChevronDown, User, Clock, Loader2) become local text glyphs marked aria-hidden.
What it does
A chronological version-history ledger: a vertical timeline rail, a current-head marker, an expandable diff/metadata drawer per snapshot and a one-click revert action that reports a loading state.
Upstream behaviour
- Chronological version ledger with vertical timeline rail and active head marker
- One-click state rollback action with loading animation feedback
- Expandable code diff viewer and snapshot metadata inspection drawer
- Full keyboard tab access and screen reader timestamp announcements
Differences from upstream
- React callback props become typed composed CustomEvents; programmatic state assignment emits none.
- Framer Motion springs/AnimatePresence ported to CSS transitions, WAAPI or the shared rAF spring helper.
- `lucide-react` icon components replaced with local SVG assets (ISC notice retained).
- React state/hooks replaced by element-owned state with pre-upgrade property preservation.
- React children/ReactNode props become DOM slots; this row has none, so no content slot exists. className is replaced by the documented parts and custom properties (no Tailwind in consumers).
- entries defaults to []; upstream declares it required with no default.
- onSelect / onRestore become the composed events detent-select { id } and detent-restore { id }; programmatic writes emit none (PC-6.5).
- onRestore's Promise return cannot be awaited across dispatchEvent, so the loading state ends through the documented endRestore() method, or implicitly when the consumer replaces entries/currentEntryId.
- Upstream shows the revert button only when an onRestore prop exists. A custom element cannot observe listeners reliably, so the button is rendered for every restorable, non-current entry and the consumer decides whether to act.
- The revert label is Revert to version <id> (contains the visible Revert); upstream used Restore version <id> with the visible word Revert, a WCAG 2.5.3 failure.
- The drawer's springSmooth (200/28/0.85) height/opacity presence runs on the shared spring helper: a closing drawer is inert at once and hidden when the spring settles. Newly mounted entries rise in idx x 50 ms apart on framer-motion 13's default transition (y spring 500/25/1 on the shared helper, which settles on its own threshold rather than Framer's restSpeed 10; opacity a 0.3 s cubic-bezier(0.25, 0.1, 0.35, 1) tween via WAAPI). The chevron turns 180 degrees on springSnappy through the shared spring helper. Motion fidelity remains a manual gate; reduced motion jumps the drawer and removes the remaining transitions.
- Upstream's dark-only palette (bg-[#0E0E0E]) is replaced by theme tokens so both colour schemes meet AA.
- lucide-react icons (RotateCcw, ChevronDown, User, Clock, Loader2) become local text glyphs marked aria-hidden.