KQ-1126 · GESTURE/PLAYER
Gesture Player
A player whose picture is the control: a sideways swipe seeks 1:1 with a time bubble riding the bar that shows where you are and how far you have jumped, and its release is projected and glides on the glide spring with the release velocity. Swipes up and down set volume on the right half and brightness on the left, a side meter filling and stretching a little past either end before it snaps back, and a double tap on a side skips with a ripple that adds up as you keep tapping. The host draws the picture from a motion value of the time, so a scrub moves the scene at frame rate without a render, and the focusable picture takes Space, the arrows and Shift with them along the same paths, with a tick per second scrubbed and a click per skip.
Swipe sideways to seek; swipe up or down on the right for volume and on the left for brightness. Tap to play or pause, double-tap a side to skip 10 seconds. Keys: Space plays and pauses, Left and Right skip 10 seconds, Shift with Left or Right seeks one second, Home and End jump to the start and end, Up and Down set the volume, and Shift with Up or Down sets the brightness.
paused · 0:42 / 3:40 · vol 70% · bright 60%
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/gesture-player
Props
- children
- (time: MotionValue<number>) => ReactNode
- default —
- The picture, drawn from the playback time in seconds. Bind it with useTransform so a scrub moves the scene every frame without a render.
- label
- string
- default —
- The clip's title: the player's accessible name.
- duration
- number
- default —
- Length of the clip, in seconds.
- value / defaultValue
- number
- default 0
- Position in seconds. A new value from the host seeks there; the player reports every seek and skip, and each whole second as it plays.
- onValueChange
- (seconds: number) => void
- default —
- Fires with the landing of every seek and skip, and with each whole second passed while playing.
- playing / defaultPlaying
- boolean
- default false
- Whether it plays. Playback runs only while the page is visible and nothing is being scrubbed, and stops at the end.
- onPlayingChange
- (playing: boolean) => void
- default —
- Fires from the tap, key or button that played or paused, and with false at the end.
- volume / defaultVolume
- number
- default 0.7
- Volume, 0 to 1. Reported as a swipe moves it; after the release the meter settles on the host's value, so a refused change springs back.
- onVolumeChange
- (volume: number) => void
- default —
- Fires as a vertical swipe or an arrow key changes the volume.
- brightness / defaultBrightness
- number
- default 0.6
- Brightness, 0 to 1, applied as a CSS brightness from 0.4 to 1.4: 0.6 shows the picture as drawn.
- onBrightnessChange
- (brightness: number) => void
- default —
- Fires as a vertical swipe on the left half or Shift with an arrow key changes the brightness.
- sensitivity
- number
- default 1
- How far a swipe goes, 0.5 to 2: a swipe across the picture seeks sensitivity × 90 seconds, and one of 80% of its height sweeps a level from end to end at 1.
- zones
- boolean
- default true
- A brightness half on the left and a volume half on the right, the active half washed while it is set. Off, a vertical swipe anywhere sets the volume.
- skip
- number
- default 10
- Seconds a double tap or an arrow key skips, 5 to 15. Further taps on the same side while the ripple is up add another skip each.
- hints
- boolean
- default true
- Faint glyphs over the paused, idle picture showing what it answers to: the skips on the sides and the levels at the top.
- sound
- boolean
- default false
- A tick for every whole second a seek crosses (a ratchet at most every 35 ms, pitched and panned by position), a tick per tenth of a level, and a click per skip. Playback is silent. Nothing plays, and no audio context exists, unless this is on.
- disabled
- boolean
- default false
- Dims the player, holds playback, and ignores taps, swipes and keys.
- className
- string
- default —
- Merged onto the player's classes; it is w-full at 16:9 unless an aspect class here says otherwise.
| Prop | Type | Default | Description |
|---|---|---|---|
| children | (time: MotionValue<number>) => ReactNode | — | The picture, drawn from the playback time in seconds. Bind it with useTransform so a scrub moves the scene every frame without a render. |
| label | string | — | The clip's title: the player's accessible name. |
| duration | number | — | Length of the clip, in seconds. |
| value / defaultValue | number | 0 | Position in seconds. A new value from the host seeks there; the player reports every seek and skip, and each whole second as it plays. |
| onValueChange | (seconds: number) => void | — | Fires with the landing of every seek and skip, and with each whole second passed while playing. |
| playing / defaultPlaying | boolean | false | Whether it plays. Playback runs only while the page is visible and nothing is being scrubbed, and stops at the end. |
| onPlayingChange | (playing: boolean) => void | — | Fires from the tap, key or button that played or paused, and with false at the end. |
| volume / defaultVolume | number | 0.7 | Volume, 0 to 1. Reported as a swipe moves it; after the release the meter settles on the host's value, so a refused change springs back. |
| onVolumeChange | (volume: number) => void | — | Fires as a vertical swipe or an arrow key changes the volume. |
| brightness / defaultBrightness | number | 0.6 | Brightness, 0 to 1, applied as a CSS brightness from 0.4 to 1.4: 0.6 shows the picture as drawn. |
| onBrightnessChange | (brightness: number) => void | — | Fires as a vertical swipe on the left half or Shift with an arrow key changes the brightness. |
| sensitivity | number | 1 | How far a swipe goes, 0.5 to 2: a swipe across the picture seeks sensitivity × 90 seconds, and one of 80% of its height sweeps a level from end to end at 1. |
| zones | boolean | true | A brightness half on the left and a volume half on the right, the active half washed while it is set. Off, a vertical swipe anywhere sets the volume. |
| skip | number | 10 | Seconds a double tap or an arrow key skips, 5 to 15. Further taps on the same side while the ripple is up add another skip each. |
| hints | boolean | true | Faint glyphs over the paused, idle picture showing what it answers to: the skips on the sides and the levels at the top. |
| sound | boolean | false | A tick for every whole second a seek crosses (a ratchet at most every 35 ms, pitched and panned by position), a tick per tenth of a level, and a click per skip. Playback is silent. Nothing plays, and no audio context exists, unless this is on. |
| disabled | boolean | false | Dims the player, holds playback, and ignores taps, swipes and keys. |
| className | string | — | Merged onto the player's classes; it is w-full at 16:9 unless an aspect class here says otherwise. |