KQ-1266 · PUBLISH/PRESS

Publish Press

A publish button drawn as a sheet of paper, printed by a roller: a press sets an inked roller down at the start of the label, it bobs in place on a mirrored tween while the action is pending, and on success it rolls across the label on a symmetric move tween, inking the new word behind it through a clip that follows its track while the old label smears into a dragged, skewed band that dries away; the roller is a cylinder seen face on whose ribs turn at distance over radius, so a bigger drum turns slower. The ink is printed through a halftone screen whose dots grow with the ink load and starts wet and solid, drying back to its screen over the success hold; with a schedule set, a date stamp hovers while pending and slams down on the recoil spring instead, and pressing a published or scheduled button lifts the ink off in four strips on the exit ease in a cascade. It is a native button: Enter or Space presses it, Escape cancels while pending, and a failure leaves Retry.

KQ-1266 · PUBLISH/PRESS

Field notes: the spring survey

Waylight Journal · draft saved 2 min ago

draft · press publish

Install

One command — the source lands in your repo. Or copy it from the Code tab.

$ pnpm dlx shadcn@latest add @kinetiq/publish-press

Props

value / defaultValue
"draft" | "published" | "scheduled"
default "draft"
The document's status, controlled or initial. A controlled press reports through onValueChange and prints once the host answers.
onValueChange
(value: "draft" | "published" | "scheduled") => void
default —
Each status the document moves to, once its action has succeeded.
onPublish
(at: Date | null, signal: AbortSignal) => void | Promise<unknown>
default —
Publishes now (at is null) or schedules for at. Return a promise and the roller bobs until it settles; the signal aborts on Escape.
onUnpublish
(signal: AbortSignal) => void | Promise<unknown>
default —
Takes a published or scheduled document back to draft.
schedule
Date | number | null
default —
When set, a press schedules for this moment and stamps the date instead of rolling; the draft label becomes scheduleLabel.
formatDate
(date: Date) => string
default UTC "Oct 9 · 09:00"
How the stamped date reads. The default prints "Oct 9 · 09:00" from UTC parts so server and browser agree; pass your own for the reader's zone.
state
"idle" | "pending" | "success" | "error"
default —
Controlled action state. Every move goes through onStateChange and waits for this.
onStateChange
(state: "idle" | "pending" | "success" | "error") => void
default —
Each action state, from the press, the answer or the timer that caused it.
ink
number
default 0.7
How much ink the roller carries, 0 to 1: a pale, speckled halftone print or a dense, solid one.
roller
number
default 0.5
How big and heavy the roller is, 0 to 1: a quick small brayer or a slow wide drum whose ribs turn slower.
smudge
number
default 0.5
How much the old label smears as the roller drags over it, 0 to 1: the band's width, drag, skew and strength. 0 wipes clean.
label
string
default "Publish"
The text on a draft.
scheduleLabel
string
default "Schedule"
The text on a draft when schedule is set.
pendingLabel
string
default "Publishing"
The text while publishing.
publishedLabel
string
default "Published"
The word the roller inks.
errorLabel
string
default "Retry"
The text after an action failed; a press tries it again.
inkColor
string
default "var(--accent-bright)"
The ink: the printed word, the stamp and the roller. Any CSS colour.
successHold
number
default 1400
How long fresh ink stays wet before it dries and the button rests, in ms.
errorHold
number
default 2600
How long the error holds before the button rests, in ms.
size
"sm" | "md" | "lg"
default "md"
32, 40 or 48 px tall; the roller and the strips scale with it.
sound
boolean
default false
Play the thock of the roller setting down and the stamp landing, and the swish of the roll and the peel, only within the press's own beat. No audio context exists unless this is on.
disabled
boolean
default false
Dims and disables the button.
className
string
default —
Merged onto the root's classes.