KQ-1819 · SWATCH/LADDER
Swatch Ladder
A row of paint-chip strips, each a ladder of chips computed in OKLCH from the palest tint at the top to a shade as deep as you set at the foot, rising and falling in a slow wave that travels across the row. Pointing at a strip, or arrowing to it, lifts it clear on springs.snap with one crisp overshoot while its neighbours part on springs.glide, and the readout gives its name, code and the chip under the pointer in OKLCH with its light reflectance value; a click copies that chip as oklch() and a check pops onto it on springs.flick. It is a horizontal listbox: Left and Right move between paints, Up and Down step lighter and darker, Enter copies, Escape lowers the strip.
Fernworks Paint Co. · autumn card
Twelve quiet colours for north light
browsing · 8 colours
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/swatch-ladder
Props
- swatches
- { name, hue, chroma, code? }[]
- default twelve invented paints
- The paints, one strip each; chips are computed in OKLCH from hue and chroma.
- strips
- number
- default 8
- How many strips stand in the row, 3 to 12 (never more than swatches).
- steps
- number
- default 7
- Chips on each strip, palest to deepest, 4 to 9.
- wave
- number
- default 0.5
- How far the strips rise and fall in the travelling wave, 0 (still) to 1.
- period
- number
- default 6
- Seconds for one swell to pass, 2 to 14.
- shade
- number
- default 0.6
- How deep the darkest chip goes: 0 keeps to pale tints, 1 runs almost to black.
- lift
- number
- default 16
- How far a strip lifts clear when it is read, px, 6 to 28.
- height
- number
- default 144
- Height of a strip, px.
- value / defaultValue
- number | null
- default null
- The strip being read, controlled or initial.
- onValueChange
- (index: number | null) => void
- default —
- Fires from the hover, touch or key that lifted or lowered a strip.
- onCopy
- (color: string, info: { name, code?, step }) => void
- default —
- Fires when a chip is copied, with its colour as oklch(L C H).
- paper
- string
- default a warm paper pigment
- The strips' card stock.
- showReadout
- boolean
- default true
- Show the line under the row that reads the lifted strip.
- label
- string
- default "Paint swatches"
- The row's accessible name, also shown in the readout at rest.
- paused
- boolean
- default false
- Hold the wave still.
- disabled
- boolean
- default false
- No lifting or copying.
- className
- string
- default —
- Classes for the root.
| Prop | Type | Default | Description |
|---|---|---|---|
| swatches | { name, hue, chroma, code? }[] | twelve invented paints | The paints, one strip each; chips are computed in OKLCH from hue and chroma. |
| strips | number | 8 | How many strips stand in the row, 3 to 12 (never more than swatches). |
| steps | number | 7 | Chips on each strip, palest to deepest, 4 to 9. |
| wave | number | 0.5 | How far the strips rise and fall in the travelling wave, 0 (still) to 1. |
| period | number | 6 | Seconds for one swell to pass, 2 to 14. |
| shade | number | 0.6 | How deep the darkest chip goes: 0 keeps to pale tints, 1 runs almost to black. |
| lift | number | 16 | How far a strip lifts clear when it is read, px, 6 to 28. |
| height | number | 144 | Height of a strip, px. |
| value / defaultValue | number | null | null | The strip being read, controlled or initial. |
| onValueChange | (index: number | null) => void | — | Fires from the hover, touch or key that lifted or lowered a strip. |
| onCopy | (color: string, info: { name, code?, step }) => void | — | Fires when a chip is copied, with its colour as oklch(L C H). |
| paper | string | a warm paper pigment | The strips' card stock. |
| showReadout | boolean | true | Show the line under the row that reads the lifted strip. |
| label | string | "Paint swatches" | The row's accessible name, also shown in the readout at rest. |
| paused | boolean | false | Hold the wave still. |
| disabled | boolean | false | No lifting or copying. |
| className | string | — | Classes for the root. |