npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@pithagon/live-region

v0.1.0

Published

A custom element for making announcements with live regions - Svelte 5

Readme

@pithagon/live-region

A Svelte 5 component for making announcements with ARIA live regions

npm version License: MIT

Overview

@pithagon/live-region provides an accessible way to announce dynamic content changes to screen reader users in Svelte 5 applications. It implements ARIA live regions following best practices for web accessibility.

Features

  • Svelte 5 Native - Built with Svelte 5 runes ($state, $effect)
  • Accessible - Follows ARIA live region best practices
  • TypeScript - Full type safety with TypeScript
  • Flexible - Global announcements or component-level usage
  • Smart Queuing - Priority-based message queue (assertive > polite)
  • Cancelable - Cancel delayed announcements when needed
  • Zero Dependencies - Minimal footprint

Installation

# Using npm
npm install @pithagon/live-region

# Using bun
bun add @pithagon/live-region

# Using pnpm
pnpm add @pithagon/live-region

Quick Start

1. Set up the global LiveRegion

Add the LiveRegion component to your root layout (e.g., src/routes/+layout.svelte):

<script>
	import { LiveRegion, registerLiveRegion } from '@pithagon/live-region';

	let liveRegion;

	$effect(() => {
		if (liveRegion) {
			registerLiveRegion(liveRegion);
		}
	});
</script>

<LiveRegion bind:this={liveRegion} />

<slot />

2. Make announcements

Now you can use the global announce() function anywhere in your app:

<script>
	import { announce } from '@pithagon/live-region';

	function handleSubmit() {
		// ... form submission logic
		announce('Form submitted successfully!');
	}
</script>

<button onclick={handleSubmit}>Submit</button>

Usage

Basic Announcements

import { announce } from '@pithagon/live-region';

// Simple announcement (polite by default)
announce('Item added to cart');

// Polite announcement (doesn't interrupt)
announce('Form saved successfully', {
	politeness: 'polite'
});

// Assertive announcement (interrupts screen reader)
announce('Error: Connection lost', {
	politeness: 'assertive'
});

Delayed Announcements

import { announce } from '@pithagon/live-region';

// Announce after 5 seconds
announce('Your session will expire soon', {
	politeness: 'polite',
	delayMs: 5000
});

Canceling Announcements

import { announce } from '@pithagon/live-region';

// Create a cancelable announcement
const cancelable = announce('Saving changes...', {
	delayMs: 3000
});

// Cancel if needed (e.g., save completed early)
cancelable.cancel();

Announcing from Elements

import { announceFromElement } from '@pithagon/live-region';

const statusElement = document.getElementById('status');
// Uses aria-label if present, otherwise innerText/textContent
announceFromElement(statusElement);

Clearing All Announcements

import { clear } from '@pithagon/live-region';

// Clear all pending announcements (useful for route transitions)
clear();

Component-Level Usage

If you prefer not to use global registration:

<script>
	import { LiveRegion } from '@pithagon/live-region';

	let liveRegion;

	function handleClick() {
		liveRegion?.announce('Button clicked!');
	}
</script>

<LiveRegion bind:this={liveRegion} />
<button onclick={handleClick}>Click me</button>

API Reference

Components

LiveRegion

The main component that creates ARIA live region containers.

Props:

  • delay?: number - Delay between announcements in milliseconds (default: 150)

Methods:

  • announce(message: string, options?: AnnounceOptions): Cancelable<Promise<void>>
  • announceFromElement(element: HTMLElement, options?: AnnounceOptions): Cancelable<Promise<void>>
  • clear(): void - Clear all pending messages
  • getMessage(politeness?: 'polite' | 'assertive'): string - Get current message

Functions

announce(message, options?)

Announce a message using the global live region.

Parameters:

  • message: string - The message to announce
  • options?: AnnounceOptions - Announcement options

Returns: Cancelable<Promise<void>>

announceFromElement(element, options?)

Announce the text content of an element.

Parameters:

  • element: HTMLElement - The element to announce from
  • options?: AnnounceOptions - Announcement options

Returns: Cancelable<Promise<void>>

registerLiveRegion(instance)

Register a LiveRegion instance as the global live region.

Parameters:

  • instance: LiveRegion - The LiveRegion component instance

unregisterLiveRegion()

Unregister the current global live region.

clear()

Clear all pending announcements from the global live region.

getMessage(politeness?)

Get the current message from the global live region.

Parameters:

  • politeness?: 'polite' | 'assertive' - The politeness level (default: 'polite')

Returns: string

Types

type Politeness = 'polite' | 'assertive';

type AnnounceOptions =
	| {
			politeness?: 'assertive';
			delayMs?: never;
	  }
	| {
			politeness?: 'polite';
			delayMs?: number;
	  };

type Cancelable<T> = T & {
	cancel: () => void;
};

Best Practices

1. Use One Global LiveRegion

Place the <LiveRegion /> component in your root layout to ensure it's available across all pages:

<!-- src/routes/+layout.svelte -->
<script>
	import { LiveRegion, registerLiveRegion } from '@pithagon/live-region';

	let liveRegion;

	$effect(() => {
		if (liveRegion) {
			registerLiveRegion(liveRegion);
		}
	});
</script>

<LiveRegion bind:this={liveRegion} />
<slot />

2. Choose Appropriate Politeness Levels

  • Use polite (default) for most announcements:

    • Form submissions
    • Item added to cart
    • Content loaded
    • Search results updated
  • Use assertive only for critical, time-sensitive messages:

    • Fatal errors
    • Connection lost
    • Security warnings
    • Session expiration

3. Keep Messages Concise

Screen readers will read the entire message. Keep announcements brief and clear:

// Good ✅
announce('3 items added to cart');

// Avoid ❌
announce(
	'The following items have been successfully added to your shopping cart and you can now proceed to checkout if you wish: Item 1, Item 2, Item 3'
);

4. Clean Up on Route Changes

Clear pending announcements when navigating to prevent outdated messages:

<!-- src/routes/+layout.svelte -->
<script>
	import { clear } from '@pithagon/live-region';
	import { beforeNavigate } from '$app/navigation';

	beforeNavigate(() => {
		clear();
	});
</script>

5. Test with Screen Readers

Always test your announcements with actual screen readers:

  • macOS: VoiceOver
  • Windows: NVDA or JAWS
  • Mobile: VoiceOver (iOS) or TalkBack (Android)

Accessibility

This component follows ARIA live region specifications:

  • ✅ Uses aria-live="polite" and aria-live="assertive" attributes
  • ✅ Uses aria-atomic="true" to ensure complete messages are read
  • ✅ Visually hidden but accessible to assistive technologies
  • ✅ Implements message queuing to prevent dropped announcements
  • ✅ Priority-based queue (assertive messages take precedence)

Examples

See EXAMPLES.md for more detailed usage examples.

Contributing

Contributions are welcome! Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.

License

MIT © Pithagon

Related Packages