KQ-1622 · WORD/WINDOW
Word Window
A paragraph whose linked words carry pictures inside their letters. Hover a word or focus it and its ink fades so the letters become windows onto its picture, placed exactly where the preview card's picture will be and drifting a few pixels against the pointer on springs.glide. Rest on it for expandDelay and a card opens out of the word: a clip that starts as the word's own box grows to the whole card on springs.glide while the drift springs home, so the window spreads from the letters into the full picture, and the caption follows. The words are real links in real text; Escape closes the card where focus is, Enter follows the link, and a long press opens it on touch.
Fernworks Quarterly · autumn issue
Our autumn issue starts on the salt flats at first light, crosses the harbour as the boats come in, and ends in an orchard where the last pears are picked by hand.
reading · rest on a word to open it
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/word-window
Props
- text
- string
- default defaultWordWindowText
- The paragraph; each [bracketed phrase] is a link carrying the next picture in links.
- links
- readonly WordWindowLink[]
- default defaultWordWindowLinks
- One per bracketed phrase, in order: { href?, src?, alt, caption?, scene? }. Without src a scene (flats, harbour, orchard, fjord) is drawn in code.
- as
- "p" | "div" | "blockquote"
- default "p"
- The paragraph's element.
- expandDelay
- number
- default 450
- How long the pointer or focus rests on a word before its card opens, in ms.
- cardSize
- number
- default 200
- The card's width in px; its picture is 0.62 as tall, and it shrinks to fit a smaller box.
- maskTone
- "natural" | "duotone" | "mono" | "deep"
- default "natural"
- How the picture is toned in the letters and the card: as drawn, recoloured to the accent, grey, or deepened toward ink.
- drift
- number
- default 8
- How far the picture drifts behind the letters against the pointer, in px.
- closeDelay
- number
- default 140
- How long the card waits after the pointer leaves before it closes, in ms.
- value / defaultValue
- number | null
- default null
- The index of the link whose card is open, controlled or initial.
- onValueChange
- (index: number | null) => void
- default —
- Fires when a rest, a key or a leave opens or closes a card.
- accent
- string
- default "var(--accent-bright)"
- The underline's colour and the duotone's hue, any CSS colour.
- underline
- boolean
- default true
- A dotted underline marks the linked words at rest.
- onLinkClick
- (link: WordWindowLink, index: number, event: React.MouseEvent<HTMLElement>) => void
- default —
- Fires when a linked word is clicked or activated, before it navigates.
- disabled
- boolean
- default false
- Keeps the words as plain links: no pictures, no cards.
- className
- string
- default —
- Classes for the box the card stays inside; size it to give the card room.
| Prop | Type | Default | Description |
|---|---|---|---|
| text | string | defaultWordWindowText | The paragraph; each [bracketed phrase] is a link carrying the next picture in links. |
| links | readonly WordWindowLink[] | defaultWordWindowLinks | One per bracketed phrase, in order: { href?, src?, alt, caption?, scene? }. Without src a scene (flats, harbour, orchard, fjord) is drawn in code. |
| as | "p" | "div" | "blockquote" | "p" | The paragraph's element. |
| expandDelay | number | 450 | How long the pointer or focus rests on a word before its card opens, in ms. |
| cardSize | number | 200 | The card's width in px; its picture is 0.62 as tall, and it shrinks to fit a smaller box. |
| maskTone | "natural" | "duotone" | "mono" | "deep" | "natural" | How the picture is toned in the letters and the card: as drawn, recoloured to the accent, grey, or deepened toward ink. |
| drift | number | 8 | How far the picture drifts behind the letters against the pointer, in px. |
| closeDelay | number | 140 | How long the card waits after the pointer leaves before it closes, in ms. |
| value / defaultValue | number | null | null | The index of the link whose card is open, controlled or initial. |
| onValueChange | (index: number | null) => void | — | Fires when a rest, a key or a leave opens or closes a card. |
| accent | string | "var(--accent-bright)" | The underline's colour and the duotone's hue, any CSS colour. |
| underline | boolean | true | A dotted underline marks the linked words at rest. |
| onLinkClick | (link: WordWindowLink, index: number, event: React.MouseEvent<HTMLElement>) => void | — | Fires when a linked word is clicked or activated, before it navigates. |
| disabled | boolean | false | Keeps the words as plain links: no pictures, no cards. |
| className | string | — | Classes for the box the card stays inside; size it to give the card room. |