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

@19h47/accordion

v9.1.0

Published

Accordion

Readme

Ask DeepWiki

@19h47/accordion

Sur un petit air d'accordéon Léon

Accessible accordion for the modern web. Panels are resolved through ariaControlsElements (Baseline 2025), with keyboard support aligned to the WAI-ARIA Accordion pattern.

Requirements

Installation

pnpm add @19h47/accordion

Also works with npm / yarn / bun.

Usage

import Accordion from '@19h47/accordion';

const element = document.querySelector('.js-accordion');
const accordion = new Accordion(element);

accordion.init();
<div class="js-accordion">
	<div
		class="js-accordion-panel"
		data-accordion-open="true"
		data-accordion-deselect="true"
	>
		<h3>
			<button
				class="js-accordion-header"
				type="button"
				id="lorem-header"
				aria-expanded="true"
				aria-controls="lorem-body"
			>
				Toggle
			</button>
		</h3>

		<div id="lorem-body" role="region" aria-labelledby="lorem-header">
			<div class="js-accordion-inner">
				Panel content
			</div>
		</div>
	</div>
</div>

The header keeps an aria-controls IDREF in markup. At runtime, the library resolves the panel via ariaControlsElements.

Wrap each header control in a heading (<h2><h6>, or nested deeper levels as needed). The library does not inject or enforce this — clean document outline is up to you.

Header: <button> vs <a>

Both work as .js-accordion-header. Choose based on intent:

| | <button type="button"> | <a href="#panel-id"> | | --- | --- | --- | | Role | Toggle control (APG default) | Link + deep link to the panel | | Activation | Click, Enter, Space | Click / Enter (native link) | | URL hash | Optional, via your own logic | Native (href + browser history) | | Best for | In-page accordion only | Shareable / bookmarkable panels |

Use <button> when the header only expands or collapses. Use <a href="#…"> when the panel id should also be a real document fragment.

For deep links, point href at the panel root (.js-accordion-panel, always in the layout), not the collapsible region. A fragment on a hidden / zero-height body makes the browser scroll to the wrong place.

Markup checklist

| Selector / attribute | Role | | --- | --- | | .js-accordion | Root container | | .js-accordion-panel | One panel (direct child of the root) | | heading (h2h6) | Wraps the header control (consumer markup; not enforced by the library) | | .js-accordion-header | Toggle control (<button> or <a>), sole child of the heading | | aria-controls | Points to the panel region id | | .js-accordion-inner | Measured content used for height animation | | role="region" + aria-labelledby | Accessible name for the panel landmark |

Options

Constructor

const accordion = new Accordion(element, {
	multiselectable: false, // allow several panels open at once
});

| Option | Type | Default | Description | | --- | --- | --- | --- | | multiselectable | boolean | false | When false, opening a panel closes the others |

You can also set data-accordion-multiselectable="true" on the root in demos; pass the parsed value into the constructor as above.

Panel data attributes

Set these on .js-accordion-panel:

<div
	class="js-accordion-panel"
	data-accordion-open="true"
	data-accordion-deselect="true"
>
	…
</div>

| Attribute | Description | | --- | --- | | data-accordion-open | Initial open state ("true" / "false") | | data-accordion-deselect | When "true", an open panel can be collapsed again by its header |

Events

import Accordion from '@19h47/accordion';

const accordion = new Accordion(document.querySelector('.js-accordion'));
accordion.init();

for (const panel of accordion.panels) {
	panel.el.addEventListener('Panel.open', ({ detail }) => {
		console.log('opened', detail.current);
	});

	panel.el.addEventListener('Panel.close', ({ detail }) => {
		console.log('closed', detail.current);
	});
}

detail.current is the .js-accordion-panel element.

Keyboard support

| Key | Behavior | | --- | --- | | Space / Enter | Expand or collapse the focused header | | Tab / Shift+Tab | Move through focusable elements in page order | | / | Next header (wraps) | | / | Previous header (wraps) | | Home | First header | | End | Last header |

Accessibility

| Role / attribute | Element | Notes | | --- | --- | --- | | aria-controls | header | IDREF to the panel region; reflected as ariaControlsElements | | aria-expanded | header | Updated on open / close | | aria-disabled | header | Set to "true" when the panel is open and data-accordion-deselect="false" | | role="region" | panel body | Landmark for the expandable content | | aria-labelledby | panel body | References the header id |

Development

pnpm install
pnpm dev      # Vite playground
pnpm build    # library build → dist/

Demo

Live example: 19h47.github.io/19h47-accordion · source

Acknowledgments