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.

KQ-1695 · PRACTICE/RUN

Practice run

Learn Fieldline by doing it once

Lesson 1 of 3Move a job to Done

Practice copy

Space or Enter picks a card up; the arrow keys carry it from lane to lane; Space or Enter puts it down; Escape puts it back.

To do2

Doing1

Done1

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.