admin-lte 4.0.2 β†’ 4.0.4

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.
Files changed (110) hide show
  1. package/ACCESSIBILITY-COMPLIANCE.md +60 -339
  2. package/CHANGELOG.md +43 -0
  3. package/README.md +15 -2
  4. package/dist/css/adminlte.css +24 -786
  5. package/dist/css/adminlte.css.map +1 -1
  6. package/dist/css/adminlte.min.css +2 -2
  7. package/dist/css/adminlte.min.css.map +1 -1
  8. package/dist/css/adminlte.rtl.css +24 -786
  9. package/dist/css/adminlte.rtl.css.map +1 -1
  10. package/dist/css/adminlte.rtl.min.css +2 -2
  11. package/dist/css/adminlte.rtl.min.css.map +1 -1
  12. package/dist/js/adminlte.js +233 -128
  13. package/dist/js/adminlte.js.map +1 -1
  14. package/dist/js/adminlte.min.js +2 -2
  15. package/dist/js/adminlte.min.js.map +1 -1
  16. package/package.json +30 -17
  17. package/src/scss/_callouts.scss +13 -3
  18. package/src/scss/_dropdown.scss +3 -1
  19. package/src/scss/adminlte.scss +1 -1
  20. package/src/scss/parts/_core.scss +0 -1
  21. package/src/ts/accessibility.ts +129 -69
  22. package/src/ts/adminlte.ts +1 -1
  23. package/src/ts/card-widget.ts +33 -8
  24. package/src/ts/fullscreen.ts +48 -42
  25. package/src/ts/layout.ts +2 -1
  26. package/src/ts/push-menu.ts +24 -8
  27. package/src/ts/treeview.ts +27 -1
  28. package/src/ts/util/index.ts +114 -29
  29. package/.browserslistrc +0 -17
  30. package/.prettierrc +0 -6
  31. package/CODE_OF_CONDUCT.md +0 -43
  32. package/SECURITY.md +0 -99
  33. package/dist/UI/general.html +0 -2317
  34. package/dist/UI/icons.html +0 -1126
  35. package/dist/UI/timeline.html +0 -1212
  36. package/dist/docs/browser-support.html +0 -826
  37. package/dist/docs/color-mode.html +0 -1142
  38. package/dist/docs/components/main-header.html +0 -1209
  39. package/dist/docs/components/main-sidebar.html +0 -924
  40. package/dist/docs/customization.html +0 -1080
  41. package/dist/docs/deployment.html +0 -1145
  42. package/dist/docs/faq.html +0 -1392
  43. package/dist/docs/getting-started.html +0 -991
  44. package/dist/docs/how-to-contribute.html +0 -890
  45. package/dist/docs/index.html +0 -16
  46. package/dist/docs/integrations.html +0 -1231
  47. package/dist/docs/introduction.html +0 -1008
  48. package/dist/docs/javascript/accessibility.html +0 -949
  49. package/dist/docs/javascript/card-widget.html +0 -1019
  50. package/dist/docs/javascript/direct-chat.html +0 -896
  51. package/dist/docs/javascript/fullscreen.html +0 -905
  52. package/dist/docs/javascript/layout.html +0 -908
  53. package/dist/docs/javascript/plugins-overview.html +0 -1144
  54. package/dist/docs/javascript/pushmenu.html +0 -1045
  55. package/dist/docs/javascript/treeview.html +0 -1024
  56. package/dist/docs/layout-blueprint.html +0 -1087
  57. package/dist/docs/layout.html +0 -842
  58. package/dist/docs/license.html +0 -807
  59. package/dist/docs/migration.html +0 -1149
  60. package/dist/docs/recipes.html +0 -1185
  61. package/dist/docs/rtl.html +0 -957
  62. package/dist/examples/lockscreen.html +0 -249
  63. package/dist/examples/login-v2.html +0 -282
  64. package/dist/examples/login.html +0 -272
  65. package/dist/examples/register-v2.html +0 -291
  66. package/dist/examples/register.html +0 -277
  67. package/dist/forms/elements.html +0 -1405
  68. package/dist/forms/layout.html +0 -1267
  69. package/dist/forms/validation.html +0 -1275
  70. package/dist/forms/wizard.html +0 -1410
  71. package/dist/generate/theme.html +0 -1082
  72. package/dist/index.html +0 -1745
  73. package/dist/index2.html +0 -2277
  74. package/dist/index3.html +0 -1532
  75. package/dist/layout/collapsed-sidebar-without-hover.html +0 -1144
  76. package/dist/layout/collapsed-sidebar.html +0 -1137
  77. package/dist/layout/fixed-complete.html +0 -1138
  78. package/dist/layout/fixed-footer.html +0 -1136
  79. package/dist/layout/fixed-header.html +0 -1136
  80. package/dist/layout/fixed-sidebar.html +0 -1138
  81. package/dist/layout/layout-custom-area.html +0 -1177
  82. package/dist/layout/layout-rtl.html +0 -1137
  83. package/dist/layout/logo-switch.html +0 -683
  84. package/dist/layout/sidebar-mini.html +0 -1137
  85. package/dist/layout/unfixed-sidebar.html +0 -1136
  86. package/dist/mailbox/compose.html +0 -1151
  87. package/dist/mailbox/inbox.html +0 -1509
  88. package/dist/mailbox/read.html +0 -1202
  89. package/dist/pages/404.html +0 -239
  90. package/dist/pages/500.html +0 -227
  91. package/dist/pages/calendar.html +0 -1266
  92. package/dist/pages/chat.html +0 -1427
  93. package/dist/pages/faq.html +0 -1383
  94. package/dist/pages/file-manager.html +0 -1835
  95. package/dist/pages/invoice.html +0 -1199
  96. package/dist/pages/kanban.html +0 -1439
  97. package/dist/pages/maintenance.html +0 -230
  98. package/dist/pages/pricing.html +0 -1279
  99. package/dist/pages/profile.html +0 -1382
  100. package/dist/pages/projects.html +0 -1644
  101. package/dist/pages/settings.html +0 -1387
  102. package/dist/tables/data.html +0 -1319
  103. package/dist/tables/simple.html +0 -1435
  104. package/dist/widgets/cards.html +0 -1356
  105. package/dist/widgets/info-box.html +0 -1429
  106. package/dist/widgets/small-box.html +0 -1225
  107. package/eslint.config.js +0 -82
  108. package/github-issue-response.md +0 -40
  109. package/index.html +0 -12
  110. package/netlify.toml +0 -16
@@ -1,369 +1,90 @@
1
- # AdminLTE Accessibility Compliance - WCAG 2.1 AA
1
+ # AdminLTE Accessibility Statement
2
2
 
3
3
  ## Overview
4
4
 
5
- AdminLTE has been enhanced with comprehensive accessibility features to meet **WCAG 2.1 AA** standards. This implementation ensures the template is usable by all users, including those with disabilities who may use assistive technologies like screen readers, keyboard navigation, or voice control software.
5
+ AdminLTE 4 is built with accessibility in mind and aims for **WCAG 2.1 AA** conformance. This document describes honestly what is implemented today, what is partially implemented, and what is still on the roadmap β€” so you know exactly what you get and what your application still needs to provide.
6
6
 
7
- ## 🎯 WCAG 2.1 AA Compliance Features
7
+ > **Important:** a template can only ever be a starting point. Accessible markup in the demo pages does not make your application compliant β€” you remain responsible for testing the pages you build.
8
8
 
9
- ### **Principle 1: Perceivable**
9
+ ## βœ… Implemented
10
10
 
11
- #### 1.1 Text Alternatives
12
- - βœ… **All decorative icons have `aria-hidden="true"`**
13
- - βœ… **Meaningful images have appropriate `alt` text**
14
- - βœ… **Icon fonts use screen reader friendly approaches**
11
+ ### Markup (demo pages)
15
12
 
16
- #### 1.3 Adaptable
17
- - βœ… **Semantic HTML structure with proper landmarks**
18
- - βœ… **Form labels properly associated with inputs**
19
- - βœ… **Table headers have correct `scope` attributes**
20
- - βœ… **Lists use proper `<ul>`, `<ol>`, `<li>` structure**
21
- - βœ… **Heading hierarchy follows logical order (h1 β†’ h2 β†’ h3)**
13
+ - Semantic landmark structure on the app shell (`<nav>`, `<main>`, `<aside>`, `<footer>`) β€” non-list `.nav` containers receive `role="navigation"` automatically (#6038)
14
+ - Exactly one `<h1>` per page (the page title in the content header)
15
+ - Breadcrumbs wrapped in `<nav aria-label="breadcrumb">` with `aria-current="page"`
16
+ - `aria-label` on all icon-only controls (card tools, topbar toggles, sidebar toggle)
17
+ - Form inputs associated with `<label>` elements (visually hidden where the design is placeholder-driven, floating labels on the v2 auth pages)
18
+ - Table headers with `scope` attributes
19
+ - `lang="en"` declared, descriptive page titles, `meta name="color-scheme"`
22
20
 
23
- #### 1.4 Distinguishable
24
- - βœ… **Color contrast ratios meet 4.5:1 minimum for normal text**
25
- - βœ… **Color contrast ratios meet 3:1 minimum for large text**
26
- - βœ… **Information not conveyed by color alone**
27
- - βœ… **Text can be resized up to 200% without loss of functionality**
28
- - βœ… **Focus indicators are clearly visible**
21
+ ### Behavior (`accessibility.ts` and components)
29
22
 
30
- ### **Principle 2: Operable**
23
+ - **Live region announcements** (WCAG 4.1.3) β€” a single polite `#live-region`, with a public `announce()` API; alerts inserted into the DOM are announced automatically
24
+ - **Skip links** to main content and navigation, injected once and reused across Turbo navigations (WCAG 2.4.1)
25
+ - **Treeview state exposure** β€” sidebar submenu toggles carry `aria-expanded`, kept in sync by the Treeview component
26
+ - **Modal focus restoration** β€” the triggering element is captured on `show.bs.modal` and restored on close (skipped if it has left the document)
27
+ - **Escape** closes open dropdowns; Bootstrap's own modal keyboard handling is left untouched
28
+ - **Arrow-key navigation** in menus and dropdowns β€” only when focus is on a menu item; never intercepts keys inside inputs, textareas, selects, or contenteditable elements
29
+ - **Reduced motion** β€” `prefers-reduced-motion` disables smooth scrolling and shortens animations; `prefers-contrast: more` styles in the CSS
30
+ - **Theme-flash prevention** and dark mode via Bootstrap color modes, respecting `prefers-color-scheme` (#6043)
31
+ - **Form error identification** (WCAG 3.3.1/3.3.2) β€” validation errors get an `invalid-feedback` node wired via `aria-describedby` (appended to existing descriptions, not replacing them) and are announced assertively
31
32
 
32
- #### 2.1 Keyboard Accessible
33
- - βœ… **All interactive elements are keyboard accessible**
34
- - βœ… **Tab order is logical and predictable**
35
- - βœ… **No keyboard traps exist**
36
- - βœ… **Skip links to bypass repetitive content**
37
- - βœ… **Arrow key navigation for menus**
38
- - βœ… **Escape key closes modals and dropdowns**
33
+ ### Explicit non-goals
39
34
 
40
- #### 2.2 Enough Time
41
- - βœ… **No time limits on user interactions**
42
- - βœ… **Animations can be paused or disabled**
35
+ - **No global focus wrapping.** Focus is deliberately *not* trapped at the page edges β€” wrapping Tab at the document boundary would itself violate WCAG 2.1.2 (No Keyboard Trap). Focus trapping is applied only inside modal dialogs.
43
36
 
44
- #### 2.3 Seizures and Physical Reactions
45
- - βœ… **No content flashes more than 3 times per second**
46
- - βœ… **Respects `prefers-reduced-motion` user preference**
47
- - βœ… **Animation duration can be controlled**
37
+ ## ⚠️ Partial / known gaps
48
38
 
49
- #### 2.4 Navigable
50
- - βœ… **Skip links to main content and navigation**
51
- - βœ… **Descriptive page titles**
52
- - βœ… **Meaningful link text (no "click here")**
53
- - βœ… **Focus order matches visual order**
54
- - βœ… **Focus is clearly visible**
55
- - βœ… **Multiple ways to navigate (menus, breadcrumbs, search)**
39
+ These are known, tracked limitations β€” pull requests welcome:
56
40
 
57
- #### 2.5 Input Modalities
58
- - βœ… **Touch targets are at least 44Γ—44 pixels**
59
- - βœ… **Drag operations have keyboard alternatives**
60
- - βœ… **Touch gestures have alternatives**
41
+ - **Treeview and push-menu have no dedicated keyboard interaction pattern** beyond normal Tab/Enter link behavior (no roving tabindex, no Home/End within the tree). `aria-expanded` is stamped by JS; static markup without JS does not carry it.
42
+ - **Drag-and-drop demos (kanban, sortable dashboard cards) have no keyboard alternative.** SortableJS does not provide one; treat these demos as visual examples only (WCAG 2.5.7 gap).
43
+ - **Touch target sizes are not enforced globally.** Card tool buttons are smaller than 44Γ—44 px; an opt-in `.touch-target` utility class exists in `_accessibility.scss`.
44
+ - **Color contrast is not guaranteed for every Bootstrap color utility combination** you may compose. The `accessibilityUtils.checkColorContrast()` helper (supports `rgb()`/hex) can verify your combinations.
45
+ - **No automated accessibility tests run in CI yet** (axe/pa11y integration is on the roadmap). Claims in this document are verified manually and are point-in-time.
61
46
 
62
- ### **Principle 3: Understandable**
47
+ ## πŸ”§ JavaScript API
63
48
 
64
- #### 3.1 Readable
65
- - βœ… **Language of page is declared (`lang="en"`)**
66
- - βœ… **Language changes are marked up**
67
- - βœ… **Unusual words have definitions or explanations**
68
-
69
- #### 3.2 Predictable
70
- - βœ… **Navigation is consistent across pages**
71
- - βœ… **Components behave predictably**
72
- - βœ… **Form submission doesn't cause unexpected context changes**
73
-
74
- #### 3.3 Input Assistance
75
- - βœ… **Error messages are clearly identified**
76
- - βœ… **Form field requirements are indicated**
77
- - βœ… **Error suggestions are provided when possible**
78
- - βœ… **Form validation messages are announced to screen readers**
79
-
80
- ### **Principle 4: Robust**
81
-
82
- #### 4.1 Compatible
83
- - βœ… **Valid HTML markup**
84
- - βœ… **Proper ARIA attributes and roles**
85
- - βœ… **Compatible with assistive technologies**
86
- - βœ… **Status messages are announced (`aria-live` regions)**
87
-
88
- ## πŸ› οΈ Implementation Details
89
-
90
- ### **Skip Links Implementation**
91
- ```html
92
- <!-- Automatically added by accessibility.js -->
93
- <div class="skip-links">
94
- <a href="#main" class="skip-link">Skip to main content</a>
95
- <a href="#navigation" class="skip-link">Skip to navigation</a>
96
- </div>
97
- ```
98
-
99
- ### **ARIA Live Regions**
100
- ```html
101
- <!-- Automatically created for status announcements -->
102
- <div id="live-region" class="live-region" aria-live="polite" aria-atomic="true" role="status"></div>
103
- ```
104
-
105
- ### **Enhanced Focus Management**
106
- - **Modal Focus Trap**: Focus is contained within modals
107
- - **Dropdown Navigation**: Arrow keys navigate menu items
108
- - **Focus Restoration**: Previous focus restored when modals close
109
- - **Escape Key Support**: ESC closes modals and dropdowns
110
-
111
- ### **Form Accessibility**
112
- ```html
113
- <!-- Example of accessible form with error handling -->
114
- <div class="mb-3">
115
- <label for="email" class="form-label">
116
- Email address <span class="required-indicator sr-only">(required)</span>
117
- </label>
118
- <input type="email" class="form-control" id="email" required aria-describedby="email-help email-error">
119
- <div id="email-help" class="form-text">We'll never share your email with anyone else.</div>
120
- <div id="email-error" class="invalid-feedback" role="alert"></div>
121
- </div>
122
- ```
123
-
124
- ### **Table Accessibility**
125
- ```html
126
- <!-- Accessible table structure -->
127
- <table class="table table-accessible" role="table">
128
- <caption>Monthly Sales Data</caption>
129
- <thead>
130
- <tr>
131
- <th scope="col">Month</th>
132
- <th scope="col">Sales</th>
133
- <th scope="col">Growth</th>
134
- </tr>
135
- </thead>
136
- <tbody>
137
- <tr>
138
- <th scope="row">January</th>
139
- <td>$10,000</td>
140
- <td>+5%</td>
141
- </tr>
142
- </tbody>
143
- </table>
144
- ```
145
-
146
- ### **Navigation Landmarks**
147
- ```html
148
- <!-- Semantic navigation structure -->
149
- <nav role="navigation" aria-label="Main navigation" id="navigation">
150
- <ul class="navbar-nav">
151
- <li class="nav-item">
152
- <a href="#" class="nav-link"
153
- role="button"
154
- data-bs-toggle="collapse"
155
- data-bs-target="#widgets-nav"
156
- aria-expanded="false"
157
- aria-controls="widgets-nav"
158
- aria-label="Toggle widgets menu">
159
- <i class="nav-icon bi bi-box-seam" aria-hidden="true"></i>
160
- <p>Widgets <i class="nav-arrow bi bi-chevron-right" aria-hidden="true"></i></p>
161
- </a>
162
- <ul id="widgets-nav" class="nav nav-treeview collapse" role="group" aria-labelledby="widgets-nav">
163
- <!-- Submenu items -->
164
- </ul>
165
- </li>
166
- </ul>
167
- </nav>
168
- ```
169
-
170
- ## 🎨 Accessible Color Palette
171
-
172
- ### **High Contrast Colors (4.5:1 ratio minimum)**
173
- - **Primary Accessible**: `#003d82` (4.5:1 on white)
174
- - **Success Accessible**: `#0f5132` (4.5:1 on white)
175
- - **Danger Accessible**: `#842029` (4.5:1 on white)
176
- - **Warning Accessible**: `#664d03` (4.5:1 on white)
177
-
178
- ### **Dark Mode Support**
179
- ```css
180
- [data-bs-theme="dark"] {
181
- .text-accessible-primary { color: #6ea8fe; }
182
- .text-accessible-success { color: #75b798; }
183
- .text-accessible-danger { color: #f1aeb5; }
184
- .text-accessible-warning { color: #ffda6a; }
185
- }
186
- ```
187
-
188
- ## πŸ“± Responsive & Touch Accessibility
189
-
190
- ### **Touch Target Sizes**
191
- - **Standard buttons**: Minimum 44Γ—44 pixels
192
- - **Icon buttons**: Minimum 44Γ—44 pixels touch area
193
- - **Small interactive elements**: Minimum 24Γ—24 pixels (when grouped)
194
-
195
- ### **Responsive Considerations**
196
- - **Zoom support**: Up to 200% zoom without horizontal scrolling
197
- - **Mobile navigation**: Touch-friendly collapsible menus
198
- - **Orientation support**: Works in both portrait and landscape
199
-
200
- ## πŸ”§ JavaScript Accessibility API
201
-
202
- ### **AccessibilityManager Class**
203
49
  ```typescript
204
- import { initAccessibility } from './accessibility.js'
50
+ import { initAccessibility, accessibilityUtils } from 'admin-lte'
205
51
 
206
- // Initialize with full features
207
- const accessibilityManager = initAccessibility({
208
- announcements: true,
209
- skipLinks: true,
210
- focusManagement: true,
211
- keyboardNavigation: true,
212
- reducedMotion: true
213
- })
214
-
215
- // Public API methods
216
- accessibilityManager.announce("Form submitted successfully", "polite")
217
- accessibilityManager.focusElement("#main-content")
218
- accessibilityManager.trapFocus(modalElement)
219
- ```
220
-
221
- ### **Utility Functions**
222
- ```typescript
223
- import { accessibilityUtils } from './accessibility.js'
224
-
225
- // Check color contrast
226
- const contrast = accessibilityUtils.checkColorContrast("#000000", "#ffffff")
227
- console.log(contrast) // { ratio: 21, passes: true }
228
-
229
- // Generate unique IDs
230
- const id = accessibilityUtils.generateId("form-field") // "form-field-abc123def"
231
-
232
- // Check if element is focusable
233
- const isFocusable = accessibilityUtils.isFocusable(element) // true/false
234
- ```
235
-
236
- ## πŸ§ͺ Testing & Validation
237
-
238
- ### **Automated Testing Tools**
239
- - **axe-core**: Automated accessibility testing
240
- - **WAVE**: Web accessibility evaluation
241
- - **Lighthouse**: Accessibility audit included
242
-
243
- ### **Manual Testing Checklist**
244
- - [ ] Navigate entire interface using only keyboard
245
- - [ ] Test with screen reader (NVDA, JAWS, VoiceOver)
246
- - [ ] Verify color contrast ratios
247
- - [ ] Test with 200% zoom
248
- - [ ] Verify reduced motion preferences
249
- - [ ] Test touch interactions on mobile
250
-
251
- ### **Screen Reader Testing**
252
- ```bash
253
- # Test announcements
254
- accessibilityManager.announce("New message received", "assertive")
255
-
256
- # Test form errors
257
- <input type="email" required aria-describedby="email-error">
258
- <div id="email-error" role="alert">Please enter a valid email address</div>
259
- ```
260
-
261
- ## πŸ“š Browser Support
262
-
263
- ### **Modern Browser Support (ES2022 Compatible)**
264
- - **Chrome**: 97+ (97% coverage)
265
- - **Firefox**: 104+ (95% coverage)
266
- - **Safari**: 15.4+ (92% coverage)
267
- - **Edge**: 97+ (94% coverage)
268
-
269
- ### **Assistive Technology Support**
270
- - **JAWS**: 2020+
271
- - **NVDA**: 2020+
272
- - **VoiceOver**: macOS 10.15+, iOS 13+
273
- - **Dragon NaturallySpeaking**: 15+
274
-
275
- ## πŸš€ Performance Impact
276
-
277
- ### **Bundle Size Impact**
278
- - **CSS**: +12KB (compressed)
279
- - **JavaScript**: +8KB (compressed)
280
- - **Total Impact**: ~20KB additional payload
281
-
282
- ### **Runtime Performance**
283
- - **Initialization**: ~5ms on modern devices
284
- - **Focus Management**: <1ms per interaction
285
- - **Announcements**: <1ms per message
286
-
287
- ## πŸ“– Usage Examples
288
-
289
- ### **Basic Setup**
290
- ```html
291
- <!DOCTYPE html>
292
- <html lang="en">
293
- <head>
294
- <!-- Enhanced accessibility meta tags -->
295
- <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
296
- <meta name="color-scheme" content="light dark">
297
- <!-- AdminLTE CSS with accessibility styles -->
298
- <link rel="stylesheet" href="dist/css/adminlte.css">
299
- </head>
300
- <body>
301
- <!-- Skip links automatically added -->
302
- <!-- Main content with proper landmarks -->
303
- <main id="main" role="main">
304
- <!-- Your content -->
305
- </main>
306
-
307
- <!-- AdminLTE JS with accessibility features -->
308
- <script src="dist/js/adminlte.js"></script>
309
- </body>
310
- </html>
311
- ```
312
-
313
- ### **Custom Configuration**
314
- ```javascript
315
- // Initialize with custom settings
316
52
  const accessibility = initAccessibility({
317
- announcements: true, // Enable screen reader announcements
318
- skipLinks: true, // Add skip navigation links
319
- focusManagement: true, // Enhanced focus handling
320
- keyboardNavigation: true, // Arrow key navigation
321
- reducedMotion: false // Disable if animations are critical
53
+ announcements: true, // live region + automatic alert announcements
54
+ skipLinks: true, // inject skip links
55
+ focusManagement: true, // modal focus restore, Escape handling
56
+ keyboardNavigation: true, // arrow keys in menus
57
+ reducedMotion: true // respect prefers-reduced-motion
322
58
  })
323
59
 
324
- // Add custom announcements
325
- accessibility.announce("Data saved successfully", "polite")
60
+ accessibility.announce('Data saved successfully', 'polite')
61
+ accessibility.focusElement('#error-summary')
62
+ accessibility.trapFocus(customDialogElement) // for non-Bootstrap dialogs
326
63
 
327
- // Focus specific elements
328
- accessibility.focusElement("#error-summary")
64
+ // Contrast checking (rgb() and hex supported)
65
+ accessibilityUtils.checkColorContrast('#000000', '#ffffff') // { ratio: 21, passes: true }
329
66
  ```
330
67
 
331
- ## πŸ”„ Future Enhancements
332
-
333
- ### **Roadmap for Additional Features**
334
- - [ ] Voice navigation support
335
- - [ ] Enhanced keyboard shortcuts
336
- - [ ] Customizable contrast themes
337
- - [ ] Advanced screen reader optimization
338
- - [ ] Internationalization (i18n) support
339
- - [ ] Right-to-left (RTL) accessibility improvements
340
-
341
- ### **Community Contributions**
342
- We welcome contributions to improve accessibility further. Please:
343
- 1. Follow WCAG 2.1 AA guidelines
344
- 2. Test with multiple assistive technologies
345
- 3. Document any new features thoroughly
346
- 4. Include automated tests where possible
68
+ The module is initialized automatically by `adminlte.js`. All document-level listeners are registered against the Turbo lifecycle signal, so Hotwired Turbo navigations neither leak listeners nor duplicate injected nodes.
347
69
 
348
- ---
70
+ ## πŸ§ͺ How to test your pages
349
71
 
350
- ## πŸ“ž Support & Resources
72
+ - **Automated:** [axe-core](https://github.com/dequelabs/axe-core), [WAVE](https://wave.webaim.org/), Lighthouse accessibility audit
73
+ - **Keyboard:** navigate your entire flow with Tab/Shift+Tab/Enter/Escape only; confirm focus is always visible and never trapped
74
+ - **Screen readers:** [NVDA](https://www.nvaccess.org/) (Windows, free), VoiceOver (macOS/iOS), JAWS
75
+ - **Zoom:** verify layouts at 200% zoom and 320px viewport width
76
+ - **Motion:** enable "reduce motion" in your OS and confirm animations calm down
351
77
 
352
- ### **Documentation**
353
- - [WCAG 2.1 Guidelines](https://www.w3.org/WAI/WCAG21/quickref/)
354
- - [ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/)
355
- - [WebAIM Resources](https://webaim.org/)
356
-
357
- ### **Testing Tools**
358
- - [axe-core](https://github.com/dequelabs/axe-core)
359
- - [WAVE Web Accessibility Evaluator](https://wave.webaim.org/)
360
- - [Lighthouse Accessibility](https://developers.google.com/web/tools/lighthouse/)
78
+ ## πŸ—ΊοΈ Roadmap
361
79
 
362
- ### **Screen Readers**
363
- - [NVDA (Free)](https://www.nvaccess.org/)
364
- - [JAWS (Commercial)](https://www.freedomscientific.com/products/software/jaws/)
365
- - [VoiceOver (Built-in on macOS/iOS)](https://support.apple.com/guide/voiceover/)
80
+ - axe/pa11y checks in CI against the built demo pages
81
+ - Keyboard interaction pattern (roving tabindex) for the sidebar treeview
82
+ - `aria-expanded`/`aria-controls` in the static demo markup (not only JS-stamped)
83
+ - Audit and document contrast for all shipped color variants
84
+ - RTL accessibility review
366
85
 
367
- ---
86
+ ## πŸ“š Resources
368
87
 
369
- **AdminLTE v4.0.0** - Now with comprehensive WCAG 2.1 AA accessibility compliance! πŸŽ‰
88
+ - [WCAG 2.1 Guidelines](https://www.w3.org/WAI/WCAG21/quickref/)
89
+ - [ARIA Authoring Practices Guide](https://www.w3.org/WAI/ARIA/apg/)
90
+ - [WebAIM](https://webaim.org/)
package/CHANGELOG.md CHANGED
@@ -7,6 +7,49 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [4.0.4] - 2026-07-02
11
+
12
+ ### Added
13
+
14
+ - **Forgot-password example page** β€” both login pages have linked `forgot-password.html` since 4.0.0, but the page didn't exist (dead link in every deployed demo). Now shipped and listed in the sidebar under Examples β€Ί Version 1.
15
+ - **Treeview exposes its state to assistive tech:** submenu toggle links now carry `aria-expanded`, stamped on init and kept in sync on open/close.
16
+
17
+ ### Fixed
18
+
19
+ - **npm packaging:** the package is now built from a `files` allowlist instead of the `.npmignore` denylist. Stray local files can no longer leak into the tarball (4.0.2 shipped an untracked working file this way), and the demo/docs HTML β€” which SECURITY.md advises never to deploy β€” is no longer published to npm. Unpacked size drops from 12.7 MB to 9.0 MB (177 β†’ 95 files). Also declares `engines: node >= 20`.
20
+ - **CSS bundles shipped the docs-site styles twice:** `_docs.scss` was imported from both `adminlte.scss` and `parts/_core.scss`, and Sass `@import` duplicates output β€” ~23 KB of dead weight in each of the four dist stylesheets.
21
+ - **Accessibility module keyboard handling:**
22
+ - removed the document-edge Tab wrap β€” it acted as a page-level keyboard trap (WCAG 2.1.2), preventing keyboard users from ever tabbing out to the browser chrome
23
+ - arrow keys are no longer intercepted inside inputs, textareas, selects, or contenteditable elements (typing in a navbar search field used to yank focus into the menu), and menu arrow-navigation only engages when focus is actually on a menu item
24
+ - modal focus restore now captures the triggering element on `show.bs.modal` (capturing on `shown` stored an element inside the modal, so closing dropped focus to `<body>`); `[autofocus]` is respected
25
+ - **Hotwired Turbo no longer duplicates injected DOM:** the skip links, `#live-region`, and sidebar overlay are now reused when a restored `<body>` snapshot already contains them β€” previously they accumulated one copy per navigation.
26
+ - **Card widget:** `remove()` now actually removes the card from the DOM after the animation (it only hid it, so hidden form fields kept submitting); clicking the collapse toggle mid-animation reverses it instead of being swallowed; widget events now dispatch on the toggle button itself rather than a clicked `<i>` icon; `minimize()` cleans up its inline styles.
27
+ - **Slide animations are cancelable:** rapid-toggling a treeview or card no longer lets a stale animation timer strip styles mid-flight and desync display state.
28
+ - **Treeview accordion guard** compared each open item against the parent `<ul>` (never true), so `open()` on an already-open item slid its own menu shut.
29
+ - **PushMenu** reacts to viewport changes via `matchMedia` on the actual breakpoint crossing β€” mobile URL-bar/keyboard resizes and same-side width changes no longer re-expand a sidebar the user collapsed; the default breakpoint (991.98) now matches the CSS convention, fixing a 992px off-by-one.
30
+ - **Callout variants** referenced two custom properties that were never defined, so links and inline code inside callouts never recolored; the user-menu footer used `--bs-light-bg`, which doesn't exist in Bootstrap 5.3 (now `--bs-tertiary-bg`).
31
+ - **Demo pages:** Bootstrap JS CDN pin updated 5.3.7 β†’ 5.3.8 to match the compiled CSS; removed the dead navbar-search button (`data-widget="navbar-search"` has no implementation in v4); every page now has exactly one `<h1>` (page titles were `<h3>`); breadcrumbs are wrapped in `<nav aria-label="breadcrumb">`; all icon-only buttons (card tools, topbar toggles) have `aria-label`s; auth forms have real `<label>`s and `<main>` landmarks; dated "Google+" copy updated.
32
+
33
+ ### Changed
34
+
35
+ - **ACCESSIBILITY-COMPLIANCE.md rewritten as an accurate accessibility statement** β€” what's implemented, what's partial (treeview keyboard pattern, drag-and-drop alternatives, touch-target sizes), and what's on the roadmap β€” replacing the aspirational all-checked WCAG checklist. Demo meta descriptions updated to match.
36
+ - **bundlewatch budgets recalibrated:** CSS budgets tightened (46 β†’ 44 kB min+gzip) to lock in the docs-dedup win; JS budget raised (5.8 β†’ 6.5 kB) for the behavior fixes above.
37
+
38
+ ## [4.0.3] - 2026-07-01
39
+
40
+ ### Added
41
+
42
+ - **Hotwired Turbo / Turbo Drive support:** plugins now re-initialise on `turbo:load`, so PushMenu, TreeView and the other JS components keep working after Turbo swaps the `<body>` on in-app navigation (previously they went dead after the first link click). Each init cycle uses an `AbortController` whose signal is aborted on `turbo:before-render`, so the `window`/`document`-level listeners are torn down before re-init instead of stacking up on every navigation. (#563, #5890 β€” diagnosed and prototyped by @MarkDaleman in #6058)
43
+
44
+ ### Fixed
45
+
46
+ - **Fullscreen state sync:** the fullscreen icons and the `maximized`/`minimized` events are now driven by the native `fullscreenchange` event instead of the request/exit calls. The UI no longer flips when a fullscreen request is denied (permissions policy, missing `allowfullscreen`, lost user gesture), and it now stays in sync when the user exits with `ESC` or `F11`. (builds on @webgo-oss's report in #6055)
47
+ - **Accessibility:** form inputs lacking both an `id` and a `name` now receive a stable, generated error-message id instead of colliding on a shared `-error` id and appending a new orphaned error node on every re-validation. (#6055, reported by @webgo-oss)
48
+
49
+ ### Updated
50
+
51
+ - All dependencies bumped to their latest releases, including four majors β€” **Astro 6 β†’ 7** (which pulls in Vite 8), **@astrojs/mdx 6 β†’ 7**, **eslint-plugin-astro 1 β†’ 2**, and **eslint-plugin-unicorn 68 β†’ 69** β€” plus ESLint, Prettier, Stylelint, PostCSS, Rollup and typescript-eslint. No source changes were required; the full `npm run production` pipeline (lint + Astro build + bundlewatch) passes and `npm audit` remains at **0 vulnerabilities**. (supersedes Dependabot PRs #6065–#6074)
52
+
10
53
  ## [4.0.2] - 2026-06-11
11
54
 
12
55
  ### Fixed
package/README.md CHANGED
@@ -31,14 +31,22 @@ large desktops, and it's MIT-licensed.
31
31
  The same AdminLTE 4 dashboard, officially integrated for the framework you know best β€”
32
32
  you're looking at the **HTML / Bootstrap** core:
33
33
 
34
- <p align="center">
34
+ <!-- ADMINLTE-ECOSYSTEM:START -->
35
+ <div align="center">
36
+ <a href="https://github.com/ColorlibHQ/AdminLTE"><img height="36" alt="HTML" src="https://img.shields.io/badge/HTML-0D6EFD?style=for-the-badge&logo=html5&logoColor=white"></a>
35
37
  <a href="https://github.com/ColorlibHQ/adminlte-react"><img height="36" alt="React" src="https://img.shields.io/badge/React-20232A?style=for-the-badge&logo=react&logoColor=61DAFB"></a>
36
38
  <a href="https://github.com/ColorlibHQ/adminlte-react"><img height="36" alt="Next.js" src="https://img.shields.io/badge/Next.js-000000?style=for-the-badge&logo=nextdotjs&logoColor=white"></a>
37
39
  <a href="https://github.com/ColorlibHQ/adminlte-vue"><img height="36" alt="Vue" src="https://img.shields.io/badge/Vue.js-35495E?style=for-the-badge&logo=vuedotjs&logoColor=4FC08D"></a>
38
40
  <a href="https://github.com/ColorlibHQ/adminlte-vue"><img height="36" alt="Nuxt" src="https://img.shields.io/badge/Nuxt-00DC82?style=for-the-badge&logo=nuxt&logoColor=white"></a>
41
+ <a href="https://github.com/ColorlibHQ/adminlte-angular"><img height="36" alt="Angular" src="https://img.shields.io/badge/Angular-DD0031?style=for-the-badge&logo=angular&logoColor=white"></a>
39
42
  <a href="https://github.com/ColorlibHQ/adminlte-laravel"><img height="36" alt="Laravel" src="https://img.shields.io/badge/Laravel-FF2D20?style=for-the-badge&logo=laravel&logoColor=white"></a>
43
+ <a href="https://github.com/ColorlibHQ/adminlte-symfony"><img height="36" alt="Symfony" src="https://img.shields.io/badge/Symfony-000000?style=for-the-badge&logo=symfony&logoColor=white"></a>
40
44
  <a href="https://github.com/ColorlibHQ/adminlte-django"><img height="36" alt="Django" src="https://img.shields.io/badge/Django-092E20?style=for-the-badge&logo=django&logoColor=white"></a>
41
- </p>
45
+ <a href="https://github.com/ColorlibHQ/adminlte-aspnet"><img height="36" alt="ASP.NET" src="https://img.shields.io/badge/ASP.NET-512BD4?style=for-the-badge&logo=dotnet&logoColor=white"></a>
46
+ <a href="https://github.com/ColorlibHQ/adminlte-drupal"><img height="36" alt="Drupal" src="https://img.shields.io/badge/Drupal-0678BE?style=for-the-badge&logo=drupal&logoColor=white"></a>
47
+ <a href="https://docs.adminlte.io"><img height="36" alt="Docs" src="https://img.shields.io/badge/Docs-adminlte.io-0EA5E9?style=for-the-badge&logo=readthedocs&logoColor=white"></a>
48
+ </div>
49
+ <!-- ADMINLTE-ECOSYSTEM:END -->
42
50
 
43
51
  | Edition | Repository | Live demo | Install |
44
52
  |---|---|---|---|
@@ -47,6 +55,11 @@ you're looking at the **HTML / Bootstrap** core:
47
55
  | **Vue 3 & Nuxt** β€” 45+ typed components, composables, SSR-safe theming | [adminlte-vue](https://github.com/ColorlibHQ/adminlte-vue) | [themes/vue-nuxt](https://adminlte.io/themes/vue-nuxt/) | see repo |
48
56
  | **Laravel** β€” Blade components, config-driven menu, auth scaffolding | [adminlte-laravel](https://github.com/ColorlibHQ/adminlte-laravel) | [laravel.adminlte.io](https://laravel.adminlte.io/) | `composer require colorlibhq/adminlte-laravel` |
49
57
  | **Django** β€” reusable app, menu filter pipeline, themed admin | [adminlte-django](https://github.com/ColorlibHQ/adminlte-django) | [django.adminlte.io](https://django.adminlte.io/) | `pip install django-adminlte4` |
58
+ | **Symfony** β€” Twig Components, AssetMapper, config-driven menu, EasyAdmin theme | [adminlte-symfony](https://github.com/ColorlibHQ/adminlte-symfony) | see repo | `composer require colorlibhq/adminlte-symfony` |
59
+ | **Angular 22** β€” 44 standalone signal components, dark mode, ⌘K palette | [adminlte-angular](https://github.com/ColorlibHQ/adminlte-angular) | see repo | `npm i @adminlte/angular` |
60
+ | **ASP.NET Core (.NET 10)** β€” Blazor components + MVC/Razor Pages Tag Helpers | [adminlte-aspnet](https://github.com/ColorlibHQ/adminlte-aspnet) | see repo | `dotnet add package ColorlibHQ.AdminLTE.AspNetCore` |
61
+ | **Drupal** β€” admin theme for Drupal 10.3+/11, themed admin UI | [adminlte-drupal](https://github.com/ColorlibHQ/adminlte-drupal) | see repo | see repo |
62
+ | **Docs** β€” guides, components, and API reference for every edition | [docs.adminlte.io](https://docs.adminlte.io) | [docs.adminlte.io](https://docs.adminlte.io) | β€” |
50
63
 
51
64
  Every edition ships the full AdminLTE 4 design β€” Bootstrap 5.3, dark mode, RTL β€” with
52
65
  idiomatic integrations for its stack (components, routing, auth, theming).