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

@get-set/gs-accordion

v1.0.4

Published

Get-Set Accordion

Readme

GSAccordion

A dependency-free, fully accessible accordion / collapse component that ships in four interchangeable flavours from a single codebase:

  1. a window factorywindow.GSAccordion(selectorOrElement, params)
  2. a jQuery plugin$(selector).GSAccordion(params)
  3. an HTMLElement prototype method — element.GSAccordion(params)
  4. a React component<GSAccordion> with a typed imperative ref

All four share the same actions/, constants/, helpers/ and types/ — so behaviour, animation and accessibility are identical across every target.

Features

  • Two modessingle (one open at a time) or multiple (independent).
  • Collapsible — allow all panels closed in single mode (or force one open).
  • Beautiful animation — smooth height-slide + fade with configurable animationDuration / animationEasing; honors prefers-reduced-motion.
  • Indicator iconschevron, plus (morphs to minus), caret, or a fully custom HTML glyph, positioned left or right (RTL-aware), with an optional rotate/morph animation.
  • Five variantsbordered, separated, filled, ghost, flush.
  • Per-item disabled.
  • Theminglight / dark / auto (follows prefers-color-scheme) plus a custom accentColor.
  • Sizessm / md / lg.
  • RTL layout.
  • Full keyboard support — Arrow Up/Down (+ Left/Right, RTL-aware), Home, End, Enter, Space, per the WAI-ARIA accordion pattern.
  • Full ARIA — header buttons carry aria-expanded + aria-controls; panels are role="region" labelled by their header.
  • CallbacksbeforeToggle (cancelable), onChange, onOpen, onClose.
  • Items two ways — author them as markup (header + panel per item) or as a config array.
  • React-only gsx — per-instance scoped styles.

Installation

npm i @get-set/gs-accordion

Package entry points

| Environment | Resolves to | What you get | | ------------------------ | ----------------------- | ---------------------------------------------- | | import ... from | dist/components/… | The React component + named exports + types | | require(...) / <script> | dist-js/bundle.js | window.GSAccordion + jQuery + prototype |

The bundled dist-js/bundle.js self-registers all three native flavours: it assigns window.GSAccordion, and (when jQuery is present) $.fn.GSAccordion, plus HTMLElement.prototype.GSAccordion.

Project layout

GSAccordion/
├─ GSAccordion.ts              # window factory entry (native)
├─ actions/                    # init, toggle, keyboard, animate, refresh, destroy
├─ constants/                  # defaultParams, sizes
├─ helpers/                    # layout, icons, uihelpers
├─ types/                      # params, ref, global.d.ts
├─ components/
│  ├─ GSAccordion.tsx          # React component
│  └─ styles/                  # GSAccordion.css/.scss + GSAccordionCSS.ts
├─ styles/                     # GSAccordion.css/.scss (published)
└─ example.html                # native showcase

Build

npm run build        # build:js (webpack bundle) + build:react (tsc declarations)

Tests

npm test             # vitest (logic + native registry + React render/handle/gsx)

Usage — Native JS (window factory)

The factory accepts either a CSS selector string or a DOM element as its first argument:

// by selector
const acc = window.GSAccordion('#faq', {
  mode: 'single',
  defaultOpen: 0,
  variant: 'bordered',
  icon: 'chevron'
});

// by element (identical result)
const el = document.getElementById('faq');
window.GSAccordion(el, { mode: 'multiple' });

Markup form

Each direct child of the container is an item. Within it, the header can be a [data-gs-accordion-header], a .gs-accordion-header, or the first heading / button; the panel is [data-gs-accordion-panel], a .gs-accordion-panel, or everything after the header.

<div id="faq">
  <div>
    <button data-gs-accordion-header>Question one</button>
    <div data-gs-accordion-panel>Answer one.</div>
  </div>
  <div data-disabled="true">
    <button data-gs-accordion-header>Coming soon</button>
    <div data-gs-accordion-panel>Not yet.</div>
  </div>
</div>

Config-array form

Pass items and the plugin renders the markup for you:

window.GSAccordion('#features', {
  mode: 'multiple',
  variant: 'separated',
  icon: 'plus',
  iconPosition: 'left',
  defaultOpen: ['perf'],
  items: [
    { key: 'perf', header: 'Performant', panel: '<p>Tiny + fast.</p>' },
    { key: 'themed', header: 'Themeable', panel: '<p>Light/dark/auto.</p>' },
    { key: 'gone', header: 'Legacy', panel: '<p>…</p>', disabled: true }
  ]
});

The instance registry — window.GSAccordionConfigue

Every native instance registers under its reference (auto-generated if omitted). Retrieve it anywhere:

window.GSAccordion('#faq', { reference: 'faq' });

const acc = window.GSAccordionConfigue.instance('faq');
acc.open(1);          // open the second item (by index)
acc.toggle('perf');   // toggle by key
acc.getOpen();        // -> ['perf']

Native instance methods: open, close, toggle, openAll, closeAll, getOpen, isOpen, refresh, destroy.

acc.open();           // open (respects mode: single opens the first)
acc.open(0);          // open by index
acc.open(['a', 'b']); // open multiple by key
acc.close(1);         // close by index/key
acc.close();          // close all
acc.toggle('a');
acc.openAll();        // expand every item (multiple mode)
acc.closeAll();
acc.getOpen();        // string[] of open keys
acc.isOpen('a');      // boolean
acc.refresh();        // rebuild from params, preserving open state
acc.destroy();        // remove listeners + ARIA, free the registry slot

Usage — jQuery

<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script src="node_modules/@get-set/gs-accordion/dist-js/bundle.js"></script>
<script>
  $('#faq').GSAccordion({ mode: 'single', icon: 'caret' });
</script>

Internally the jQuery adapter passes the element to window.GSAccordion, so it shares the exact same engine.

Usage — HTMLElement prototype

document.querySelector('#faq').GSAccordion({
  variant: 'filled',
  accentColor: '#7c3aed'
});

Usage — React

import GSAccordion, {
  GSAccordionItem,
  GSAccordionHandle
} from '@get-set/gs-accordion';

function FAQ() {
  const ref = React.useRef<GSAccordionHandle>(null);

  return (
    <>
      <button onClick={() => ref.current?.openAll()}>Expand all</button>

      <GSAccordion ref={ref} mode="multiple" variant="separated" icon="plus">
        <GSAccordionItem itemKey="a" header="What is it?">
          A four-in-one accordion.
        </GSAccordionItem>
        <GSAccordionItem itemKey="b" header="Accessible?">
          Fully — ARIA + keyboard.
        </GSAccordionItem>
        <GSAccordionItem itemKey="c" header="Coming soon" disabled>
          Not yet.
        </GSAccordionItem>
      </GSAccordion>
    </>
  );
}

Config-array in React

<GSAccordion
  mode="single"
  defaultOpen={0}
  items={[
    { key: 'a', header: 'One', panel: '<p>Body one</p>' },
    { key: 'b', header: 'Two', panel: '<p>Body two</p>' }
  ]}
/>

The imperative handle — GSAccordionHandle

| Method | Description | | -------------------------- | ----------------------------------------------------- | | open(key?) | Open item(s) by index/key. Omit to open (per mode). | | close(key?) | Close item(s) by index/key. Omit to close all. | | toggle(key) | Toggle the item by index/key. | | openAll() | Expand every item (multiple mode). | | closeAll() | Collapse every item. | | getOpen() | string[] of the currently-open item keys. | | isOpen(key) | Whether the given item is open. | | refresh() | Re-measure open panels (after content changes). | | destroy() | Unregister the instance from the global registry. |

Controlled vs uncontrolled

  • Uncontrolled — use defaultOpen and let the component manage state.
  • Controlled — pass openKeys (an array of keys) and drive it yourself; the callbacks tell you what the user attempted.

The gsx prop (React only)

Inject per-instance scoped CSS. It is written under [data-key='<reference>'] on mount and removed on unmount:

<GSAccordion
  reference="pricing"
  gsx={{
    '.gs-accordion-header': { fontWeight: '700' },
    '.gs-accordion-item-open': { background: '#eef2ff' }
  }}
>
  …
</GSAccordion>

Options

Every option is optional. Defaults are shown.

| Option | Type | Default | Description | | ------------------- | ---------------------------------------------------------- | ------------------------------ | -------------------------------------------------------------------------- | | reference | string | auto GUID | Registry key for the instance. | | items | GSAccordionItem[] | — | Config-array items (else read from markup / children). | | mode | 'single' \| 'multiple' | 'single' | One open at a time, or independent. | | defaultOpen | string \| number \| Array<string \| number> | — | Items open on init (by index or key). Uncontrolled. | | openKeys | Array<string \| number> (React only) | — | Controlled open keys. | | collapsible | boolean | true | Single mode: allow all closed. false forces one open. | | animation | boolean | true | Height-slide + fade. false disables motion. | | animationDuration | number (ms) | 300 | Slide duration. | | animationEasing | string | cubic-bezier(.4,0,.2,1) | CSS easing for the slide. | | reducedMotion | 'auto' \| boolean | 'auto' | auto follows the OS; true always reduces; false never. | | icon | 'chevron' \| 'plus' \| 'caret' \| 'custom' \| false | 'chevron' | Header indicator glyph. false hides it. | | iconPosition | 'left' \| 'right' | 'right' | Which side the icon sits on (RTL-aware). | | iconRotate | boolean | true | Rotate/morph the icon when its item opens. | | customIcon | string (HTML) | — | Glyph used when icon: 'custom' (per-item icon overrides it). | | variant | 'bordered' \| 'separated' \| 'filled' \| 'ghost' \| 'flush' | 'bordered' | Visual shell style. | | size | 'sm' \| 'md' \| 'lg' | 'md' | Padding + font-size preset. | | theme | 'light' \| 'dark' \| 'auto' | 'auto' | auto follows prefers-color-scheme. | | accentColor | string | #2563eb | Accent (open icon, focus ring, highlights) — CSS var --gsa-accent. | | rtl | boolean | false | Right-to-left layout. | | className | string | — | Extra class on the root. | | gsx | NestedCSS (React only) | — | Per-instance scoped styles. | | beforeToggle | (e) => void \| boolean | — | Fired before a toggle. Return false to cancel. | | onChange | (openKeys: string[], e) => void | — | Fired after any open-state change. | | onOpen | (key: string, index: number) => void | — | Fired when an item opens. | | onClose | (key: string, index: number) => void | — | Fired when an item closes. |

GSAccordionItem (config array)

| Field | Type | Description | | ---------- | --------- | ------------------------------------------------- | | key | string | Stable key (falls back to the index). | | header | string | Header label (HTML allowed). | | panel | string | Panel body (HTML allowed). | | disabled | boolean | Disable the item. | | open | boolean | Open on init (merged with defaultOpen). | | icon | string | Per-item custom icon HTML (with icon: 'custom').|

GSAccordionToggleEvent (callback payload)

| Field | Type | Description | | --------- | ------------- | -------------------------------------- | | key | string | The item key. | | index | number | The item index. | | header | HTMLElement | The header button element. | | panel | HTMLElement | The panel region element. | | willOpen| boolean | true if opening, false if closing. |


Variant catalog

Every value of variant:

| Variant | Look | | ----------- | ---------------------------------------------------------------- | | bordered | Single rounded outline; items divided by hairlines. (default) | | separated | Each item is its own rounded card with a gap; open card lifts. | | filled | Each item is a soft-filled rounded block; open tint uses accent. | | ghost | Borderless; only hairline dividers, accent on hover. | | flush | Edge-to-edge, bottom-bordered rows with no side padding. |

Icon catalog

Every value of icon:

| Icon | Behaviour | | --------- | ------------------------------------------------------------ | | chevron | Down chevron; rotates 180° when open. (default) | | caret | Solid triangle; rotates 180° when open. | | plus | Plus sign; the vertical stroke collapses into a minus. | | custom | Your own HTML (customIcon or the per-item icon). | | false | No indicator. |

Size catalog

| Size | Header padding | Font size | | ---- | -------------- | --------- | | sm | 10 × 12 px | 13 px | | md | 14 × 16 px | 15 px | | lg | 18 × 20 px | 17 px |

Theme catalog

| Theme | Behaviour | | ------- | ----------------------------------------------- | | light | Always light surface. | | dark | Always dark surface. | | auto | Follows prefers-color-scheme. (default) |


Keyboard & accessibility

| Key | Action | | -------------------------------- | ------------------------------------------ | | Enter / Space | Toggle the focused item. | | Arrow Down / Arrow Right* | Focus the next header (wraps). | | Arrow Up / Arrow Left* | Focus the previous header (wraps). | | Home | Focus the first header. | | End | Focus the last header. |

* Left/Right are mirrored under rtl: true.

Each header exposes aria-expanded and aria-controls; each panel is role="region" labelled by its header via aria-labelledby. Disabled items get aria-disabled="true" and are skipped by roving focus.


Examples

Native — FAQ, single mode, first item open

window.GSAccordion('#faq', { mode: 'single', defaultOpen: 0 });

Native — separated cards, multiple, plus icon (element arg)

const acc = window.GSAccordion(document.getElementById('features'), {
  mode: 'multiple',
  variant: 'separated',
  icon: 'plus',
  iconPosition: 'left',
  items: [
    { key: 'a', header: 'Fast', panel: '<p>Tiny.</p>' },
    { key: 'b', header: 'Themed', panel: '<p>Dark mode.</p>' }
  ]
});
acc.openAll();

React — controlled, dark theme, custom accent

function Controlled() {
  const [open, setOpen] = React.useState<string[]>(['a']);
  return (
    <GSAccordion
      mode="multiple"
      theme="dark"
      accentColor="#22d3ee"
      openKeys={open}
      onChange={(keys) => setOpen(keys)}
    >
      <GSAccordionItem itemKey="a" header="Alpha">A</GSAccordionItem>
      <GSAccordionItem itemKey="b" header="Beta">B</GSAccordionItem>
    </GSAccordion>
  );
}

React — cancelable toggle with beforeToggle

<GSAccordion
  beforeToggle={(e) => {
    if (e.key === 'locked' && e.willOpen) {
      return false; // veto opening this item
    }
  }}
>
  …
</GSAccordion>

License

ISC © Get-Set