KQ-1695 · PRACTICE/RUN
Practice Run
A hands-on tutorial where each lesson is one small real task in a sandboxed copy of the interface: a working board whose cards drag 1:1 and glide into their lane on springs.glide, a comment box whose @ opens a real combobox of teammates, a job whose Labels menu opens on springs.snap. A coach line answers what the visitor actually does, one sentence at a time rising into place on springs.snap, and a finished task presses a quiet check stamp onto the sandbox on springs.recoil before the next lesson slides in on springs.glide. Every lesson has a keyboard path (Space picks a card up and the arrows carry it; arrows and Enter pick a person; arrows walk the menu) and a Skip, and progress is a value so a run resumes where it stopped.
Practice run
Learn Fieldline by doing it once
Move “Replace valve” to Done. Drag it, or press Space to pick it up.
0 of 3 done · lesson 1 · move a job to done
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/practice-run
Props
- lessons
- PracticeLesson[]
- default defaultPracticeLessons
- The lessons in order, each a move (board), mention (combobox) or label (menu) task with its own data and optional coach lines.
- progress / defaultProgress
- Record<string, "done" | "skipped">
- default — / {}
- Each lesson's state, controlled or initial. The run opens on the first lesson that is neither done nor skipped.
- onProgressChange
- (progress: PracticeProgress) => void
- default —
- Fires from the finish, skip or restart that changed it, with the whole progress.
- onComplete
- (lesson: PracticeLesson) => void
- default —
- A lesson's task was done for real.
- onSkip
- (lesson: PracticeLesson) => void
- default —
- A lesson was skipped.
- onFinish
- (progress: PracticeProgress) => void
- default —
- Start working was pressed after the last lesson.
- onRestart
- () => void
- default —
- Practice again was pressed; progress is cleared.
- coach
- string
- default "Wren"
- The coach's name, on its avatar, in the ticker and the caption.
- coachStyle
- "bubble" | "ticker" | "margin"
- default "bubble"
- An avatar and a speech bubble, a single mono line over a progress hairline, or a note in the left margin pointing at the sandbox. Under 30rem it is always a caption docked at the foot of the sandbox.
- stampStyle
- "seal" | "tick" | "ink"
- default "seal"
- The stamp a finished task gets: a round seal with its rim lettered, a tick drawn on flick in a rounded square, or a rubber-stamped DONE.
- accent
- string
- default "var(--accent-bright)"
- The stamp's ink, the lit lane, the step rail and the mention token. Any CSS colour, taken at a fixed lightness.
- stampHold
- number
- default 700
- How long the stamp rests before the next lesson slides in, ms.
- workspace
- string
- default "Fieldline"
- The product being practised, in the copy.
- status
- "ready" | "loading"
- default "ready"
- Whether the lessons are ready; loading draws a still sandbox and the rail is inert.
- maxHeight
- number
- default 560
- The tallest the run grows before its body scrolls, px.
- disabled
- boolean
- default false
- Nothing can be done or skipped; the run dims.
- className
- string
- default —
- Classes for the outer section.
| Prop | Type | Default | Description |
|---|---|---|---|
| lessons | PracticeLesson[] | defaultPracticeLessons | The lessons in order, each a move (board), mention (combobox) or label (menu) task with its own data and optional coach lines. |
| progress / defaultProgress | Record<string, "done" | "skipped"> | — / {} | Each lesson's state, controlled or initial. The run opens on the first lesson that is neither done nor skipped. |
| onProgressChange | (progress: PracticeProgress) => void | — | Fires from the finish, skip or restart that changed it, with the whole progress. |
| onComplete | (lesson: PracticeLesson) => void | — | A lesson's task was done for real. |
| onSkip | (lesson: PracticeLesson) => void | — | A lesson was skipped. |
| onFinish | (progress: PracticeProgress) => void | — | Start working was pressed after the last lesson. |
| onRestart | () => void | — | Practice again was pressed; progress is cleared. |
| coach | string | "Wren" | The coach's name, on its avatar, in the ticker and the caption. |
| coachStyle | "bubble" | "ticker" | "margin" | "bubble" | An avatar and a speech bubble, a single mono line over a progress hairline, or a note in the left margin pointing at the sandbox. Under 30rem it is always a caption docked at the foot of the sandbox. |
| stampStyle | "seal" | "tick" | "ink" | "seal" | The stamp a finished task gets: a round seal with its rim lettered, a tick drawn on flick in a rounded square, or a rubber-stamped DONE. |
| accent | string | "var(--accent-bright)" | The stamp's ink, the lit lane, the step rail and the mention token. Any CSS colour, taken at a fixed lightness. |
| stampHold | number | 700 | How long the stamp rests before the next lesson slides in, ms. |
| workspace | string | "Fieldline" | The product being practised, in the copy. |
| status | "ready" | "loading" | "ready" | Whether the lessons are ready; loading draws a still sandbox and the rail is inert. |
| maxHeight | number | 560 | The tallest the run grows before its body scrolls, px. |
| disabled | boolean | false | Nothing can be done or skipped; the run dims. |
| className | string | — | Classes for the outer section. |