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

@a11y_craft/aria-announce

v1.0.2

Published

Tiny, zero-dependency aria-live region manager for screen reader announcements (VoiceOver, NVDA, JAWS) — works with React, Vue, Svelte, and vanilla JS

Readme

@a11y_craft/aria-announce

Tiny, zero-dependency aria-live announcer for screen readers — works with React, Vue, Svelte, Angular, and vanilla JS.

npm version bundle size license

Screen reader support: VoiceOver (macOS/iOS) · NVDA · JAWS · TalkBack (Android) · Narrator (Windows)

Framework support: React · Vue · Svelte · Angular · vanilla JS · any DOM environment

Why

aria-live regions are the standard way to make dynamic content accessible to screen reader users — but getting them right is tricky:

  • Setting text on an existing live region doesn't always re-trigger screen readers
  • Sending messages too fast causes announcements to be dropped
  • Duplicate messages within a short window create noise
  • Most existing packages are framework-specific, heavy, or abandoned

aria-announce solves all of this in ~1 KB, with no dependencies.

Install

npm install @a11y_craft/aria-announce
# or
yarn add @a11y_craft/aria-announce
# or
pnpm add @a11y_craft/aria-announce

Quick Start

import { announce } from '@a11y_craft/aria-announce';

announce('Your file has been saved.');

That's it. No setup, no providers, no configuration required.

API

announce(message, options?)

The main function. Queues a message for announcement.

announce('3 results found');
announce('Session expiring in 1 minute', { politeness: 'assertive' });

Options:

| Option | Type | Default | Description | |--------|------|---------|-------------| | politeness | 'polite' \| 'assertive' | 'polite' | Politeness level of the announcement | | delay | number (ms) | 100 | Delay before announcing — helps screen readers catch the update | | dedupeMs | number (ms) | 500 | Suppress duplicate messages within this window |

announce.polite(message)

Shorthand for polite announcements (non-interrupting).

announce.polite('Form submitted successfully.');

announce.assertive(message)

Shorthand for assertive announcements (interrupts the screen reader immediately).

announce.assertive('Error: Please fill in all required fields.');

Use assertive sparingly — it interrupts whatever the user is currently hearing.

announce.clear()

Clears the queue and empties all live regions.

announce.clear();

announce.destroy()

Removes the aria-live DOM elements entirely. Useful for cleanup in SPAs or tests.

announce.destroy();

Usage Examples

Vanilla JS

import { announce } from '@a11y_craft/aria-announce';

document.querySelector('#save-btn').addEventListener('click', async () => {
  await saveData();
  announce('Changes saved successfully.');
});

document.querySelector('#delete-btn').addEventListener('click', () => {
  announce.assertive('Item deleted.');
});

React

import { announce } from '@a11y_craft/aria-announce';

function SaveButton() {
  const handleSave = async () => {
    await save();
    announce('Draft saved.');
  };

  return <button onClick={handleSave}>Save</button>;
}

No provider needed. Works in any component, anywhere in the tree.

// In a toast/notification system
function showToast(message: string, type: 'info' | 'error') {
  if (type === 'error') {
    announce.assertive(message);
  } else {
    announce.polite(message);
  }
}

Vue

<script setup>
import { announce } from '@a11y_craft/aria-announce';

async function handleSubmit() {
  await submitForm();
  announce('Form submitted successfully.');
}
</script>

<template>
  <button @click="handleSubmit">Submit</button>
</template>

Svelte

<script>
  import { announce } from '@a11y_craft/aria-announce';

  async function handleUpload() {
    await upload();
    announce('File uploaded.');
  }
</script>

<button on:click={handleUpload}>Upload</button>

With a loading state

import { announce } from '@a11y_craft/aria-announce';

async function fetchResults(query: string) {
  announce('Loading results...');
  const results = await search(query);
  announce(`${results.length} results found for "${query}".`);
}

How It Works

On the first call, aria-announce creates two visually hidden aria-live elements in the document body — one polite, one assertive:

<div aria-live="polite" aria-atomic="true" style="...visually hidden..."></div>
<div aria-live="assertive" aria-atomic="true" style="...visually hidden..."></div>

When you call announce(), it:

  1. Checks for duplicates (suppresses repeated messages within dedupeMs)
  2. Queues the message with the chosen politeness level
  3. Clears the region, then sets the new message (forces screen readers to re-announce)
  4. Processes the queue sequentially so rapid calls don't drop announcements

Screen Reader Compatibility

aria-announce is tested and works with the major screen readers:

| Screen Reader | Platform | Notes | |---------------|----------|-------| | VoiceOver | macOS, iOS | Both polite and assertive | | NVDA | Windows | Both polite and assertive | | JAWS | Windows | Both polite and assertive | | TalkBack | Android | aria-live supported | | Narrator | Windows | Both polite and assertive |


WCAG Compliance

aria-announce is designed to align with WCAG 2.2 Success Criterion 4.1.3 (Status Messages):

  • Uses aria-live with appropriate politeness levels
  • Sets aria-atomic="true" so the full message is read, not just changed text
  • Avoids focus movement for status messages

SSR / Server-Side Rendering

aria-announce is a no-op in server environments. All calls are safely ignored when document is not available.


TypeScript

Full TypeScript support with exported types:

import { announce } from '@a11y_craft/aria-announce';
import type { AnnounceOptions, AnnounceFunction } from 'aria-announce';

const options: AnnounceOptions = {
  politeness: 'assertive',
  delay: 50,
  dedupeMs: 1000,
};

announce('Upload complete.', options);

Browser Support

Works in all modern browsers. Requires a DOM environment (not SSR).


License

MIT © Nidhi Gajera