KQ-1376 · READ/ALONG
Read Along
Scroll-reveal for long paragraphs: every word starts in faint ink and the words darken in reading order as the paragraph scrolls past the reading line, a long word taking longer than a short one, with the reading position gliding on springs.glide between scroll events so scrolling back reverses it just as smoothly. A soft underline draws itself through the word being read — its tail follows the word's start on glide, so between words it slides on like a finger under the line — or a caret marks the place; the keyboard path is the scroll container's own scrolling.
KQ-1376 · READ/ALONG
reading word 1 of 69 · scroll the notes
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/read-along
Props
- text
- string
- default —
- The paragraph. It stays real text, read and copied in order.
- as
- "p" | "div" | "span" | "h2" | "h3" | "h4"
- default "p"
- The element the paragraph renders as.
- faint
- number
- default 0.2
- How faint unread words are, as opacity 0 to 1.
- range
- number
- default 0.5
- Where reading ends, as a share of the viewport's height below start: the paragraph is read once its bottom edge has risen to start − range. 0.1 to 1.
- start
- number
- default 0.85
- Where reading begins: the paragraph's top at this fraction of the viewport's height from its top.
- cursor
- "underline" | "caret" | "none"
- default "underline"
- What marks the reading position: a soft underline drawn through the word, a caret, or nothing.
- cursorColor
- string
- default "var(--accent-bright)"
- The cursor's colour.
- softness
- number
- default 8
- How many characters the darkening front is spread over.
- pace
- "length" | "even"
- default "length"
- Whether a long word takes longer to read (length) or every word the same (even).
- smooth
- boolean
- default true
- Glide the reading position between scroll events.
- progress
- number
- default —
- Drive the reading yourself, 0 to 1; overrides scrolling.
- scrollContainer
- React.RefObject<HTMLElement | null>
- default —
- The scroll container to read; defaults to the nearest scrollable ancestor, or the window.
- onProgressChange
- (progress: number) => void
- default —
- How far through the paragraph reading is, 0 to 1 in steps of 0.01, as it changes.
- onWordChange
- (index: number) => void
- default —
- The word being read changed: its index among the paragraph's words. Also reported on arrival.
- onComplete
- () => void
- default —
- The paragraph has been read to its end (again).
- className
- string
- default —
- Classes for the paragraph element; size, leading and colour are inherited.
| Prop | Type | Default | Description |
|---|---|---|---|
| text | string | — | The paragraph. It stays real text, read and copied in order. |
| as | "p" | "div" | "span" | "h2" | "h3" | "h4" | "p" | The element the paragraph renders as. |
| faint | number | 0.2 | How faint unread words are, as opacity 0 to 1. |
| range | number | 0.5 | Where reading ends, as a share of the viewport's height below start: the paragraph is read once its bottom edge has risen to start − range. 0.1 to 1. |
| start | number | 0.85 | Where reading begins: the paragraph's top at this fraction of the viewport's height from its top. |
| cursor | "underline" | "caret" | "none" | "underline" | What marks the reading position: a soft underline drawn through the word, a caret, or nothing. |
| cursorColor | string | "var(--accent-bright)" | The cursor's colour. |
| softness | number | 8 | How many characters the darkening front is spread over. |
| pace | "length" | "even" | "length" | Whether a long word takes longer to read (length) or every word the same (even). |
| smooth | boolean | true | Glide the reading position between scroll events. |
| progress | number | — | Drive the reading yourself, 0 to 1; overrides scrolling. |
| scrollContainer | React.RefObject<HTMLElement | null> | — | The scroll container to read; defaults to the nearest scrollable ancestor, or the window. |
| onProgressChange | (progress: number) => void | — | How far through the paragraph reading is, 0 to 1 in steps of 0.01, as it changes. |
| onWordChange | (index: number) => void | — | The word being read changed: its index among the paragraph's words. Also reported on arrival. |
| onComplete | () => void | — | The paragraph has been read to its end (again). |
| className | string | — | Classes for the paragraph element; size, leading and colour are inherited. |