accessible-kit 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,1038 @@
1
+ # Accessible Kit
2
+
3
+ <!-- Badges will be added when published -->
4
+ [![npm version](https://img.shields.io/npm/v/accessible-kit.svg)](https://www.npmjs.com/package/accessible-kit)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
6
+ [![Bundle Size](https://img.shields.io/bundlephobia/minzip/accessible-kit)](https://bundlephobia.com/package/accessible-kit)
7
+
8
+ > Lightweight, accessible UI component library with full ARIA support. Zero dependencies, vanilla JavaScript.
9
+
10
+ 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.
11
+
12
+ ## âœĻ Features
13
+
14
+ - **ðŸŽŊ Fully Accessible** - Complete ARIA support and keyboard navigation
15
+ - **ðŸŠķ Lightweight** - Zero dependencies, vanilla JavaScript
16
+ - **ðŸŽĻ Customizable** - Separated core/theme CSS for easy theming
17
+ - **ðŸ“ą Responsive** - Mobile-first design approach
18
+ - **🌙 Dark Mode** - Built-in dark mode support
19
+ - **â™ŋ Inclusive** - High contrast mode and reduced motion support
20
+ - **🔧 Framework Agnostic** - Works with any framework or vanilla JS
21
+ - **ðŸ“Ķ Tree-shakeable** - Import only what you need
22
+
23
+ ## 📚 Table of Contents
24
+
25
+ - [Demo](#-demo)
26
+ - [Installation](#-installation)
27
+ - [Quick Start](#-quick-start)
28
+ - [Components](#-components)
29
+ - [Dropdown](#dropdown)
30
+ - [Tabs](#tabs)
31
+ - [Accordion](#accordion)
32
+ - [Collapse](#collapse)
33
+ - [Modal](#modal)
34
+ - [Offcanvas](#offcanvas)
35
+ - [Browser Support](#-browser-support)
36
+ - [Contributing](#-contributing)
37
+ - [License](#-license)
38
+
39
+ ## 🎭 Demo
40
+
41
+ View live examples at: [https://5ulo.github.io/accessible-kit/](https://5ulo.github.io/accessible-kit/)
42
+
43
+ ## ðŸ“Ķ Installation
44
+
45
+ ### NPM
46
+
47
+ ```bash
48
+ npm install accessible-kit
49
+ ```
50
+
51
+ ### Yarn
52
+
53
+ ```bash
54
+ yarn add accessible-kit
55
+ ```
56
+
57
+ ### CDN
58
+
59
+ ```html
60
+ <!-- All components -->
61
+ <script src="https://unpkg.com/accessible-kit/src/js/index.js"></script>
62
+
63
+ <!-- Individual component -->
64
+ <script src="https://unpkg.com/accessible-kit/src/js/a11y-dropdown.js"></script>
65
+ <link rel="stylesheet" href="https://unpkg.com/accessible-kit/src/css/a11y-dropdown.core.css">
66
+ <link rel="stylesheet" href="https://unpkg.com/accessible-kit/src/css/a11y-dropdown.theme.css">
67
+ ```
68
+
69
+ ## 🚀 Quick Start
70
+
71
+ ### Using CDN
72
+
73
+ ```html
74
+ <!DOCTYPE html>
75
+ <html lang="en">
76
+ <head>
77
+ <link rel="stylesheet" href="https://unpkg.com/accessible-kit/src/css/a11y-dropdown.core.css">
78
+ <link rel="stylesheet" href="https://unpkg.com/accessible-kit/src/css/a11y-dropdown.theme.css">
79
+ </head>
80
+ <body>
81
+ <div data-dropdown>
82
+ <button data-dropdown-button>
83
+ Options
84
+ <span data-dropdown-arrow></span>
85
+ </button>
86
+ <div data-dropdown-menu>
87
+ <div>
88
+ <div>
89
+ <button data-dropdown-item>Edit</button>
90
+ <button data-dropdown-item>Delete</button>
91
+ </div>
92
+ </div>
93
+ </div>
94
+ </div>
95
+
96
+ <script src="https://unpkg.com/accessible-kit/src/js/a11y-dropdown.js"></script>
97
+ </body>
98
+ </html>
99
+ ```
100
+
101
+ ### Using NPM/Modules
102
+
103
+ ```javascript
104
+ // Import all components
105
+ import 'accessible-kit';
106
+
107
+ // Or import specific components
108
+ import 'accessible-kit/dropdown';
109
+ import 'accessible-kit/tabs';
110
+
111
+ // Import styles
112
+ import 'accessible-kit/styles/dropdown-core';
113
+ import 'accessible-kit/styles/dropdown-theme';
114
+
115
+ // Initialize
116
+ a11yKit.initAll();
117
+ // or
118
+ a11yKit.initDropdowns();
119
+ ```
120
+
121
+ ### Module Imports (ES6+)
122
+
123
+ ```javascript
124
+ import { AccessibleDropdown } from 'accessible-kit/dropdown';
125
+
126
+ const dropdown = new AccessibleDropdown(element, {
127
+ closeOnSelect: true,
128
+ onOpen: () => console.log('Opened'),
129
+ onClose: () => console.log('Closed')
130
+ });
131
+ ```
132
+
133
+ ## ðŸ§Đ Components
134
+
135
+ ### Available Components (v1.0)
136
+
137
+ - ✅ **Dropdown** - Accessible dropdown menus with keyboard navigation
138
+ - ✅ **Tabs** - Tab panels following WAI-ARIA Tabs Pattern
139
+ - ✅ **Accordion** - Expandable sections with keyboard support
140
+ - ✅ **Collapse** - Standalone collapsible panels
141
+ - ✅ **Modal** - Accessible dialogs with focus trap
142
+ - ✅ **Offcanvas** - Slide-out side panels with focus management
143
+
144
+ ### Roadmap (v1.1+)
145
+
146
+ - 🔜 **Tooltip** - Accessible tooltips with positioning
147
+ - 🔜 **Toast/Notification** - Live region announcements
148
+ - 🔜 **Toggle Switch** - Accessible switch component
149
+ - 🔜 **Popover** - Interactive popovers
150
+ - 🔜 **Alert/Banner** - Dismissible alert messages
151
+ - 🔜 **Combobox/Autocomplete** - Searchable select component
152
+
153
+ ---
154
+
155
+ ## Dropdown
156
+
157
+ Fully accessible dropdown component with keyboard navigation and ARIA support.
158
+
159
+ ### Features
160
+
161
+ - ✅ Full ARIA attributes support
162
+ - ✅ Keyboard navigation (arrows, Enter, Space, Esc, Home, End)
163
+ - ✅ Focus management
164
+ - ✅ Auto-close on outside click
165
+ - ✅ CSS Grid animations by default
166
+ - ✅ Multiple variants (nav, language switcher)
167
+ - ✅ Automatic `prefers-reduced-motion` support
168
+
169
+ ### Installation
170
+
171
+ ```html
172
+ <!-- CSS -->
173
+ <link rel="stylesheet" href="css/a11y-dropdown.core.css">
174
+ <link rel="stylesheet" href="css/a11y-dropdown.theme.css">
175
+
176
+ <!-- JavaScript -->
177
+ <script src="js/a11y-dropdown.js"></script>
178
+ ```
179
+
180
+ ### Basic Usage
181
+
182
+ ```html
183
+ <div data-dropdown>
184
+ <button data-dropdown-button>
185
+ Options
186
+ <span data-dropdown-arrow></span>
187
+ </button>
188
+ <div data-dropdown-menu>
189
+ <!-- Two wrapper divs required for animations -->
190
+ <div>
191
+ <div>
192
+ <button data-dropdown-item>Edit</button>
193
+ <button data-dropdown-item>Duplicate</button>
194
+ <hr data-dropdown-divider>
195
+ <button data-dropdown-item>Delete</button>
196
+ </div>
197
+ </div>
198
+ </div>
199
+ </div>
200
+ ```
201
+
202
+ ### JavaScript Initialization
203
+
204
+ ```javascript
205
+ // Auto-initialize all dropdowns
206
+ initDropdowns();
207
+
208
+ // Or manual initialization with options
209
+ const dropdown = new AccessibleDropdown(element, {
210
+ closeOnSelect: true,
211
+ closeOnOutsideClick: true,
212
+ closeOnEscape: true,
213
+ hoverDelay: 0,
214
+ onOpen: (dropdown) => {},
215
+ onClose: (dropdown) => {},
216
+ onSelect: (item, index) => {}
217
+ });
218
+ ```
219
+
220
+ ### Animations
221
+
222
+ Dropdowns have **CSS Grid animations enabled by default**. The animation automatically respects `prefers-reduced-motion` user preferences.
223
+
224
+ **Customizing animation speed:**
225
+
226
+ ```html
227
+ <!-- Inline via style attribute -->
228
+ <div data-dropdown style="--a11y-dropdown-duration: 0.5s;">
229
+ <!-- dropdown content -->
230
+ </div>
231
+ ```
232
+
233
+ ```css
234
+ /* Or globally in CSS */
235
+ :root {
236
+ --a11y-dropdown-duration: 0.3s;
237
+ --a11y-dropdown-easing: ease-in-out;
238
+ }
239
+ ```
240
+
241
+ **Disable animations:**
242
+
243
+ ```html
244
+ <div data-dropdown-menu data-no-animation>
245
+ <!-- menu without animations -->
246
+ </div>
247
+ ```
248
+
249
+ ### Configuration
250
+
251
+ **Data attributes:**
252
+
253
+ ```html
254
+ <!-- Keep dropdown open after selection -->
255
+ <div data-dropdown data-close-on-select="false">
256
+
257
+ <!-- Disable close on outside click -->
258
+ <div data-dropdown data-close-on-outside-click="false">
259
+
260
+ <!-- Hover delay (ms) -->
261
+ <div data-dropdown data-hover-delay="200">
262
+ ```
263
+
264
+ **JavaScript options:**
265
+
266
+ ```javascript
267
+ {
268
+ closeOnSelect: true, // Close after selecting item
269
+ closeOnOutsideClick: true, // Close on outside click
270
+ closeOnEscape: true, // Close on Escape key
271
+ hoverDelay: 0, // Hover delay in ms
272
+ onOpen: (dropdown) => {}, // Callback on open
273
+ onClose: (dropdown) => {}, // Callback on close
274
+ onSelect: (item, index) => {} // Callback on item select
275
+ }
276
+ ```
277
+
278
+ ### Keyboard Navigation
279
+
280
+ - **Enter** / **Space** - Open/close menu or select item
281
+ - **↓** / **↑** - Navigate between items
282
+ - **Home** / **End** - Jump to first/last item
283
+ - **Esc** - Close menu and return focus to button
284
+ - **Tab** - Close menu and move focus
285
+
286
+ ### Variants
287
+
288
+ **Navigation menu:**
289
+
290
+ ```html
291
+ <div data-dropdown data-variant="nav">
292
+ <button data-dropdown-button>Products</button>
293
+ <div data-dropdown-menu>
294
+ <div>
295
+ <div>
296
+ <a href="#" data-dropdown-item>Product 1</a>
297
+ <a href="#" data-dropdown-item>Product 2</a>
298
+ </div>
299
+ </div>
300
+ </div>
301
+ </div>
302
+ ```
303
+
304
+ **Language switcher:**
305
+
306
+ ```html
307
+ <div data-dropdown data-variant="language">
308
+ <button data-dropdown-button>
309
+ 🇎🇧 EN
310
+ <span data-dropdown-arrow></span>
311
+ </button>
312
+ <div data-dropdown-menu>
313
+ <div>
314
+ <div>
315
+ <button data-dropdown-item>
316
+ <span data-dropdown-item-flag>🇎🇧</span>
317
+ English
318
+ </button>
319
+ <button data-dropdown-item>
320
+ <span data-dropdown-item-flag>ðŸ‡ļ🇰</span>
321
+ Slovenčina
322
+ </button>
323
+ </div>
324
+ </div>
325
+ </div>
326
+ </div>
327
+ ```
328
+
329
+ **Right-aligned menu:**
330
+
331
+ ```html
332
+ <div data-dropdown-menu="right">
333
+ <!-- items -->
334
+ </div>
335
+ ```
336
+
337
+ ---
338
+
339
+ ## Tabs
340
+
341
+ Fully accessible tabs component following WAI-ARIA Tabs Pattern.
342
+
343
+ ### Features
344
+
345
+ - ✅ Full ARIA attributes (role, aria-selected, aria-controls)
346
+ - ✅ Keyboard navigation (arrows, Home, End)
347
+ - ✅ Automatic and manual activation modes
348
+ - ✅ Focus management
349
+ - ✅ Disabled tabs support
350
+ - ✅ Horizontal and vertical orientation
351
+ - ✅ Multiple visual variants (basic, boxed, pills)
352
+ - ✅ Fade animations by default
353
+ - ✅ Automatic `prefers-reduced-motion` support
354
+
355
+ ### Installation
356
+
357
+ ```html
358
+ <!-- CSS -->
359
+ <link rel="stylesheet" href="css/a11y-tabs.core.css">
360
+ <link rel="stylesheet" href="css/a11y-tabs.theme.css">
361
+
362
+ <!-- JavaScript -->
363
+ <script src="js/a11y-tabs.js"></script>
364
+ ```
365
+
366
+ ### Basic Usage
367
+
368
+ ```html
369
+ <div data-tabs>
370
+ <div role="tablist" data-tabs-list>
371
+ <button data-tabs-tab>Tab 1</button>
372
+ <button data-tabs-tab>Tab 2</button>
373
+ <button data-tabs-tab>Tab 3</button>
374
+ </div>
375
+
376
+ <div data-tabs-panel>
377
+ Content for tab 1
378
+ </div>
379
+
380
+ <div data-tabs-panel>
381
+ Content for tab 2
382
+ </div>
383
+
384
+ <div data-tabs-panel>
385
+ Content for tab 3
386
+ </div>
387
+ </div>
388
+ ```
389
+
390
+ ### JavaScript Initialization
391
+
392
+ ```javascript
393
+ // Auto-initialize all tabs
394
+ initTabs();
395
+
396
+ // Manual initialization
397
+ const tabs = new AccessibleTabs(element, {
398
+ activeIndex: 0, // Initial active tab (0-based)
399
+ automatic: true, // Auto-activate on arrow keys
400
+ orientation: 'horizontal', // 'horizontal' or 'vertical'
401
+ onChange: (tab, panel, index) => {},
402
+ onTabClick: (tab, index) => {}
403
+ });
404
+ ```
405
+
406
+ ### Animations
407
+
408
+ Tabs have **fade animation enabled by default** when switching between panels.
409
+
410
+ **Customizing animation speed:**
411
+
412
+ ```html
413
+ <div data-tabs style="--a11y-tabs-duration: 0.5s;">
414
+ <!-- tabs -->
415
+ </div>
416
+ ```
417
+
418
+ ```css
419
+ :root {
420
+ --a11y-tabs-duration: 0.3s;
421
+ --a11y-tabs-easing: ease-in-out;
422
+ }
423
+ ```
424
+
425
+ **Disable animations:**
426
+
427
+ ```html
428
+ <div data-tabs data-no-animation>
429
+ <!-- tabs without fade animation -->
430
+ </div>
431
+ ```
432
+
433
+ ### Configuration
434
+
435
+ **Data attributes:**
436
+
437
+ ```html
438
+ <!-- Set initial active tab (0-based index) -->
439
+ <div data-tabs data-active-index="1">
440
+
441
+ <!-- Manual activation (requires Enter/Space) -->
442
+ <div data-tabs data-automatic="false">
443
+
444
+ <!-- Vertical orientation -->
445
+ <div data-tabs data-orientation="vertical">
446
+ ```
447
+
448
+ **JavaScript options:**
449
+
450
+ ```javascript
451
+ {
452
+ activeIndex: 0, // Initial active tab
453
+ automatic: true, // Auto-activate on arrow keys
454
+ orientation: 'horizontal', // 'horizontal' or 'vertical'
455
+ onChange: (tab, panel, index) => {}, // Callback on tab change
456
+ onTabClick: (tab, index) => {} // Callback on tab click
457
+ }
458
+ ```
459
+
460
+ ### Keyboard Navigation
461
+
462
+ **Horizontal tabs:**
463
+ - **←** / **→** - Navigate between tabs
464
+ - **Home** - Jump to first tab
465
+ - **End** - Jump to last tab
466
+ - **Enter** / **Space** - Activate tab (manual mode)
467
+ - **Tab** - Move focus to panel content
468
+
469
+ **Vertical tabs:**
470
+ - **↑** / **↓** - Navigate between tabs
471
+ - **Home** / **End** - First/last tab
472
+ - **Enter** / **Space** - Activate tab
473
+ - **Tab** - Move to panel content
474
+
475
+ ### Variants
476
+
477
+ **Boxed variant:**
478
+
479
+ ```html
480
+ <div data-tabs data-variant="boxed">
481
+ <div role="tablist" data-tabs-list>
482
+ <button data-tabs-tab>Tab 1</button>
483
+ <button data-tabs-tab>Tab 2</button>
484
+ </div>
485
+
486
+ <div data-tabs-panels>
487
+ <div data-tabs-panel>Content 1</div>
488
+ <div data-tabs-panel>Content 2</div>
489
+ </div>
490
+ </div>
491
+ ```
492
+
493
+ **Pills variant:**
494
+
495
+ ```html
496
+ <div data-tabs data-variant="pills">
497
+ <!-- tabs styled as pills/buttons -->
498
+ </div>
499
+ ```
500
+
501
+ **Vertical tabs:**
502
+
503
+ ```html
504
+ <div data-tabs data-orientation="vertical">
505
+ <div role="tablist" data-tabs-list>
506
+ <button data-tabs-tab>Tab 1</button>
507
+ <button data-tabs-tab>Tab 2</button>
508
+ </div>
509
+
510
+ <div data-tabs-panels>
511
+ <div data-tabs-panel>Content 1</div>
512
+ <div data-tabs-panel>Content 2</div>
513
+ </div>
514
+ </div>
515
+ ```
516
+
517
+ **Disabled tab:**
518
+
519
+ ```html
520
+ <button data-tabs-tab disabled>Disabled Tab</button>
521
+ ```
522
+
523
+ **Tabs with badges:**
524
+
525
+ ```html
526
+ <button data-tabs-tab>
527
+ Active
528
+ <span class="tabs__tab-badge">12</span>
529
+ </button>
530
+ ```
531
+
532
+ ---
533
+
534
+ ## Accordion
535
+
536
+ Fully accessible accordion component with keyboard navigation.
537
+
538
+ ### Features
539
+
540
+ - ✅ Full ARIA attributes support
541
+ - ✅ Keyboard navigation (arrows, Home, End, Enter, Space)
542
+ - ✅ Single or multiple expand modes
543
+ - ✅ CSS Grid animations by default
544
+ - ✅ Optional "Toggle All" button
545
+ - ✅ Automatic `prefers-reduced-motion` support
546
+
547
+ ### Installation
548
+
549
+ ```html
550
+ <!-- CSS -->
551
+ <link rel="stylesheet" href="css/a11y-accordion.core.css">
552
+ <link rel="stylesheet" href="css/a11y-accordion.theme.css">
553
+
554
+ <!-- JavaScript -->
555
+ <script src="js/a11y-accordion.js"></script>
556
+ ```
557
+
558
+ ### Basic Usage
559
+
560
+ ```html
561
+ <div data-accordion>
562
+ <div data-accordion-item>
563
+ <button data-accordion-trigger>
564
+ Section 1
565
+ </button>
566
+ <div data-accordion-panel>
567
+ <!-- Two wrapper divs required for animations -->
568
+ <div>
569
+ <div>
570
+ <p>Content for section 1</p>
571
+ </div>
572
+ </div>
573
+ </div>
574
+ </div>
575
+
576
+ <div data-accordion-item>
577
+ <button data-accordion-trigger>
578
+ Section 2
579
+ </button>
580
+ <div data-accordion-panel>
581
+ <div>
582
+ <div>
583
+ <p>Content for section 2</p>
584
+ </div>
585
+ </div>
586
+ </div>
587
+ </div>
588
+ </div>
589
+ ```
590
+
591
+ ### JavaScript Initialization
592
+
593
+ ```javascript
594
+ // Auto-initialize all accordions
595
+ initAccordions();
596
+
597
+ // Manual initialization
598
+ const accordion = new AccessibleAccordion(element, {
599
+ allowMultiple: false,
600
+ allowToggle: true,
601
+ defaultExpanded: [],
602
+ onToggle: (item, isExpanded) => {},
603
+ onChange: (expandedItems) => {}
604
+ });
605
+ ```
606
+
607
+ ### Animations
608
+
609
+ Accordions have **CSS Grid animations enabled by default**.
610
+
611
+ **Customizing animation:**
612
+
613
+ ```html
614
+ <div data-accordion style="--a11y-accordion-duration: 0.5s;">
615
+ <!-- accordion items -->
616
+ </div>
617
+ ```
618
+
619
+ ```css
620
+ :root {
621
+ --a11y-accordion-duration: 0.3s;
622
+ --a11y-accordion-easing: ease;
623
+ }
624
+ ```
625
+
626
+ **Disable animations:**
627
+
628
+ ```html
629
+ <div data-accordion data-no-animation>
630
+ <!-- accordion without animations -->
631
+ </div>
632
+ ```
633
+
634
+ ### Configuration
635
+
636
+ **Allow multiple sections open:**
637
+
638
+ ```html
639
+ <div data-accordion data-accordion-multiple>
640
+ <!-- multiple items can be open -->
641
+ </div>
642
+ ```
643
+
644
+ **Default expanded state:**
645
+
646
+ ```html
647
+ <div data-accordion-item data-default-expanded>
648
+ <!-- this item is expanded by default -->
649
+ </div>
650
+ ```
651
+
652
+ **Toggle All Button:**
653
+
654
+ ```html
655
+ <div data-accordion data-accordion-multiple>
656
+ <!-- Auto-generated toggle button -->
657
+ <div data-accordion-controls="top"></div>
658
+
659
+ <div data-accordion-item>
660
+ <!-- items -->
661
+ </div>
662
+
663
+ <!-- Bottom toggle button -->
664
+ <div data-accordion-controls="bottom"></div>
665
+ </div>
666
+ ```
667
+
668
+ ### Keyboard Navigation
669
+
670
+ - **↓** - Move to next trigger
671
+ - **↑** - Move to previous trigger
672
+ - **Home** - Move to first trigger
673
+ - **End** - Move to last trigger
674
+ - **Enter** / **Space** - Toggle accordion item
675
+
676
+ ---
677
+
678
+ ## Collapse
679
+
680
+ Standalone collapsible panels - accordion functionality without the group structure.
681
+
682
+ ### Features
683
+
684
+ - ✅ Standalone toggle buttons
685
+ - ✅ CSS Grid animations by default
686
+ - ✅ Control multiple panels with one button
687
+ - ✅ Dynamic button text based on state
688
+ - ✅ ARIA attributes for accessibility
689
+
690
+ ### Basic Usage
691
+
692
+ ```html
693
+ <!-- Simple toggle -->
694
+ <button data-collapse-toggle="#panel">
695
+ Toggle Panel
696
+ </button>
697
+
698
+ <div id="panel">
699
+ <!-- Two wrapper divs required for animations -->
700
+ <div>
701
+ <div>
702
+ <p>Panel content here</p>
703
+ </div>
704
+ </div>
705
+ </div>
706
+ ```
707
+
708
+ ### Control Multiple Panels
709
+
710
+ ```html
711
+ <!-- Using class selector -->
712
+ <button data-collapse-toggle=".info-panel">
713
+ Toggle All Info Panels
714
+ </button>
715
+
716
+ <div class="info-panel">
717
+ <div><div>Panel 1</div></div>
718
+ </div>
719
+ <div class="info-panel">
720
+ <div><div>Panel 2</div></div>
721
+ </div>
722
+ <div class="info-panel">
723
+ <div><div>Panel 3</div></div>
724
+ </div>
725
+ ```
726
+
727
+ ### Dynamic Button Text
728
+
729
+ ```html
730
+ <button
731
+ data-collapse-toggle="#details"
732
+ data-text-for-show="Show Details"
733
+ data-text-for-hide="Hide Details"
734
+ data-aria-label-for-show="Show additional details"
735
+ data-aria-label-for-hide="Hide additional details">
736
+ <span>Show Details</span>
737
+ </button>
738
+
739
+ <div id="details">
740
+ <div><div>Details content</div></div>
741
+ </div>
742
+ ```
743
+
744
+ ### Animations
745
+
746
+ **Disable animations for specific panel:**
747
+
748
+ ```html
749
+ <div id="no-animation-panel" data-no-animation>
750
+ <div>
751
+ <div>Panel without animation</div>
752
+ </div>
753
+ </div>
754
+ ```
755
+
756
+ ---
757
+
758
+ ## Modal
759
+
760
+ Accessible modal dialogs with focus trap following WAI-ARIA Dialog Pattern.
761
+
762
+ ### Features
763
+
764
+ - ✅ Full ARIA attributes (role="dialog", aria-modal="true")
765
+ - ✅ Focus trap - Tab cycles only within modal
766
+ - ✅ Return focus - Returns focus to trigger after close
767
+ - ✅ Scroll lock - Locks body scroll when open
768
+ - ✅ Escape to close
769
+ - ✅ Backdrop click to close
770
+ - ✅ Configurable behavior
771
+
772
+ ### Installation
773
+
774
+ ```html
775
+ <!-- CSS -->
776
+ <link rel="stylesheet" href="css/a11y-modal.core.css">
777
+ <link rel="stylesheet" href="css/a11y-modal.theme.css">
778
+
779
+ <!-- JavaScript -->
780
+ <script src="js/a11y-modal.js"></script>
781
+ ```
782
+
783
+ ### Basic Usage
784
+
785
+ ```html
786
+ <!-- Trigger button -->
787
+ <button data-modal-trigger="my-modal">Open Modal</button>
788
+
789
+ <!-- Modal -->
790
+ <div data-modal id="my-modal">
791
+ <div data-modal-backdrop></div>
792
+ <div data-modal-dialog>
793
+ <div data-modal-header>
794
+ <h2 data-modal-title>Modal Title</h2>
795
+ <button data-modal-close aria-label="Close modal">×</button>
796
+ </div>
797
+ <div data-modal-body>
798
+ <p>Modal content goes here.</p>
799
+ </div>
800
+ <div data-modal-footer>
801
+ <button data-modal-close>Cancel</button>
802
+ <button>Confirm</button>
803
+ </div>
804
+ </div>
805
+ </div>
806
+ ```
807
+
808
+ ### JavaScript Initialization
809
+
810
+ ```javascript
811
+ // Auto-initialize all modals
812
+ initModals();
813
+
814
+ // Manual initialization
815
+ const modal = new AccessibleModal(element, {
816
+ closeOnBackdropClick: true,
817
+ closeOnEscape: true,
818
+ lockScroll: true,
819
+ onOpen: (modal) => {},
820
+ onClose: (modal) => {}
821
+ });
822
+
823
+ // Programmatic control
824
+ modal.open();
825
+ modal.close();
826
+ ```
827
+
828
+ ### Configuration
829
+
830
+ ```javascript
831
+ {
832
+ closeOnBackdropClick: true, // Close on backdrop click
833
+ closeOnEscape: true, // Close on Esc key
834
+ lockScroll: true, // Lock body scroll
835
+ onOpen: (modal) => {}, // Callback on open
836
+ onClose: (modal) => {} // Callback on close
837
+ }
838
+ ```
839
+
840
+ ### Keyboard Navigation
841
+
842
+ - **Tab** - Cycle through focusable elements (trapped within modal)
843
+ - **Shift + Tab** - Reverse cycle
844
+ - **Esc** - Close modal
845
+
846
+ ---
847
+
848
+ ## Offcanvas
849
+
850
+ Slide-out side panels with focus trap and full accessibility support.
851
+
852
+ ### Features
853
+
854
+ - ✅ Full ARIA attributes (role="dialog", aria-modal="true")
855
+ - ✅ Focus trap - Tab cycles only within offcanvas
856
+ - ✅ Return focus - Returns focus to trigger after close
857
+ - ✅ Scroll lock - Locks body scroll when open
858
+ - ✅ Escape to close
859
+ - ✅ Backdrop click to close
860
+ - ✅ 4 positions (left, right, top, bottom)
861
+
862
+ ### Installation
863
+
864
+ ```html
865
+ <!-- CSS -->
866
+ <link rel="stylesheet" href="css/a11y-offcanvas.core.css">
867
+ <link rel="stylesheet" href="css/a11y-offcanvas.theme.css">
868
+
869
+ <!-- JavaScript -->
870
+ <script src="js/a11y-offcanvas.js"></script>
871
+ ```
872
+
873
+ ### Basic Usage
874
+
875
+ ```html
876
+ <!-- Trigger button -->
877
+ <button data-offcanvas-trigger="menu">Open Menu</button>
878
+
879
+ <!-- Offcanvas -->
880
+ <div data-offcanvas id="menu">
881
+ <div data-position="left" data-offcanvas-panel>
882
+ <div data-offcanvas-header>
883
+ <h2 data-offcanvas-title>Menu</h2>
884
+ <button data-offcanvas-close aria-label="Close menu">×</button>
885
+ </div>
886
+ <div data-offcanvas-body>
887
+ <nav>
888
+ <a href="#">Home</a>
889
+ <a href="#">About</a>
890
+ <a href="#">Contact</a>
891
+ </nav>
892
+ </div>
893
+ </div>
894
+ </div>
895
+ ```
896
+
897
+ ### Positions
898
+
899
+ ```html
900
+ <!-- Left (default) -->
901
+ <div data-offcanvas-panel data-position="left">
902
+
903
+ <!-- Right -->
904
+ <div data-offcanvas-panel data-position="right">
905
+
906
+ <!-- Top -->
907
+ <div data-offcanvas-panel data-position="top">
908
+
909
+ <!-- Bottom -->
910
+ <div data-offcanvas-panel data-position="bottom">
911
+ ```
912
+
913
+ ### Animations
914
+
915
+ **Customizing animation:**
916
+
917
+ ```html
918
+ <div data-offcanvas style="--a11y-offcanvas-duration: 0.5s;">
919
+ <!-- offcanvas content -->
920
+ </div>
921
+ ```
922
+
923
+ ```css
924
+ :root {
925
+ --a11y-offcanvas-duration: 0.3s;
926
+ --a11y-offcanvas-easing: ease-in-out;
927
+ }
928
+ ```
929
+
930
+ **Disable animations:**
931
+
932
+ ```html
933
+ <div data-offcanvas data-no-animation>
934
+ <!-- offcanvas without animations -->
935
+ </div>
936
+ ```
937
+
938
+ ---
939
+
940
+ ## 🌐 Browser Support
941
+
942
+ Tested and working in:
943
+
944
+ - **Chrome/Edge** 90+
945
+ - **Firefox** 88+
946
+ - **Safari** 14+
947
+ - **iOS Safari** 14+
948
+ - **Android Chrome** 90+
949
+
950
+ ## 🏗ïļ CSS Architecture
951
+
952
+ All components use a **separated core/theme architecture**:
953
+
954
+ ### Core CSS (`*.core.css`)
955
+
956
+ Contains only logic, positioning, layout, and behavior:
957
+ - Positioning (relative, absolute, z-index)
958
+ - Layout structure (display, flex, grid)
959
+ - Visibility states
960
+ - Animations
961
+ - Responsive breakpoints
962
+
963
+ **Do not modify** unless changing component functionality.
964
+
965
+ ### Theme CSS (`*.theme.css`)
966
+
967
+ Contains all visual styling:
968
+ - Colors (background, border, text)
969
+ - Spacing (padding, margin)
970
+ - Typography
971
+ - Borders and border-radius
972
+ - Shadows
973
+ - Dark mode
974
+ - High contrast mode
975
+
976
+ **Customize freely** to match your design system.
977
+
978
+ ## ðŸŽĻ Creating Custom Themes
979
+
980
+ 1. Copy the theme CSS file:
981
+ ```bash
982
+ cp a11y-dropdown.theme.css my-custom-theme.css
983
+ ```
984
+
985
+ 2. Modify CSS variables and styles
986
+
987
+ 3. Update your HTML:
988
+ ```html
989
+ <link rel="stylesheet" href="css/a11y-dropdown.core.css">
990
+ <link rel="stylesheet" href="css/my-custom-theme.css">
991
+ ```
992
+
993
+ ## ðŸĪ Contributing
994
+
995
+ Contributions are welcome! Please read our [Contributing Guidelines](CONTRIBUTING.md) before submitting PRs.
996
+
997
+ ### Development Setup
998
+
999
+ ```bash
1000
+ # Clone repository
1001
+ git clone https://github.com/5ulo/accessible-kit.git
1002
+ cd accessible-kit
1003
+
1004
+ # Install dependencies
1005
+ npm install
1006
+
1007
+ # Start development server
1008
+ npm run dev
1009
+
1010
+ # Build for production
1011
+ npm run build
1012
+ ```
1013
+
1014
+ ### Running Tests
1015
+
1016
+ ```bash
1017
+ npm test
1018
+ ```
1019
+
1020
+ ## 📄 License
1021
+
1022
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
1023
+
1024
+ ## 🙏 Acknowledgments
1025
+
1026
+ Built with a focus on accessibility and usability, following:
1027
+ - [WAI-ARIA Authoring Practices Guide (APG)](https://www.w3.org/WAI/ARIA/apg/)
1028
+ - [WCAG 2.1 Guidelines](https://www.w3.org/WAI/WCAG21/quickref/)
1029
+ - Modern web standards and best practices
1030
+
1031
+ ## 💎 Support
1032
+
1033
+ - 📖 [Documentation](https://5ulo.github.io/accessible-kit/)
1034
+ - 🐛 [Issue Tracker](https://github.com/5ulo/accessible-kit/issues)
1035
+
1036
+ ---
1037
+
1038
+ Made with â™ŋ and âĪïļ for a more accessible web.