Accessible Kit

Lightweight, accessible UI component library with full ARIA support

Collection of fully accessible UI components for modern web applications. Zero dependencies, vanilla JavaScript.

Components

5 ready components (v1.0) + 6 in roadmap (v1.1+)
All components are built following WAI-ARIA Authoring Practices Guide with full keyboard navigation and screen reader support.

Dropdown Ready

Accessible dropdown with keyboard navigation for navigation menus, language switchers, and action menus.

  • ✓ ARIA attributes
  • ✓ Keyboard navigation
  • ✓ Multiple variants
  • ✓ Dark mode support

Tabs Ready

Tabs with full a11y support for organizing content into separate sections.

  • ✓ Horizontal & Vertical
  • ✓ Multiple styles
  • ✓ Disabled tabs
  • ✓ Automatic activation

Offcanvas Ready

Sliding side panel with focus trap and full a11y support for navigation and sidebars.

  • ✓ Focus trap
  • ✓ 4 positions
  • ✓ Scroll lock
  • ✓ Backdrop support

Modal Ready

Modal dialog with focus trap and proper focus management for overlay interactions.

  • ✓ Focus trap
  • ✓ Backdrop click
  • ✓ Scroll lock
  • ✓ Size variants

Collapse Ready

Standalone collapse toggle for show/hide functionality with ARIA support.

  • ✓ Standalone toggles
  • ✓ CSS selector support
  • ✓ Dynamic text
  • ✓ Multiple panels

Accordion Ready

Accessible accordion with keyboard navigation for groups of collapsible sections.

  • ✓ Single/Multiple expand
  • ✓ Keyboard navigation
  • ✓ Toggle all control
  • ✓ Dynamic text

Tooltip Coming Soon

Accessible tooltip with ARIA support and smart positioning.

  • ✓ ARIA role="tooltip"
  • ✓ Smart positioning
  • ✓ Delay support
  • ✓ ESC to close

Toast/Notification Coming Soon

Live region announcements with auto-dismiss and notification stacking.

  • ✓ aria-live regions
  • ✓ Auto-dismiss timer
  • ✓ Stacking support
  • ✓ Multiple positions

Toggle Switch Coming Soon

Switch component with localStorage/preferences support and ARIA attributes.

  • ✓ role="switch"
  • ✓ localStorage support
  • ✓ Smooth animations
  • ✓ Labels & descriptions

Popover Coming Soon

Interactive popover with positioning and focus management for rich content.

  • ✓ Interactive content
  • ✓ Smart positioning
  • ✓ Focus management
  • ✓ Close on outside click

Alert/Banner Coming Soon

ARIA alert component with dismissible support and various message types.

  • ✓ role="alert"
  • ✓ Dismissible/Persistent
  • ✓ Info/Warning/Error
  • ✓ Icon support

Combobox/Autocomplete Coming Soon

Complex ARIA pattern for search, autocomplete, and filtering with keyboard navigation.

  • ✓ role="combobox"
  • ✓ Search & filter
  • ✓ Keyboard navigation
  • ✓ Highlight matches

Key Features

Fully Accessible

All components follow WAI-ARIA standards

⌨️

Keyboard Navigation

Complete keyboard navigation support

🎨

Customizable

Separated core and theme CSS for easy customization

📦

Zero Dependencies

Vanilla JavaScript without external libraries

📱

Responsive

Works on all devices and screen sizes

🌙

Dark Mode

Automatic dark mode support

Quick Start

1. Add CSS Files

<!-- Core CSS (logic) -->
<link rel="stylesheet" href="css/a11y-dropdown.core.css">
<link rel="stylesheet" href="css/a11y-tabs.core.css">
<link rel="stylesheet" href="css/a11y-offcanvas.core.css">
<link rel="stylesheet" href="css/a11y-modal.core.css">
<link rel="stylesheet" href="css/a11y-accordion.core.css">

<!-- Theme CSS (visual) -->
<link rel="stylesheet" href="css/a11y-dropdown.theme.css">
<link rel="stylesheet" href="css/a11y-tabs.theme.css">
<link rel="stylesheet" href="css/a11y-offcanvas.theme.css">
<link rel="stylesheet" href="css/a11y-modal.theme.css">
<link rel="stylesheet" href="css/a11y-accordion.theme.css">

2. Add JavaScript

<script src="js/a11y-dropdown.js"></script>
<script src="js/a11y-tabs.js"></script>
<script src="js/a11y-offcanvas.js"></script>
<script src="js/a11y-modal.js"></script>
<script src="js/a11y-accordion.js"></script>

3. Use in HTML

<!-- Dropdown -->
<div data-dropdown>
    <button data-dropdown-button>
        Options
        <span class="dropdown__arrow"></span>
    </button>
    <div data-dropdown-menu>
        <button data-dropdown-item>Item 1</button>
        <button data-dropdown-item>Item 2</button>
    </div>
</div>

<!-- Tabs -->
<div data-tabs>
    <div role="tablist" data-tabs-list>
        <button data-tabs-tab>Tab 1</button>
        <button data-tabs-tab>Tab 2</button>
    </div>
    <div data-tabs-panel>Content 1</div>
    <div data-tabs-panel>Content 2</div>
</div>

<!-- Offcanvas -->
<button data-offcanvas-trigger="menu">☰ Menu</button>
<div data-offcanvas id="menu">
    <div data-position="left" data-offcanvas-panel>
        <div data-offcanvas-header>
            <h2 data-offcanvas-title>Menu</h2>
            <button data-offcanvas-close>×</button>
        </div>
        <div data-offcanvas-body>Content...</div>
    </div>
    <div data-offcanvas-backdrop></div>
</div>

<!-- Modal -->
<button data-modal-trigger="my-modal">Open Modal</button>
<div data-modal id="my-modal">
    <div data-modal-dialog>
        <div data-modal-header>
            <h2 data-modal-title>Title</h2>
            <button data-modal-close>×</button>
        </div>
        <div data-modal-body>Content...</div>
        <div data-modal-footer>
            <button data-modal-close>Close</button>
        </div>
    </div>
    <div data-modal-backdrop></div>
</div>

<!-- Accordion -->
<div data-accordion>
    <div data-accordion-item>
        <button data-accordion-trigger>Section 1</button>
        <div data-accordion-panel>Content 1</div>
    </div>
    <div data-accordion-item>
        <button data-accordion-trigger>Section 2</button>
        <div data-accordion-panel>Content 2</div>
    </div>
</div>

Initialization and Import

Accessible Kit supports multiple initialization methods according to your needs: automatic initialization via CDN, manual initialization with callbacks, and ES6 import for module bundlers (Astro, Vite, Webpack).

1. Auto-initialization (CDN / direct files)

When using via <script> tag, components initialize automatically:

<script src="js/a11y-dropdown.js"></script>
<!-- Dropdown automatically initializes after DOM loads -->

2. CDN with window.a11yKit namespace (recommended)

<script src="js/a11y-dropdown.js"></script>
<script src="js/a11y-tabs.js"></script>
<!-- Or all at once: -->
<script src="js/index.js"></script>

<script>
  // Via global namespace (recommended - no collisions)
  a11yKit.initAll(); // initializes all components

  // Or individually
  a11yKit.initDropdowns();
  a11yKit.initTabs();
  a11yKit.initCollapses();
  a11yKit.initAccordions();

  // Bootstrap style - short aliases
  const dropdown = new a11yKit.Dropdown(element, options);
  const modal = new a11yKit.Modal(element, options);
  const collapse = new a11yKit.Collapse();
  const accordion = new a11yKit.Accordion();
</script>

3. Manual initialization (with disabled auto-init)

<script>
  window.a11yKitManualInit = true;
</script>
<script src="js/a11y-dropdown.js"></script>
<script>
  // Via namespace (recommended)
  a11yKit.initDropdowns();

  // Or directly (backwards compatible)
  initDropdowns();
</script>

4. ES6 Module Import (Astro, Vite, Webpack)

Named import - init functions

import { initDropdowns } from './a11y-kit/a11y-dropdown.js';
import { initTabs } from './a11y-kit/a11y-tabs.js';

initDropdowns();
initTabs();

Named import - Bootstrap style (short aliases)

import { Dropdown, Modal, Tabs, Collapse, Accordion } from './a11y-kit/index.js';

// Use like Bootstrap
const dropdown = new Dropdown(element, {
  closeOnSelect: true,
  onOpen: (instance) => { console.log('Opened!'); }
});

const collapse = new Collapse();
const accordion = new Accordion();

Wildcard import

import * as a11yKit from './a11y-kit/index.js';

// Init functions:
a11yKit.initAll();
a11yKit.initDropdowns();
a11yKit.initCollapses();
a11yKit.initAccordions();

// Bootstrap style:
const dropdown = new a11yKit.Dropdown(element, options);
const modal = new a11yKit.Modal(element, options);
const collapse = new a11yKit.Collapse();
const accordion = new a11yKit.Accordion();

Example for Astro

// src/layouts/Layout.astro
<script>
  // Variant 1: Named imports
  import { initDropdowns } from '/src/assets/js/a11y-kit/a11y-dropdown.js';
  import { initTabs } from '/src/assets/js/a11y-kit/a11y-tabs.js';

  initDropdowns();
  initTabs();
</script>

<!-- OR -->

<script>
  // Variant 2: Wildcard import
  import * as a11yKit from '/src/assets/js/a11y-kit';

  a11yKit.initAll(); // all at once
</script>

Manual initialization with callbacks

import { AccessibleDropdown } from './a11y-kit/a11y-dropdown.js';

const dropdown = new AccessibleDropdown(element, {
  closeOnSelect: true,
  onOpen: (instance) => {
    console.log('Opened!');
  },
  onClose: (instance) => {
    console.log('Closed!');
  },
  onSelect: (item, index) => {
    console.log('Selected item:', item.textContent);
  }
});

NPM package import

// Installation
npm install accessible-kit

// Import
import { initAll } from 'accessible-kit';
initAll();

// Or wildcard
import * as a11yKit from 'accessible-kit';
a11yKit.initDropdowns();

// Or individual components (tree-shaking)
import { initDropdowns } from 'accessible-kit/dropdown';
import { initTabs } from 'accessible-kit/tabs';
initDropdowns();
initTabs();

💡 Note about .js extensions

  • With extension (./a11y-kit/a11y-dropdown.js) - always works, clear and explicit
  • Without extension (./a11y-kit/a11y-dropdown) - works in most modern bundlers
  • Shorter paths (./a11y-kit) - works if you have index.js

Which method to use?

Documentation

Detailed documentation for each component can be found in the README.md file or on the demo pages of individual components.

View on GitHub or check the Contributing Guide.