KQ-1711 · SPARE/KEYS
Spare Keys
A backup codes sheet that has to be kept before you go on. The codes are dealt onto the sheet when it comes into view — each ticket leaves a tilted deck above the grid and flies to its cell on springs.glide while its tilt settles on springs.snap, staggered by cascade — and Copy all flashes every ticket in turn as its code lands on the clipboard. Continue carries a padlock that stays shut until the box is ticked, then its shackle lifts and turns open about its right leg on springs.snap. Every action is a button: each ticket copies itself, Download saves a .txt, Print prints the codes alone, and Regenerate warns in place, strikes the old set and deals the new one.
Backup codes
mara@fieldline.io · made today 09:12
Each code works once. Keep them somewhere other than this device.
10 codes · not saved yet
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/spare-keys
Props
- codes
- string[]
- default defaultSpareKeysCodes
- The backup codes, in order.
- used
- string[]
- default []
- Codes already spent: struck through, named "used" and left out of Copy all.
- account
- string
- default "mara@fieldline.io"
- Whose codes these are, shown in the header, the file and the print.
- issuer
- string
- default "Fieldline"
- The service they unlock, used in the file and the print.
- generatedAt
- number
- default defaultSpareKeysGeneratedAt
- When the set was made, epoch ms.
- now
- number
- default defaultSpareKeysNow
- The clock "made today 09:12" is read against, epoch ms (UTC).
- confirmed / defaultConfirmed
- boolean
- default — / false
- The "I've saved these codes" box, controlled or initial.
- onConfirmedChange
- (confirmed) => void
- default —
- Fires from the tick, or from Regenerate clearing it because the saved set is gone.
- onCopy
- (codes) => void
- default —
- Codes were written to the clipboard: every unused one, or the ticket pressed.
- onDownload
- (codes) => void
- default —
- Download was pressed; the sheet saves the .txt itself, then this fires.
- onPrint
- (codes) => void
- default prints a hidden frame
- Print was pressed. Omit it and the sheet prints the codes alone through a hidden frame.
- onRegenerate
- () => void | Promise<void>
- default —
- New codes were confirmed after the warning. Return a promise while they are made and pass the new set back through codes; a rejection restores the old set.
- onConfirm
- () => void
- default —
- Continue was pressed with the box ticked.
- fileName
- string
- default "fieldline-backup-codes.txt"
- The downloaded file's name.
- status
- "ready" | "loading" | "error"
- default "ready"
- Ten skeleton tickets while the codes are made; a message and Try again on error.
- onRetry
- () => void
- default —
- Try again was pressed after making codes failed.
- cellStyle
- "ticket" | "plain" | "slip"
- default "ticket"
- A notched ticket with a perforation, a plain cell, or a slip with a tear-off stub.
- columns
- number
- default 2
- Columns where the sheet is wide enough, 2 to 5; always two under 19rem of container and three at most under 34rem.
- accent
- string
- default "var(--accent-bright)"
- The copy flash, the key glyph, the box and Continue's fill, any CSS colour; Continue's ink adapts to its lightness.
- deal
- "inView" | "mount" | "none"
- default "inView"
- When the codes are dealt onto the sheet; they are dealt again after a regenerate.
- disabled
- boolean
- default false
- Every action is unavailable.
- className
- string
- default —
- Classes for the wrapper.
| Prop | Type | Default | Description |
|---|---|---|---|
| codes | string[] | defaultSpareKeysCodes | The backup codes, in order. |
| used | string[] | [] | Codes already spent: struck through, named "used" and left out of Copy all. |
| account | string | "mara@fieldline.io" | Whose codes these are, shown in the header, the file and the print. |
| issuer | string | "Fieldline" | The service they unlock, used in the file and the print. |
| generatedAt | number | defaultSpareKeysGeneratedAt | When the set was made, epoch ms. |
| now | number | defaultSpareKeysNow | The clock "made today 09:12" is read against, epoch ms (UTC). |
| confirmed / defaultConfirmed | boolean | — / false | The "I've saved these codes" box, controlled or initial. |
| onConfirmedChange | (confirmed) => void | — | Fires from the tick, or from Regenerate clearing it because the saved set is gone. |
| onCopy | (codes) => void | — | Codes were written to the clipboard: every unused one, or the ticket pressed. |
| onDownload | (codes) => void | — | Download was pressed; the sheet saves the .txt itself, then this fires. |
| onPrint | (codes) => void | prints a hidden frame | Print was pressed. Omit it and the sheet prints the codes alone through a hidden frame. |
| onRegenerate | () => void | Promise<void> | — | New codes were confirmed after the warning. Return a promise while they are made and pass the new set back through codes; a rejection restores the old set. |
| onConfirm | () => void | — | Continue was pressed with the box ticked. |
| fileName | string | "fieldline-backup-codes.txt" | The downloaded file's name. |
| status | "ready" | "loading" | "error" | "ready" | Ten skeleton tickets while the codes are made; a message and Try again on error. |
| onRetry | () => void | — | Try again was pressed after making codes failed. |
| cellStyle | "ticket" | "plain" | "slip" | "ticket" | A notched ticket with a perforation, a plain cell, or a slip with a tear-off stub. |
| columns | number | 2 | Columns where the sheet is wide enough, 2 to 5; always two under 19rem of container and three at most under 34rem. |
| accent | string | "var(--accent-bright)" | The copy flash, the key glyph, the box and Continue's fill, any CSS colour; Continue's ink adapts to its lightness. |
| deal | "inView" | "mount" | "none" | "inView" | When the codes are dealt onto the sheet; they are dealt again after a regenerate. |
| disabled | boolean | false | Every action is unavailable. |
| className | string | — | Classes for the wrapper. |