Idle Detector
stimeo--idle
Tells you when interaction stops, warns before it does, and reports when you come back.
Reports when interaction with the page stops. It watches pointer movement, keys, scrolling, and returning to the tab. After the time you set with none of that, it reports the idle state. It can also warn shortly before, so you can confirm with someone before their session ends. When interaction returns, that is reported immediately too. It brings no warning dialog of its own, so pair it with one. It does not touch your server session. Normally one of these sits on the page as a whole.
Stop interacting with the page: a warning shows after 3s and the idle state after 6s. Move the mouse or press a key to come back.
Idle soon — interact to stay signed in
Idle — the session would time out here
Keyboard
This component has no keyboard interactions of its own.
<%# Idle / session-timeout demo: the controller watches document-level activity and,
after a short demo timeout, fires prompt -> idle; interacting again fires active.
Real apps use a ~15-minute timeout; this demo shortens it (6s, warning at 3s) so the
transitions are visible. The two notices are declared regions: the controller owns
hidden on them and shows each only while its own phase holds, so both are authored
hidden and no consumer JS is needed. Status semantics are this markup's to give. %>
<div
class="idle-demo"
data-controller="stimeo--idle"
data-stimeo--idle-timeout-value="6000"
data-stimeo--idle-prompt-before-value="3000">
<p class="idle-demo__hint"><%= t("components.idle.demo.hint") %></p>
<p
class="idle-demo__notice idle-demo__notice--prompt"
role="status"
data-stimeo--idle-target="prompt"
hidden><%= t("components.idle.demo.prompt") %></p>
<p
class="idle-demo__notice idle-demo__notice--idle"
role="status"
data-stimeo--idle-target="idle"
hidden><%= t("components.idle.demo.idle") %></p>
</div>
/*
* Presentation-only styles for the idle demo. The library owns visibility on the two
* notices and toggles data-prompt / data-idle on the root; this CSS lays out the hint
* plus the notices and tints each one for the phase it belongs to.
*/
.idle-demo {
display: flex;
flex-direction: column;
gap: 0.75rem;
max-width: 28rem;
}
.idle-demo__hint {
margin: 0;
color: var(--color-text-muted);
}
.idle-demo__notice {
margin: 0;
padding: 0.5rem 0.75rem;
border: 1px solid var(--border);
border-radius: 0.375rem;
font-weight: 600;
text-align: center;
}
.idle-demo__notice--prompt {
border-color: var(--amber-500);
background: var(--amber-50);
color: var(--amber-700);
}
.idle-demo__notice--idle {
border-color: var(--danger-500);
background: var(--danger-50);
color: var(--danger-700);
}
This demo needs no consumer-side JS (the controller handles the behavior).
These demo styles use shared design tokens (light + dark). Copy the shared styles too, then toggle data-theme on your root element for dark mode.
The data-* attributes you add to your own HTML to wire this component. Put the data-controller below on a root element, then place its targets / values / actions inside that element.
On the root element
data-controller="stimeo--idle"
Targets
| Name | Description | Attribute |
|---|---|---|
prompt
|
A region shown only while data-prompt is set (the warning step before idle); the controller owns its hidden. |
data-stimeo--idle-target="prompt" |
idle
|
A region shown only while data-idle is set; the controller owns its hidden. |
data-stimeo--idle-target="idle" |
Values
| Name | Description | Attribute |
|---|---|---|
timeout
|
Milliseconds of no activity before idle (default 900000). | data-stimeo--idle-timeout-value |
promptBefore
|
Milliseconds before the timeout to fire prompt (0 = no prompt). |
data-stimeo--idle-prompt-before-value |
events
|
Activity event types that reset the clock, watched passively; visibilitychange is always watched too. |
data-stimeo--idle-events-value |
Events
| Name | Description | Event |
|---|---|---|
prompt
|
Fires promptBefore ms before the timeout, with detail.remaining (ms). |
stimeo--idle:prompt |
idle
|
Fires when the timeout is reached. | stimeo--idle:idle |
active
|
Fires when the user interacts again after a prompt or idle. | stimeo--idle:active |
State hooks
The library only manages these ARIA/data attributes and custom properties. Your CSS reads them to render the look — selectors like [aria-selected], [aria-expanded], or var(--stimeo--…) hook into this state.
| Hook | Target | Meaning |
|---|---|---|
data-prompt |
Controller element | Present (set to true) during the warning step before idle; removed on idle or activity. |
data-idle |
Controller element | Present (set to true) while idle; removed when activity resumes. |