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 testLicense
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.