KQ-1257 · REPEAT/COIL
Repeat Coil
A three-way repeat button whose glyph is two strands rebuilt every frame: off they hang as loose arrows, the first press bends them into one closed loop on the glide spring, and the second winds a third turn inside it on glide while a "1" pip pops out of the loop onto its corner on the recoil spring. The third press drops the pip back on an exit tween and lets the loop fall slack again. It reports aria-pressed false, true and mixed; Space and Enter cycle it, the arrow keys step either way, and Home and End jump to the ends.
KQ-1257 · REPEAT/COIL
Low Tide
Coldbrook Quartet
1:423:58
repeat off · queue ends after track 12
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/repeat-coil
Props
- value / defaultValue
- "off" | "all" | "one"
- default "off"
- The repeat mode, controlled or initial.
- onValueChange
- (mode: RepeatMode) => void
- default —
- Fires from the press or key that changed the mode.
- labels
- Partial<Record<RepeatMode, string>>
- default Repeat off / Repeat all / Repeat one
- Text for each mode; the button keeps the width of the longest.
- allowOne
- boolean
- default true
- Offer repeat-one; off, the button cycles off and all only.
- compact
- boolean
- default false
- Icon only, with the mode's label as the accessible name.
- coil
- number
- default 0.6
- How far and how deep the third turn winds in repeat-one, 0 to 1.
- pip
- boolean
- default true
- Pop a "1" badge out of the loop in repeat-one.
- slack
- number
- default 0.5
- How much the loose arrows sag while repeat is off, 0 to 1.
- pipDelay
- number
- default 90
- Milliseconds from the coil starting to the pip popping out.
- size
- "sm" | "md" | "lg"
- default "md"
- Button height 32, 40 or 48 px with the glyph scaled to match.
- accent
- string
- default "var(--accent-bright)"
- The loop, the pip and the pressed tint; any CSS colour.
- idleColor
- string
- default "var(--ink-3)"
- The loose arrows' colour while repeat is off.
- sound
- boolean
- default false
- A click on every press and a pop as the pip lands.
- disabled
- boolean
- default false
- Ignores presses and keys and dims the button.
- className
- string
- default —
- Classes for the wrapper.
| Prop | Type | Default | Description |
|---|---|---|---|
| value / defaultValue | "off" | "all" | "one" | "off" | The repeat mode, controlled or initial. |
| onValueChange | (mode: RepeatMode) => void | — | Fires from the press or key that changed the mode. |
| labels | Partial<Record<RepeatMode, string>> | Repeat off / Repeat all / Repeat one | Text for each mode; the button keeps the width of the longest. |
| allowOne | boolean | true | Offer repeat-one; off, the button cycles off and all only. |
| compact | boolean | false | Icon only, with the mode's label as the accessible name. |
| coil | number | 0.6 | How far and how deep the third turn winds in repeat-one, 0 to 1. |
| pip | boolean | true | Pop a "1" badge out of the loop in repeat-one. |
| slack | number | 0.5 | How much the loose arrows sag while repeat is off, 0 to 1. |
| pipDelay | number | 90 | Milliseconds from the coil starting to the pip popping out. |
| size | "sm" | "md" | "lg" | "md" | Button height 32, 40 or 48 px with the glyph scaled to match. |
| accent | string | "var(--accent-bright)" | The loop, the pip and the pressed tint; any CSS colour. |
| idleColor | string | "var(--ink-3)" | The loose arrows' colour while repeat is off. |
| sound | boolean | false | A click on every press and a pop as the pip lands. |
| disabled | boolean | false | Ignores presses and keys and dims the button. |
| className | string | — | Classes for the wrapper. |