Tiny, headless accessibility toolkit for Svelte/SvelteKit: dual aria-live regions, imperative announce() API, screen-reader utility components, and a route-change helper.
- Dual off-screen live regions (
polite&assertive) to avoid priority clashes - Simple
announce(text, options?)API with: politeness, priority sorting, TTL auto-cleanup, optionaldedupeKey - Headless
<LiveAnnouncer />component – inject once near root <VisuallyHidden />wrapper for SR-only text<SkipTo />accessible skip link with safe focus managementannounceRouteChange()helper for SvelteKit navigation events- Zero runtime dependencies beyond Svelte peer dep
- Strict TypeScript & generated
.d.tstypes
pnpm add svelte-aria-live
# or
npm install svelte-aria-liveAdd the announcer once (e.g. in App.svelte or layout):
<script>
import { LiveAnnouncer } from 'svelte-aria-live';
</script>
<LiveAnnouncer />import { announce } from "svelte-aria-live";
announce("Saved successfully");
announce("Error saving", { politeness: "assertive", priority: 100 });
announce("Loading data…", { dedupeKey: "loading", ttlMs: 3000 });import { announceRouteChange } from "svelte-aria-live";
// After navigation:
announceRouteChange(() => document.title);<SkipTo target="#main" />
<main id="main">...</main><h1>Dashboard <VisuallyHidden>(real-time metrics)</VisuallyHidden></h1>Adds an announcement to the queue. Returns numeric id.
AnnounceOptions:
politeness:'polite' | 'assertive'(default'polite')priority: number (higher renders first; default0)ttlMs: milliseconds before removal (default5000)dedupeKey: string; replaces any prior announcements with same key
Announces a route change assertively with high priority (200) and dedupe key 'route'.
Renders two off-screen regions. limit trims visible DOM nodes (older messages still removed by TTL).
<VisuallyHidden />
Wrap SR-only content. Pure headless styling.
Skip link focusing target. Temporarily sets tabindex="-1" if necessary for focus.
Off-screen pattern uses both classic clip: rect(0 0 0 0) and modern clip-path: inset(50%) for broad compatibility.
Two separate live regions prevent assertive announcements from starving polite messages.
No aria-atomic set to allow incremental updates.
pnpm install
pnpm check
pnpm buildOutputs package/index.js + index.d.ts.
pnpm dev:demo
# build/preview
pnpm build:demo
pnpm preview:demoOpen http://localhost:5173 and trigger buttons; inspect DOM to see live regions update.
MIT © 2025 Nickbrit