KQ-1372 · TYPE/TRAIL
Type Trail
A container whose pointer writes a phrase: the letters are laid along the pointer's recent path, spaced by arc length and turned to its tangent, leaving their resting line one by one on springs.glide as the pen reaches them, wet in the accent colour at the nib and fading and shrinking down the tail. When the pointer rests the phrase gathers into a neat line under it on springs.snap — one crisp overshoot as each letter rights itself, staggered from the nib back — and moving again releases it onto the path on springs.glide; leaving sends it home. The container takes focus: the arrow keys walk a visible pen that writes the same trail, Enter gathers under it and Escape sends the phrase back.
Fieldline Notes
Notes that keep up
Write as fast as you think; Fieldline files it for you.
resting · move across the card to write
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/type-trail
Props
- text
- string
- default —
- The phrase the pointer writes.
- children
- ReactNode
- default —
- What the container holds; the trail is drawn above it and never takes its clicks.
- as
- "div" | "section" | "header" | "aside" | "figure"
- default "div"
- The container's element.
- spacing
- number
- default 0.06
- Extra space between letters along the path, em.
- tail
- number
- default 0.6
- How far the tail fades and shrinks, 0 (not at all) to 1.
- size
- "sm" | "md" | "lg"
- default "md"
- The phrase's type size against the container's: 0.85, 1.1 or 1.5em.
- smoothing
- number
- default 0.35
- How much the pen smooths the pointer, 0 (raw) to 1 (calligraphic).
- gatherAfter
- number
- default 160
- How long the pointer rests before the phrase gathers under it, ms.
- rest
- "center" | "bottom" | "hidden"
- default "bottom"
- Where the phrase waits when nobody is writing.
- color
- string
- default "var(--foreground)"
- The type's colour once dry, any CSS colour.
- accent
- string
- default "var(--accent-bright)"
- The ink at the nib: fresh letters, a few em long.
- trigger
- "mount" | "inView" | "manual"
- default "inView"
- When a ghost pen writes the phrase once by itself, to show the piece; manual never does.
- once
- boolean
- default true
- The ghost pen writes once, or every time the container re-enters view.
- delay
- number
- default 300
- Wait before the ghost pen, ms.
- onComplete
- () => void
- default —
- The ghost pen has finished and the phrase has come to rest.
- onStateChange
- (state: "rest" | "writing" | "gathered") => void
- default —
- Fires as the phrase rests, is being written, or has gathered under the pen.
- keyboard
- boolean
- default true
- The container takes keyboard focus, and the arrow keys move a pen.
- disabled
- boolean
- default false
- No writing: the phrase stays at rest.
- className
- string
- default —
- Classes for the container; give it a size (the trail is bounded to it) and the type the phrase scales from.
| Prop | Type | Default | Description |
|---|---|---|---|
| text | string | — | The phrase the pointer writes. |
| children | ReactNode | — | What the container holds; the trail is drawn above it and never takes its clicks. |
| as | "div" | "section" | "header" | "aside" | "figure" | "div" | The container's element. |
| spacing | number | 0.06 | Extra space between letters along the path, em. |
| tail | number | 0.6 | How far the tail fades and shrinks, 0 (not at all) to 1. |
| size | "sm" | "md" | "lg" | "md" | The phrase's type size against the container's: 0.85, 1.1 or 1.5em. |
| smoothing | number | 0.35 | How much the pen smooths the pointer, 0 (raw) to 1 (calligraphic). |
| gatherAfter | number | 160 | How long the pointer rests before the phrase gathers under it, ms. |
| rest | "center" | "bottom" | "hidden" | "bottom" | Where the phrase waits when nobody is writing. |
| color | string | "var(--foreground)" | The type's colour once dry, any CSS colour. |
| accent | string | "var(--accent-bright)" | The ink at the nib: fresh letters, a few em long. |
| trigger | "mount" | "inView" | "manual" | "inView" | When a ghost pen writes the phrase once by itself, to show the piece; manual never does. |
| once | boolean | true | The ghost pen writes once, or every time the container re-enters view. |
| delay | number | 300 | Wait before the ghost pen, ms. |
| onComplete | () => void | — | The ghost pen has finished and the phrase has come to rest. |
| onStateChange | (state: "rest" | "writing" | "gathered") => void | — | Fires as the phrase rests, is being written, or has gathered under the pen. |
| keyboard | boolean | true | The container takes keyboard focus, and the arrow keys move a pen. |
| disabled | boolean | false | No writing: the phrase stays at rest. |
| className | string | — | Classes for the container; give it a size (the trail is bounded to it) and the type the phrase scales from. |