Session Timeout

Warns before an idle session expires and lets the user stay signed in, so a timeout doesn't silently lose unsaved work.

StopsLogged out and lost unsaved work

Installation

pnpm dlx shadcn@latest add https://bollard-ui.vercel.app/r/session-timeout.json

The files land in your project. They're yours to edit.

What it catches

  • Idle time approaching the timeout (warns warnBefore ms ahead)
  • Activity in another tab, which resets the timer (BroadcastChannel)
  • Sign-out in another tab, followed here
  • Keep-alive failures, shown while the warning stays open

Props

SessionTimeout props
PropTypeDefault
timeout

Idle time before the session ends, in ms.

number15 * 60_000
warnBefore

How long before expiry the warning opens, in ms.

number60_000
onKeepAlive* (required)

Extend the session on the server. Return a promise to show progress; throw to keep the warning.

() => void | Promise<void>—
onSignOut* (required)

Sign out now: the user chose to, or another tab signed out.

() => void—
onExpire

Called when the idle time runs out. Defaults to `onSignOut`.

() => void—
channel

BroadcastChannel name shared by every tab of the app.

string"bollard-ui-session"
announceAt

Seconds left at which screen readers hear the countdown.

number[][60, 30, 10]
disabled

Pause tracking, e.g. while signed out.

booleanfalse
title

Dialog title.

string"Still there?"
description

Dialog description.

string"You'll be signed out for inactivity."
stayLabel

Label of the stay-signed-in button.

string"Stay signed in"
signOutLabel

Label of the sign-out button.

string"Sign out"
announcement

Read to screen readers; `{seconds}` is filled in.

string"Your session ends in {seconds} seconds."
errorText

Shown when `onKeepAlive` rejects.

string"Couldn't extend your session. Try again."

* required. Also accepts the native props of <dialog> (className, aria-*, data-*…), passed through to it.

Accessibility

  • Native <dialog> with role=alertdialog, labelled and described
  • Stay signed in receives focus (autoFocus)
  • Countdown is spoken only from announceAt seconds, assertively; errors use role=alert
  • Ring and digit animation respect reduced motion

Only what the source does. Test with your own screen reader and content before shipping.

Limitations

This is a UX guard rail. Enforce on the server: Expire sessions on the server and extend them only through an authenticated keep-alive.

  • The client timer is advisory; the server session can still expire on its own clock
  • Cross-tab sync needs BroadcastChannel
  • Does not save work; pair with autosave

What it stops

Logged out and lost unsaved work

Also known as

session timeout · idle timeout · auto logout · stay signed in · countdown · net banking · jwt expiry · keep me logged in

Dependencies

Pairs well with