KQ-1714 · SESSION/LAPSE
Session Lapse
An idle-timeout guard for a page: before the session ends an alert dialog rises over it with a ring that drains linearly while the seconds in its middle count down, both read off one motion value. Stay signed in, Escape, or a press, key or scroll outside the dialog refills the ring on glide while it pops on snap and the seconds count back up, then the dialog leaves on the exit ease; letting it run out fades the page into a signed-out note that keeps the unsaved draft. Focus moves to Stay signed in when the warning appears, Tab wraps inside it, and the countdown is announced when the warning appears, at 30 seconds in longer warnings, and at 10.
idle clock running · Fernworks
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/session-lapse
Props
- timeout
- number
- default 900000
- Idle time before the session ends, in ms.
- warningTime
- number
- default 60000
- How long before the end the warning appears, in ms; the ring counts this window down.
- open / defaultOpen
- boolean
- default — / false
- Whether the warning is showing, controlled or initial.
- onOpenChange
- (open: boolean) => void
- default —
- Fires when the warning appears or leaves, from whatever caused it.
- watch
- "document" | "self" | "none"
- default "document"
- Whose activity keeps the session alive: the whole page, only this component's box, or nothing but the button.
- paused
- boolean
- default false
- Hold the idle clock (a call, a video); it restarts when released, and a showing warning holds its time.
- onExtend
- (via: "button" | "activity") => void
- default —
- The session was extended, by the button or Escape, or by activity during the warning.
- onSignOut
- () => void
- default —
- Sign out was chosen from the warning.
- onExpire
- () => void
- default —
- The warning ran out and the session ended.
- onSignIn
- () => void
- default —
- Sign back in was pressed on the signed-out note.
- draft
- { title: string; excerpt: string; words?: number } | null
- default defaultSessionLapseDraft
- The unsaved work the signed-out note promises to keep; null for none.
- appName
- string
- default "Fernworks"
- The product's name, in the warning's sentence and the announcements.
- title
- string
- default —
- The warning's title. Defaults by tone: "Still there?", "Are you still working?", "Signing out soon".
- labels
- { stay?: string; signOut?: string; signIn?: string }
- default Stay signed in · Sign out · Sign back in
- The three actions' words.
- ringStyle
- "line" | "ticks" | "pie"
- default "line"
- How the countdown is drawn: a draining line, a tick per second, or a shrinking sector.
- tone
- "calm" | "plain" | "urgent"
- default "calm"
- The ring's colour and the title's voice: cobalt, ink, or amber turning to danger for the last ten seconds.
- children
- ReactNode
- default —
- The page the session belongs to; inert while the warning or the note shows. A quiet placeholder when omitted.
- className
- string
- default —
- Classes for the outer wrapper.
| Prop | Type | Default | Description |
|---|---|---|---|
| timeout | number | 900000 | Idle time before the session ends, in ms. |
| warningTime | number | 60000 | How long before the end the warning appears, in ms; the ring counts this window down. |
| open / defaultOpen | boolean | — / false | Whether the warning is showing, controlled or initial. |
| onOpenChange | (open: boolean) => void | — | Fires when the warning appears or leaves, from whatever caused it. |
| watch | "document" | "self" | "none" | "document" | Whose activity keeps the session alive: the whole page, only this component's box, or nothing but the button. |
| paused | boolean | false | Hold the idle clock (a call, a video); it restarts when released, and a showing warning holds its time. |
| onExtend | (via: "button" | "activity") => void | — | The session was extended, by the button or Escape, or by activity during the warning. |
| onSignOut | () => void | — | Sign out was chosen from the warning. |
| onExpire | () => void | — | The warning ran out and the session ended. |
| onSignIn | () => void | — | Sign back in was pressed on the signed-out note. |
| draft | { title: string; excerpt: string; words?: number } | null | defaultSessionLapseDraft | The unsaved work the signed-out note promises to keep; null for none. |
| appName | string | "Fernworks" | The product's name, in the warning's sentence and the announcements. |
| title | string | — | The warning's title. Defaults by tone: "Still there?", "Are you still working?", "Signing out soon". |
| labels | { stay?: string; signOut?: string; signIn?: string } | Stay signed in · Sign out · Sign back in | The three actions' words. |
| ringStyle | "line" | "ticks" | "pie" | "line" | How the countdown is drawn: a draining line, a tick per second, or a shrinking sector. |
| tone | "calm" | "plain" | "urgent" | "calm" | The ring's colour and the title's voice: cobalt, ink, or amber turning to danger for the last ten seconds. |
| children | ReactNode | — | The page the session belongs to; inert while the warning or the note shows. A quiet placeholder when omitted. |
| className | string | — | Classes for the outer wrapper. |