KQ-1780 · CLIP/THREAD
Clip Thread
An asynchronous video thread whose clips are procedural screen shares drawn in SVG from one time motion value, so hovering a strip thumbnail scrubs its frames under the pointer at frame rate and the cursor in each frame glides between what the speaker points at. While a clip plays its track fills linearly and the transcript lights up word by word: a capsule glides from word to word on springs.flick and across line breaks on springs.snap, and any word can be clicked to jump there; reactions land on springs.recoil as markers on the track, choosing a clip slides the frame in on springs.glide, and a finished clip's progress ring closes into a tick. Space plays, the arrows skip five seconds, the strip is a listbox walked with Left and Right, and the transcript's lines are walked with Up and Down.
Onboarding flow review
Fernworks · 5 clips · 1 processing
paused · Ana Reyes · 5 clips · 1 processing
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/clip-thread
Props
- clips
- ClipThreadClip[]
- default defaultClips
- The thread, oldest first: { id, author, role?, at, duration, title?, scene?, transcript: { at, text }[], reactions?: { kind, count, mine?, marks? }[], replyTo?, processing? }.
- selected / defaultSelected
- string
- default — / the first ready clip
- The clip in the player, controlled or initial.
- onSelectedChange
- (clipId) => void
- default —
- Fires from the strip choice, or the auto-advance, that changed the clip.
- playing / defaultPlaying / onPlayingChange
- boolean
- default — / false
- Playback, controlled or initial, and the callback from the press, key or end of clip that changed it.
- onRecord
- () => void
- default —
- Record was pressed. Add the new clip with `processing` to clips; it shows a progress ring until you clear it.
- onReply
- (clipId) => void
- default —
- "Reply with a clip" was pressed on the clip in the player.
- onReact
- (clipId, kind, at, on) => void
- default —
- A reaction ("agree" | "love" | "idea" | "question") was toggled at a moment of the clip, in seconds.
- now
- number
- default defaultClipNow
- The moment relative times count from, in ms since the epoch. Never read from the clock during render.
- title
- string
- default "Onboarding flow review"
- The thread's heading.
- skip
- number
- default 5
- Seconds the arrow keys skip on the frame and the track.
- autoAdvance
- boolean
- default true
- Play the next ready clip when one ends.
- posterAt
- number
- default 0.3
- Where in a clip its strip poster frame sits, 0 to 1; a skim eases back to it.
- thumbShape
- "wide" | "square" | "round"
- default "wide"
- Strip thumbnails as 16:9 cards, squares, or circular video notes.
- density
- "compact" | "regular" | "roomy"
- default "regular"
- Strip thumbnail size, transcript type size and line height, and gaps.
- accent
- string
- default "var(--accent-bright)"
- Word capsule, playhead, fill, reaction markers, rings and the chosen card — any CSS colour; fills take its hue at a fixed lightness.
- status / onRetry
- "ready" | "loading" | "error" / () => void
- default "ready"
- Loading shows a skeleton player and strip; error shows a message and Try again, which calls onRetry.
- height
- number
- default 540
- The surface's height in px; the transcript, and below 44rem the player column, scroll inside it.
- disabled
- boolean
- default false
- Watch only: no recording, replying or reacting.
- className
- string
- default —
- Classes for the outer section.
| Prop | Type | Default | Description |
|---|---|---|---|
| clips | ClipThreadClip[] | defaultClips | The thread, oldest first: { id, author, role?, at, duration, title?, scene?, transcript: { at, text }[], reactions?: { kind, count, mine?, marks? }[], replyTo?, processing? }. |
| selected / defaultSelected | string | — / the first ready clip | The clip in the player, controlled or initial. |
| onSelectedChange | (clipId) => void | — | Fires from the strip choice, or the auto-advance, that changed the clip. |
| playing / defaultPlaying / onPlayingChange | boolean | — / false | Playback, controlled or initial, and the callback from the press, key or end of clip that changed it. |
| onRecord | () => void | — | Record was pressed. Add the new clip with `processing` to clips; it shows a progress ring until you clear it. |
| onReply | (clipId) => void | — | "Reply with a clip" was pressed on the clip in the player. |
| onReact | (clipId, kind, at, on) => void | — | A reaction ("agree" | "love" | "idea" | "question") was toggled at a moment of the clip, in seconds. |
| now | number | defaultClipNow | The moment relative times count from, in ms since the epoch. Never read from the clock during render. |
| title | string | "Onboarding flow review" | The thread's heading. |
| skip | number | 5 | Seconds the arrow keys skip on the frame and the track. |
| autoAdvance | boolean | true | Play the next ready clip when one ends. |
| posterAt | number | 0.3 | Where in a clip its strip poster frame sits, 0 to 1; a skim eases back to it. |
| thumbShape | "wide" | "square" | "round" | "wide" | Strip thumbnails as 16:9 cards, squares, or circular video notes. |
| density | "compact" | "regular" | "roomy" | "regular" | Strip thumbnail size, transcript type size and line height, and gaps. |
| accent | string | "var(--accent-bright)" | Word capsule, playhead, fill, reaction markers, rings and the chosen card — any CSS colour; fills take its hue at a fixed lightness. |
| status / onRetry | "ready" | "loading" | "error" / () => void | "ready" | Loading shows a skeleton player and strip; error shows a message and Try again, which calls onRetry. |
| height | number | 540 | The surface's height in px; the transcript, and below 44rem the player column, scroll inside it. |
| disabled | boolean | false | Watch only: no recording, replying or reacting. |
| className | string | — | Classes for the outer section. |