Feedback

StaleRegion

Wrapper for a page whose data may be old that keeps that data at full contrast and turns off only the controls that change something, each described by why.

import { StaleRegion } from '@lostgradient/cinder';
staleofflineinert
01

Overview

Reference usage

StaleRegion wraps a page (or a part of one) that keeps showing old data while the server cannot answer. It changes nothing about how that data looks: text, dots and tones stay exactly as they were, at full contrast, never dimmed with opacity. The warning banner above it is the only sign it is old. What the region does is turn off the controls that change something, and only those.

A control opts in with mutating, on Button, Toggle, Checkbox, Select and DropdownTrigger. While the region is stale an opted-in control goes inert: it carries aria-disabled="true", stays focusable so a keyboard or screen-reader user can still land on it and hear why, ignores the press, and lists the region's reason in aria-describedby ("Off until it’s back" unless the page words its own). Everything that does not opt in stays live: links, tabs, filters, search, Retry now and Cancel. A control outside any region is untouched. When stale turns false the controls return by themselves, with no remount.

The region takes no box of its own (display: contents), so wrapping a header, a banner and a list does not move any of them.

What it does not do

  • It does not draw the banner. Put a Banner with a connection preset inside the region; the banner names the "as of" time with its zone once, so no row repeats it.
  • It does not choose between the old data and the full error state. A page that has data shows the data under the banner; a page with nothing to show renders the error state instead. Never both.
  • It does not say which controls change something. That is the page's call: mark the pencil, the trash and the "+" with mutating, and leave Export, which only reads, without it. New chat creates a new chat rather than editing the list, so it stays live.

Usage

svelte
<script lang="ts">
  import { Banner, Button, Link, StaleRegion } from '@lostgradient/cinder';

  let reachable = $state(false);
</script>

<StaleRegion stale={!reachable} reason="Off until storage answers.">
  {#if !reachable}
    <Banner preset="unreachable" dataUpdatedAt={new Date()} onRetry={() => (reachable = true)} />
  {/if}
  <Button mutating iconOnly aria-label="New agent">+</Button>
  <Link href="/agents/tool-runner">Tool runner</Link>
</StaleRegion>
Live preview

Old data with inert writes

Off until it’s back
Can’t reach the Interborough server. Showing what loaded as of 1:54 PM UTC. Changes are off until it’s back. Retrying in 4 s (attempt 3 of 8).
Agents
Tool runner · Available
Assistant · Available

02

When to use

Use when
  • The server is unreachable or a refresh failed and the page keeps showing what it loaded, with a banner above it.
  • Turning off a page's writing controls (Edit, Save, Delete, a switch) while its reading controls (links, filters, tabs, Retry) stay live.
Avoid when
  • Disabling one control for its own reason, such as a missing provider — set aria-disabled on that control and describe it.
  • Showing the connection state itself — use banner with a connection preset.
03

Examples

Old data with inert writes

The server is unreachable, so the page keeps its data at full contrast under a warning banner. Only the button that changes something is inert (aria-disabled, still focusable, described by "Off until it’s back"); the link and Retry now stay live.

Every control that changes something

Button, Toggle, Checkbox and Select opt in with mutating. Under a stale region each one keeps focus, ignores the press and is described by the reason. The page words the reason, and the filter beside them, which only reads, stays live.

An offline page with old data at full contrast

The offline banner sits over the page, the old data keeps full text contrast (no opacity), and only the controls marked mutating go inert: the header +, Edit and the approval card’s Approve and Deny. Reading, Export and links stay live.

04

Props

Props for stale-region
Name
Type
Default
Description
stale boolean true Whether the data under the region is old. While it is, every control inside that opted in with mutating goes inert; when it turns false they return by themselves. Defaults to true, so a page mounts the region only while it is stale or binds this to its connection state.
reason text 'Off until it’s back' The reason an inert control is off, read as its description. Pages word it for what they show: "Off until storage answers", "Approving is off until Interborough is reachable".
describedBy text The id of an element that already says why, such as the page's banner. Inert controls list it in aria-describedby instead of the region's own reason, which is then not rendered.
children required snippet The page or section whose data may be old.