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

announce-queue

v0.2.0

Published

Screen-reader announcements for React — an aria-live queue that paces messages, drops stale ones, and lets alerts interrupt

Readme

announce-queue

npm bundle size license

Screen-reader announcements for React, played one at a time.

Try the demo →

npm install announce-queue
import { AnnounceQueueProvider, useAnnounce } from 'announce-queue'

// once, at the root
;<AnnounceQueueProvider>{children}</AnnounceQueueProvider>

// anywhere below it
const { announce, clear } = useAnnounce()

announce('Draft saved') // waits its turn
announce('Connection lost', { priority: 'assertive' }) // interrupts
clear() // drop everything, e.g. on a route change

That is the whole surface. react >= 18 is the only peer dependency; there are no runtime ones.

What it does for you

A message holds its live region for as long as it takes to read, then the node is removed and the next one goes in — polite updates never talk over each other. Alerts skip the queue and cut off whatever polite message is being read. Bursts do not pile up: only the newest few messages survive, because an announcement read fifteen seconds late is worse than none.

It also handles the three screen-reader quirks that make hand-rolled live regions go silent: every message is a brand-new DOM node, the regions carry no aria-atomic, and a repeat of the previous text gets an invisible trailing space.

API

<AnnounceQueueProvider>

Mount it once, at the root. It renders the two visually hidden regions and owns the queue.

| Prop | Type | Default | Description | | ------------ | -------------------------------- | -------- | ----------------------------------------------------------------------------- | | clearAfter | number \| 'auto' | 'auto' | ms the node stays in the DOM. 'auto' derives it from the text (1000–6000ms) | | cooldown | number | 150 | ms of silence after a node is removed, before the next one of that priority | | maxQueue | number | 3 | pending messages kept per priority; the oldest are dropped first | | dedupe | boolean | true | drop a message identical to one still pending in the same priority | | onEvent | (event: AnnounceEvent) => void | — | observes every enqueue, skip, drop, insert and clear |

Nothing touches the DOM before the mount effect, so it is safe to render on the server. Messages announced before mount are buffered.

useAnnounce()

Returns { announce, clear }. Throws if called outside the provider. Per-call options override the provider defaults:

announce('Upload failed', {
  priority: 'assertive', // default 'polite'
  clearAfter: 2000, // or 'auto'
  cooldown: 300,
  dedupe: false,
})

clear(priority?) drops what is pending and empties the regions — pass a priority to leave the other one alone:

const { clear } = useAnnounce()
const pathname = usePathname()

useEffect(() => clear, [pathname, clear]) // stop talking about the screen the user left

Also exported

createAnnounceQueue(config) — the same engine without React: announce, clear, attach(assertiveEl, politeEl), destroy(). estimateReadingTime(message) — the number behind clearAfter: 'auto'.

Rules the queue follows

  • One message per priority is audible at a time: clearAfter + cooldown between insertions.
  • Assertive is taken first, removes any live polite node at once (its clear event carries interrupted: true), and holds the polite lane until the alert is gone.
  • Dedupe applies to the pending queue only, never to history.
  • Overflow past maxQueue drops the oldest pending message and reports it as drop.

Development

npm install
npm run demo   # the playground at demo/, wired to src/ rather than a build
npm run ci     # format, types, knip, tests, both builds

Contributions welcome — see CONTRIBUTING.md.

For coding agents: llms.txt carries the same API in a machine-readable form, ships inside the package, and is served at /llms.txt.

License

MIT