KQ-1623 · ENVELOPE/MODAL
Envelope Modal
A desk of envelopes, each closed with a seal, that open like letters into the full story. Opening one is three beats: the seal gives and the flap swings up about its hinge in perspective on springs.snap, its patterned liner showing as it turns; the folded letter slides up out of the pocket on springs.glide; then it flies to the middle and grows to fill the component's box as a modal, its panels unfolding one after another on springs.glide in a cascade, each darkening as it turns edge-on, until the real, scrollable letter takes over and focus moves into it. Closing refolds it, carries it back over its envelope and slides it into the pocket while the flap closes on springs.snap and the seal is pressed back with springs.recoil. Enter or Space opens an envelope, Escape closes the letter, and focus stays inside it while it is open.
Fieldline Journal · October
Letters from the field
desk · 6 letters, enter opens
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/envelope-modal
Props
- items
- readonly EnvelopeModalItem[]
- default defaultEnvelopeModalItems
- The letters: { id, title, from?, date?, body, monogram? }. A string body splits into paragraphs on blank lines.
- value / defaultValue
- string | null
- default null
- The id of the open letter, controlled or initial.
- onValueChange
- (id: string | null) => void
- default —
- Fires from the click or key that opens or closes a letter.
- paperTone
- "ivory" | "kraft" | "linen" | "blush"
- default "ivory"
- The paper: envelope, liner and letter, fixed pigments that look the same in both themes.
- foldCount
- number
- default 3
- How many panels the letter is folded into, 2 to 5.
- seal
- "wax" | "foil" | "string" | "none"
- default "wax"
- What holds the flap shut: an embossed wax disc, a scalloped foil sticker, a button-and-string tie, or nothing.
- sealColor
- string
- default —
- The seal's colour, any CSS colour; defaults to wax red, foil gold or string brown.
- tilt
- number
- default 2.5
- How far the envelopes lie askew on the desk, in degrees either way.
- scrim
- number
- default 0.55
- How far the desk dims behind an open letter, 0 to 1.
- inset
- number
- default 12
- The open letter's margin inside the box, in px.
- columns
- number
- default —
- A fixed number of columns; by default 2 under 480 px and 3 above.
- headingLevel
- 2 | 3 | 4
- default 3
- The letter title's heading level.
- label
- string
- default "Letters"
- Names the desk for assistive technology.
- closeLabel
- string
- default "Close letter"
- The close button's name.
- seed
- number
- default 3
- Seeds the desk's scatter.
- sound
- boolean
- default false
- Plays the paper: the flap, the slide and every crease, only after the visitor's click or key.
- disabled
- boolean
- default false
- Shows the desk but opens nothing.
- className
- string
- default "h-full w-full"
- Sizes the box; the desk and the open letter fill it. Give it a height.
| Prop | Type | Default | Description |
|---|---|---|---|
| items | readonly EnvelopeModalItem[] | defaultEnvelopeModalItems | The letters: { id, title, from?, date?, body, monogram? }. A string body splits into paragraphs on blank lines. |
| value / defaultValue | string | null | null | The id of the open letter, controlled or initial. |
| onValueChange | (id: string | null) => void | — | Fires from the click or key that opens or closes a letter. |
| paperTone | "ivory" | "kraft" | "linen" | "blush" | "ivory" | The paper: envelope, liner and letter, fixed pigments that look the same in both themes. |
| foldCount | number | 3 | How many panels the letter is folded into, 2 to 5. |
| seal | "wax" | "foil" | "string" | "none" | "wax" | What holds the flap shut: an embossed wax disc, a scalloped foil sticker, a button-and-string tie, or nothing. |
| sealColor | string | — | The seal's colour, any CSS colour; defaults to wax red, foil gold or string brown. |
| tilt | number | 2.5 | How far the envelopes lie askew on the desk, in degrees either way. |
| scrim | number | 0.55 | How far the desk dims behind an open letter, 0 to 1. |
| inset | number | 12 | The open letter's margin inside the box, in px. |
| columns | number | — | A fixed number of columns; by default 2 under 480 px and 3 above. |
| headingLevel | 2 | 3 | 4 | 3 | The letter title's heading level. |
| label | string | "Letters" | Names the desk for assistive technology. |
| closeLabel | string | "Close letter" | The close button's name. |
| seed | number | 3 | Seeds the desk's scatter. |
| sound | boolean | false | Plays the paper: the flap, the slide and every crease, only after the visitor's click or key. |
| disabled | boolean | false | Shows the desk but opens nothing. |
| className | string | "h-full w-full" | Sizes the box; the desk and the open letter fill it. Give it a height. |