accessible-kit
v1.0.9
Published
Lightweight, accessible UI component library with full ARIA support. Zero dependencies, vanilla JavaScript.
Downloads
219
Maintainers
Readme
Accessible Kit
Lightweight, accessible UI component library with full ARIA support. Zero dependencies, vanilla JavaScript.
A collection of fully accessible UI components for modern web applications. Built with a focus on keyboard navigation, screen reader support, and following WAI-ARIA best practices.
✨ Features
- 🎯 Fully Accessible - Complete ARIA support and keyboard navigation
- 🪶 Lightweight - Zero dependencies, vanilla JavaScript
- 🎨 Customizable - Separated core/theme CSS for easy theming
- 📱 Responsive - Mobile-first design approach
- 🌙 Dark Mode - Built-in dark mode support
- ♿ Inclusive - High contrast mode and reduced motion support
- 🔧 Framework Agnostic - Works with any framework or vanilla JS
- 📦 Tree-shakeable - Import only what you need
- ⌨️ Focus Visible - Uses
:focus-visiblefor better keyboard navigation UX
📚 Table of Contents
🎭 Demo
View live examples at: https://5ulo.github.io/accessible-kit/
📦 Installation
NPM
npm install accessible-kitYarn
yarn add accessible-kitCDN (ES Modules)
<!-- Individual component with manual initialization -->
<script type="module">
import { initDropdowns } from 'https://unpkg.com/accessible-kit/src/js/a11y-dropdown.js';
document.addEventListener('DOMContentLoaded', () => {
initDropdowns();
});
</script>
<link rel="stylesheet" href="https://unpkg.com/accessible-kit/src/css/a11y-dropdown.core.css">
<link rel="stylesheet" href="https://unpkg.com/accessible-kit/src/css/a11y-dropdown.theme.css">🚀 Quick Start
Using ES Modules (Recommended for Modern Browsers)
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://unpkg.com/accessible-kit/src/css/a11y-dropdown.core.css">
<link rel="stylesheet" href="https://unpkg.com/accessible-kit/src/css/a11y-dropdown.theme.css">
</head>
<body>
<div data-dropdown>
<button data-dropdown-button>
Options
<span data-dropdown-arrow></span>
</button>
<div data-dropdown-menu>
<div>
<div>
<button data-dropdown-item>Edit</button>
<button data-dropdown-item>Delete</button>
</div>
</div>
</div>
</div>
<script type="module">
import { initDropdowns } from 'https://unpkg.com/accessible-kit/src/js/a11y-dropdown.js';
document.addEventListener('DOMContentLoaded', () => {
initDropdowns();
});
</script>
</body>
</html>Using NPM/Modules
// Import specific components (best for tree-shaking)
import { initDropdowns } from 'accessible-kit/dropdown';
import { initTabs } from 'accessible-kit/tabs';
// Import styles
import 'accessible-kit/styles/dropdown-core';
import 'accessible-kit/styles/dropdown-theme';
// Initialize after DOM is ready
document.addEventListener('DOMContentLoaded', () => {
initDropdowns();
initTabs();
});
// Or import all components
import { initAll } from 'accessible-kit';
document.addEventListener('DOMContentLoaded', () => {
initAll();
});Module Imports (ES6+)
import { AccessibleDropdown } from 'accessible-kit/dropdown';
const dropdown = new AccessibleDropdown(element, {
closeOnSelect: true,
onOpen: () => console.log('Opened'),
onClose: () => console.log('Closed')
});🧩 Components
Available Components (v1.0)
- ✅ Dropdown - Accessible dropdown menus with keyboard navigation
- ✅ Tabs - Tab panels following WAI-ARIA Tabs Pattern
- ✅ Accordion - Expandable sections with keyboard support
- ✅ Collapse - Standalone collapsible panels
- ✅ Modal - Accessible dialogs with focus trap
- ✅ Offcanvas - Slide-out side panels with focus management
Roadmap (v1.1+)
- 🔜 Tooltip - Accessible tooltips with positioning
- 🔜 Toast/Notification - Live region announcements
- 🔜 Toggle Switch - Accessible switch component
- 🔜 Popover - Interactive popovers
- 🔜 Alert/Banner - Dismissible alert messages
- 🔜 Combobox/Autocomplete - Searchable select component
Dropdown
Fully accessible dropdown component with keyboard navigation and ARIA support. Supports multiple ARIA patterns (menu, dialog, listbox) for different use cases.
Features
- ✅ Full ARIA attributes support (menu, navigation, dialog, and listbox patterns)
- ✅ Flexible role patterns via
data-dropdown-roleattribute - ✅ Keyboard navigation (arrows, Enter, Space, Esc, Home, End)
- ✅ Focus management
- ✅ Auto-close on outside click
- ✅ CSS Grid animations by default
- ✅ Multiple variants (nav, language switcher)
- ✅ Automatic
prefers-reduced-motionsupport
Installation
<!-- CSS -->
<link rel="stylesheet" href="css/a11y-dropdown.core.css">
<link rel="stylesheet" href="css/a11y-dropdown.theme.css">
<!-- JavaScript -->
<script src="js/a11y-dropdown.js"></script>Basic Usage
<div data-dropdown>
<button data-dropdown-button>
Options
<span data-dropdown-arrow></span>
</button>
<div data-dropdown-menu>
<!-- Two wrapper divs required for animations -->
<div>
<div>
<button data-dropdown-item>Edit</button>
<button data-dropdown-item>Duplicate</button>
<hr data-dropdown-divider>
<button data-dropdown-item>Delete</button>
</div>
</div>
</div>
</div>ARIA Patterns
The dropdown component supports multiple ARIA patterns to match different use cases. By default, it uses the menu pattern, but you can change this using the data-dropdown-role attribute.
When to Use Each Pattern
Menu Pattern (default) - Use role="menu" for:
- Action menus (Edit, Delete, etc.)
- User profile menus (button items)
- Context menus (button items)
Navigation Pattern - Use data-dropdown-role="navigation" for:
- Language/region switchers
- Navigation dropdowns containing
<a>links - Any disclosure widget where native
<nav>landmark and link semantics must be preserved
Dialog Pattern - Use data-dropdown-role="dialog" for:
- Media player playlists/controls
- Complex interactive widgets
- Custom form controls
- Rich content with multiple focusable elements
- Non-menu disclosure patterns
Example: Dialog Pattern (Radio Playlist)
<!-- Use data-dropdown-role="dialog" for playlists, controls, or interactive widgets -->
<div data-dropdown data-dropdown-role="dialog">
<button data-dropdown-button>
🎵 Playlist
<span data-dropdown-arrow></span>
</button>
<div data-dropdown-menu>
<div>
<div>
<button data-dropdown-item>Station 1</button>
<button data-dropdown-item>Station 2</button>
<button data-dropdown-item>Station 3</button>
</div>
</div>
</div>
</div>
<!-- This automatically sets:
- Button: aria-haspopup="dialog" (instead of "true")
- Menu: role="dialog" (instead of "menu")
- Items: No role attribute (instead of "menuitem")
- Keyboard: Tab allowed within dropdown (menu pattern closes on Tab)
-->Why use dialog pattern? When your dropdown contains complex interactive content (like a media player playlist), it's not semantically a "menu" of commands. The dialog pattern better represents this content structure and provides more appropriate keyboard behavior. Tab/Shift+Tab cycles through items within the dropdown (instead of closing it like menu pattern does).
Example: Navigation Pattern (Language Switcher)
<!-- Use data-dropdown-role="navigation" for language switchers and nav menus with links -->
<div data-dropdown data-dropdown-role="navigation">
<button data-dropdown-button aria-label="Výber jazyka">
🇬🇧 English
<span data-dropdown-arrow></span>
</button>
<nav data-dropdown-menu aria-label="Výber jazyka">
<div>
<div>
<ul style="list-style: none; margin: 0; padding: 0;">
<li><a href="/en" hreflang="en" lang="en" data-dropdown-item aria-current="page">English</a></li>
<li><a href="/sk" hreflang="sk" lang="sk" data-dropdown-item>Slovensky</a></li>
</ul>
</div>
</div>
</nav>
</div>
<!-- This automatically sets:
- Button: aria-expanded + aria-controls only (no aria-haspopup)
- Menu: no role override (preserves native <nav> landmark)
- Items: no role override (preserves native <a> link semantics)
- Keyboard: Arrow keys navigate, Tab closes (same as menu pattern)
-->Why use navigation pattern?
Language switchers and nav dropdowns contain <a> links, not menu commands. The role="menu" + role="menuitem" pattern is semantically incorrect for links — it hides the native link semantics from screen readers. The navigation pattern keeps the <nav> landmark and <a> link roles intact, allowing users to understand they're navigating, not executing commands.
JavaScript Initialization
import { initDropdowns, Dropdown } from 'accessible-kit/dropdown';
// Initialize all dropdowns
document.addEventListener('DOMContentLoaded', () => {
initDropdowns();
});
// Or manual initialization with options
const dropdown = new Dropdown(element, {
dropdownRole: 'menu', // 'menu' (default), 'dialog', 'listbox', or 'navigation'
closeOnSelect: true,
closeOnOutsideClick: true,
closeOnEscape: true,
hoverDelay: 0,
onOpen: (dropdown) => {},
onClose: (dropdown) => {},
onSelect: (item, index) => {}
});Animations
Dropdowns have CSS Grid animations enabled by default. The animation automatically respects prefers-reduced-motion user preferences.
Customizing animation speed:
<!-- Inline via style attribute -->
<div data-dropdown style="--a11y-dropdown-duration: 0.5s;">
<!-- dropdown content -->
</div>/* Or globally in CSS */
:root {
--a11y-dropdown-duration: 0.3s;
--a11y-dropdown-easing: ease-in-out;
}Disable animations:
<div data-dropdown-menu data-no-animation>
<!-- menu without animations -->
</div>Configuration
Data attributes:
<!-- Use dialog pattern for non-menu content -->
<div data-dropdown data-dropdown-role="dialog">
<!-- Keep dropdown open after selection -->
<div data-dropdown data-close-on-select="false">
<!-- Disable close on outside click -->
<div data-dropdown data-close-on-outside-click="false">
<!-- Hover delay (ms) -->
<div data-dropdown data-hover-delay="200">JavaScript options:
{
dropdownRole: 'menu', // ARIA pattern: 'menu', 'dialog', 'listbox', or 'navigation'
closeOnSelect: true, // Close after selecting item
closeOnOutsideClick: true, // Close on outside click
closeOnEscape: true, // Close on Escape key
hoverDelay: 0, // Hover delay in ms
onOpen: (dropdown) => {}, // Callback on open
onClose: (dropdown) => {}, // Callback on close
onSelect: (item, index) => {} // Callback on item select
}Keyboard Navigation
Menu Pattern (default):
- Enter / Space - Open/close menu or select item
- ↓ / ↑ - Navigate between items
- Home / End - Jump to first/last item
- Esc - Close menu and return focus to button
- Tab - Close menu and move focus
Dialog Pattern:
- Enter / Space - Open/close or select item
- ↓ / ↑ - Navigate between items
- Esc - Close and return focus to button
- Tab / Shift+Tab - Cycle through items within dialog (does not close)
Navigation Pattern:
- ↓ / ↑ - Navigate between links
- Home / End - Jump to first/last link
- Esc - Close and return focus to button
- Tab - Close and move focus
- Enter - Follow link (native browser behavior)
Variants
Navigation menu:
<div data-dropdown data-variant="nav">
<button data-dropdown-button>Products</button>
<div data-dropdown-menu>
<div>
<div>
<a href="#" data-dropdown-item>Product 1</a>
<a href="#" data-dropdown-item>Product 2</a>
</div>
</div>
</div>
</div>Language switcher:
<div data-dropdown data-variant="language" data-dropdown-role="navigation">
<button data-dropdown-button aria-label="Výber jazyka">
🇬🇧 EN
<span data-dropdown-arrow></span>
</button>
<nav data-dropdown-menu aria-label="Výber jazyka">
<div>
<div>
<ul style="list-style: none; margin: 0; padding: 0;">
<li>
<a href="/en" hreflang="en" lang="en" data-dropdown-item aria-current="page">
<span data-dropdown-item-flag>🇬🇧</span>
English
</a>
</li>
<li>
<a href="/sk" hreflang="sk" lang="sk" data-dropdown-item>
<span data-dropdown-item-flag>🇸🇰</span>
Slovenčina
</a>
</li>
</ul>
</div>
</div>
</nav>
</div>Right-aligned menu:
<div data-dropdown-menu="right">
<!-- items -->
</div>Tabs
Fully accessible tabs component following WAI-ARIA Tabs Pattern.
Features
- ✅ Full ARIA attributes (role, aria-selected, aria-controls)
- ✅ Keyboard navigation (arrows, Home, End)
- ✅ Automatic and manual activation modes
- ✅ Focus management
- ✅ Disabled tabs support
- ✅ Horizontal and vertical orientation
- ✅ Multiple visual variants (basic, boxed, pills)
- ✅ Fade animations by default
- ✅ Automatic
prefers-reduced-motionsupport
Installation
<!-- CSS -->
<link rel="stylesheet" href="css/a11y-tabs.core.css">
<link rel="stylesheet" href="css/a11y-tabs.theme.css">
<!-- JavaScript -->
<script src="js/a11y-tabs.js"></script>Basic Usage
<div data-tabs>
<div role="tablist" data-tabs-list>
<button data-tabs-tab>Tab 1</button>
<button data-tabs-tab>Tab 2</button>
<button data-tabs-tab>Tab 3</button>
</div>
<div data-tabs-panel>
Content for tab 1
</div>
<div data-tabs-panel>
Content for tab 2
</div>
<div data-tabs-panel>
Content for tab 3
</div>
</div>JavaScript Initialization
import { initTabs, Tabs } from 'accessible-kit/tabs';
// Initialize all tabs
document.addEventListener('DOMContentLoaded', () => {
initTabs();
});
// Or manual initialization with options
const tabs = new Tabs(element, {
activeIndex: 0, // Initial active tab (0-based)
automatic: true, // Auto-activate on arrow keys
orientation: 'horizontal', // 'horizontal' or 'vertical'
onChange: (tab, panel, index) => {},
onTabClick: (tab, index) => {}
});Animations
Tabs have fade animation enabled by default when switching between panels.
Customizing animation speed:
<div data-tabs style="--a11y-tabs-duration: 0.5s;">
<!-- tabs -->
</div>:root {
--a11y-tabs-duration: 0.3s;
--a11y-tabs-easing: ease-in-out;
}Disable animations:
<div data-tabs data-no-animation>
<!-- tabs without fade animation -->
</div>Configuration
Data attributes:
<!-- Set initial active tab (0-based index) -->
<div data-tabs data-active-index="1">
<!-- Manual activation (requires Enter/Space) -->
<div data-tabs data-automatic="false">
<!-- Vertical orientation -->
<div data-tabs data-orientation="vertical">JavaScript options:
{
activeIndex: 0, // Initial active tab
automatic: true, // Auto-activate on arrow keys
orientation: 'horizontal', // 'horizontal' or 'vertical'
onChange: (tab, panel, index) => {}, // Callback on tab change
onTabClick: (tab, index) => {} // Callback on tab click
}Keyboard Navigation
Horizontal tabs:
- ← / → - Navigate between tabs
- Home - Jump to first tab
- End - Jump to last tab
- Enter / Space - Activate tab (manual mode)
- Tab - Move focus to panel content
Vertical tabs:
- ↑ / ↓ - Navigate between tabs
- Home / End - First/last tab
- Enter / Space - Activate tab
- Tab - Move to panel content
Variants
Boxed variant:
<div data-tabs data-variant="boxed">
<div role="tablist" data-tabs-list>
<button data-tabs-tab>Tab 1</button>
<button data-tabs-tab>Tab 2</button>
</div>
<div data-tabs-panels>
<div data-tabs-panel>Content 1</div>
<div data-tabs-panel>Content 2</div>
</div>
</div>Pills variant:
<div data-tabs data-variant="pills">
<!-- tabs styled as pills/buttons -->
</div>Vertical tabs:
<div data-tabs data-orientation="vertical">
<div role="tablist" data-tabs-list>
<button data-tabs-tab>Tab 1</button>
<button data-tabs-tab>Tab 2</button>
</div>
<div data-tabs-panels>
<div data-tabs-panel>Content 1</div>
<div data-tabs-panel>Content 2</div>
</div>
</div>Disabled tab:
<button data-tabs-tab disabled>Disabled Tab</button>Tabs with badges:
<button data-tabs-tab>
Active
<span class="tabs__tab-badge">12</span>
</button>Accordion
Fully accessible accordion component with keyboard navigation.
Features
- ✅ Full ARIA attributes support
- ✅ Keyboard navigation (arrows, Home, End, Enter, Space)
- ✅ Single or multiple expand modes
- ✅ CSS Grid animations by default
- ✅ Optional "Toggle All" button
- ✅ Automatic
prefers-reduced-motionsupport
Installation
<!-- CSS -->
<link rel="stylesheet" href="css/a11y-accordion.core.css">
<link rel="stylesheet" href="css/a11y-accordion.theme.css">
<!-- JavaScript -->
<script src="js/a11y-accordion.js"></script>Basic Usage
<div data-accordion>
<div data-accordion-item>
<button data-accordion-trigger>
Section 1
</button>
<div data-accordion-panel>
<!-- Two wrapper divs required for animations -->
<div>
<div>
<p>Content for section 1</p>
</div>
</div>
</div>
</div>
<div data-accordion-item>
<button data-accordion-trigger>
Section 2
</button>
<div data-accordion-panel>
<div>
<div>
<p>Content for section 2</p>
</div>
</div>
</div>
</div>
</div>JavaScript Initialization
import { initAccordions, Accordion } from 'accessible-kit/accordion';
// Initialize all accordions
document.addEventListener('DOMContentLoaded', () => {
initAccordions();
});
// Or manual initialization with options
const accordion = new Accordion(element, {
allowMultiple: false,
allowToggle: true,
defaultExpanded: [],
onToggle: (item, isExpanded) => {},
onChange: (expandedItems) => {}
});Animations
Accordions have CSS Grid animations enabled by default.
Customizing animation:
<div data-accordion style="--a11y-accordion-duration: 0.5s;">
<!-- accordion items -->
</div>:root {
--a11y-accordion-duration: 0.3s;
--a11y-accordion-easing: ease;
}Disable animations:
<div data-accordion data-no-animation>
<!-- accordion without animations -->
</div>Configuration
Allow multiple sections open:
<div data-accordion data-accordion-multiple>
<!-- multiple items can be open -->
</div>Default expanded state:
<div data-accordion-item data-default-expanded>
<!-- this item is expanded by default -->
</div>Toggle All Button:
<div data-accordion data-accordion-multiple>
<!-- Auto-generated toggle button -->
<div data-accordion-controls="top"></div>
<div data-accordion-item>
<!-- items -->
</div>
<!-- Bottom toggle button -->
<div data-accordion-controls="bottom"></div>
</div>Keyboard Navigation
- ↓ - Move to next trigger
- ↑ - Move to previous trigger
- Home - Move to first trigger
- End - Move to last trigger
- Enter / Space - Toggle accordion item
Collapse
Standalone collapsible panels - accordion functionality without the group structure.
Features
- ✅ Standalone toggle buttons
- ✅ CSS Grid animations by default
- ✅ Control multiple panels with one button
- ✅ Dynamic button text based on state
- ✅ ARIA attributes for accessibility
Basic Usage
<!-- Simple toggle -->
<button data-collapse-toggle="#panel">
Toggle Panel
</button>
<div id="panel">
<!-- Two wrapper divs required for animations -->
<div>
<div>
<p>Panel content here</p>
</div>
</div>
</div>Control Multiple Panels
<!-- Using class selector -->
<button data-collapse-toggle=".info-panel">
Toggle All Info Panels
</button>
<div class="info-panel">
<div><div>Panel 1</div></div>
</div>
<div class="info-panel">
<div><div>Panel 2</div></div>
</div>
<div class="info-panel">
<div><div>Panel 3</div></div>
</div>Dynamic Button Text
<button
data-collapse-toggle="#details"
data-text-for-show="Show Details"
data-text-for-hide="Hide Details"
data-aria-label-for-show="Show additional details"
data-aria-label-for-hide="Hide additional details">
<span>Show Details</span>
</button>
<div id="details">
<div><div>Details content</div></div>
</div>Animations
Disable animations for specific panel:
<div id="no-animation-panel" data-no-animation>
<div>
<div>Panel without animation</div>
</div>
</div>Modal
Accessible modal dialogs with focus trap following WAI-ARIA Dialog Pattern.
Features
- ✅ Full ARIA attributes (role="dialog", aria-modal="true")
- ✅ Focus trap - Tab cycles only within modal
- ✅ Return focus - Returns focus to trigger after close
- ✅ Scroll lock - Locks body scroll when open
- ✅ Escape to close
- ✅ Backdrop click to close
- ✅ Configurable behavior
Installation
<!-- CSS -->
<link rel="stylesheet" href="css/a11y-modal.core.css">
<link rel="stylesheet" href="css/a11y-modal.theme.css">
<!-- JavaScript -->
<script src="js/a11y-modal.js"></script>Basic Usage
<!-- Trigger button -->
<button data-modal-trigger="my-modal">Open Modal</button>
<!-- Modal -->
<div data-modal id="my-modal">
<div data-modal-backdrop></div>
<div data-modal-dialog>
<div data-modal-header>
<h2 data-modal-title>Modal Title</h2>
<button data-modal-close aria-label="Close modal">×</button>
</div>
<div data-modal-body>
<p>Modal content goes here.</p>
</div>
<div data-modal-footer>
<button data-modal-close>Cancel</button>
<button>Confirm</button>
</div>
</div>
</div>JavaScript Initialization
import { initModals, Modal } from 'accessible-kit/modal';
// Initialize all modals
document.addEventListener('DOMContentLoaded', () => {
initModals();
});
// Or manual initialization with options
const modal = new Modal(element, {
closeOnBackdropClick: true,
closeOnEscape: true,
lockScroll: true,
onOpen: (modal) => {},
onClose: (modal) => {}
});
// Programmatic control
modal.open();
modal.close();Configuration
{
closeOnBackdropClick: true, // Close on backdrop click
closeOnEscape: true, // Close on Esc key
lockScroll: true, // Lock body scroll
onOpen: (modal) => {}, // Callback on open
onClose: (modal) => {} // Callback on close
}Keyboard Navigation
- Tab - Cycle through focusable elements (trapped within modal)
- Shift + Tab - Reverse cycle
- Esc - Close modal
Offcanvas
Slide-out side panels with focus trap and full accessibility support.
Features
- ✅ Full ARIA attributes (role="dialog", aria-modal="true")
- ✅ Focus trap - Tab cycles only within offcanvas
- ✅ Return focus - Returns focus to trigger after close
- ✅ Scroll lock - Locks body scroll when open
- ✅ Escape to close
- ✅ Backdrop click to close
- ✅ 4 positions (left, right, top, bottom)
Installation
<!-- CSS -->
<link rel="stylesheet" href="css/a11y-offcanvas.core.css">
<link rel="stylesheet" href="css/a11y-offcanvas.theme.css">
<!-- JavaScript -->
<script src="js/a11y-offcanvas.js"></script>Basic Usage
<!-- Trigger button -->
<button data-offcanvas-trigger="menu">Open Menu</button>
<!-- Offcanvas -->
<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 aria-label="Close menu">×</button>
</div>
<div data-offcanvas-body>
<nav>
<a href="#">Home</a>
<a href="#">About</a>
<a href="#">Contact</a>
</nav>
</div>
</div>
</div>Positions
<!-- Left (default) -->
<div data-offcanvas-panel data-position="left">
<!-- Right -->
<div data-offcanvas-panel data-position="right">
<!-- Top -->
<div data-offcanvas-panel data-position="top">
<!-- Bottom -->
<div data-offcanvas-panel data-position="bottom">Animations
Customizing animation:
<div data-offcanvas style="--a11y-offcanvas-duration: 0.5s;">
<!-- offcanvas content -->
</div>:root {
--a11y-offcanvas-duration: 0.3s;
--a11y-offcanvas-easing: ease-in-out;
}Disable animations:
<div data-offcanvas data-no-animation>
<!-- offcanvas without animations -->
</div>🌐 Browser Support
Tested and working in:
- Chrome/Edge 90+
- Firefox 88+
- Safari 14+
- iOS Safari 14+
- Android Chrome 90+
🏗️ CSS Architecture
All components use a separated core/theme architecture:
Core CSS (*.core.css)
Contains only logic, positioning, layout, and behavior:
- Positioning (relative, absolute, z-index)
- Layout structure (display, flex, grid)
- Visibility states
- Animations
- Responsive breakpoints
- NO visual styling - completely theme-agnostic
Do not modify unless changing component functionality.
Theme CSS (*.theme.css)
Contains all visual styling:
- Colors (background, border, text)
- Spacing (padding, margin)
- Typography
- Borders and border-radius
- Shadows
- All focus indicators (
:focus-visiblewithoutline,outline-offset, etc.) - Dark mode
- High contrast mode
Customize freely to match your design system.
🎨 Creating Custom Themes
- Copy the theme CSS file:
cp a11y-dropdown.theme.css my-custom-theme.cssModify CSS variables and styles
Update your HTML:
<link rel="stylesheet" href="css/a11y-dropdown.core.css">
<link rel="stylesheet" href="css/my-custom-theme.css">🤝 Contributing
Contributions are welcome! Please read our Contributing Guidelines before submitting PRs.
Development Setup
# Clone repository
git clone https://github.com/5ulo/accessible-kit.git
cd accessible-kit
# Install dependencies
npm install
# Start development server
npm run dev
# Build for production
npm run buildRunning Tests
npm test📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🙏 Acknowledgments
Built with a focus on accessibility and usability, following:
- WAI-ARIA Authoring Practices Guide (APG)
- WCAG 2.1 Guidelines
- Modern web standards and best practices
💬 Support
Made with ♿ and ❤️ for a more accessible web.
