aria-ease 7.5.0 → 7.8.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 +60 -75
- package/dist/ToggleComponentStrategy-TMRNXFSL.js +1 -0
- package/dist/cli.cjs +34 -34
- package/dist/cli.js +1 -1
- package/dist/{contractTestRunnerPlaywright-75NI6SN7.js → contractTestRunnerPlaywright-CJFYO766.js} +1 -1
- package/dist/{contractTestRunnerPlaywright-VLOD5IB3.js → contractTestRunnerPlaywright-OB2GWGOA.js} +1 -1
- package/dist/index.cjs +33 -33
- package/dist/index.d.cts +18 -14
- package/dist/index.d.ts +18 -14
- package/dist/index.js +10 -10
- package/dist/src/{Types.d-D96FYkCN.d.cts → Types.d-BjBTlIzl.d.cts} +18 -8
- package/dist/src/{Types.d-D96FYkCN.d.ts → Types.d-BjBTlIzl.d.ts} +18 -8
- package/dist/src/accordion/index.cjs +1 -1
- package/dist/src/accordion/index.d.cts +1 -1
- package/dist/src/accordion/index.d.ts +1 -1
- package/dist/src/accordion/index.js +1 -1
- package/dist/src/block/index.d.cts +1 -1
- package/dist/src/block/index.d.ts +1 -1
- package/dist/src/checkbox/index.cjs +1 -1
- package/dist/src/checkbox/index.d.cts +1 -1
- package/dist/src/checkbox/index.d.ts +1 -1
- package/dist/src/checkbox/index.js +1 -1
- package/dist/src/combobox/index.cjs +1 -1
- package/dist/src/combobox/index.d.cts +1 -1
- package/dist/src/combobox/index.d.ts +1 -1
- package/dist/src/combobox/index.js +1 -1
- package/dist/src/menu/index.cjs +1 -1
- package/dist/src/menu/index.d.cts +1 -1
- package/dist/src/menu/index.d.ts +1 -1
- package/dist/src/menu/index.js +1 -1
- package/dist/src/radio/index.cjs +1 -1
- package/dist/src/radio/index.d.cts +1 -1
- package/dist/src/radio/index.d.ts +1 -1
- package/dist/src/radio/index.js +1 -1
- package/dist/src/tabs/index.cjs +1 -1
- package/dist/src/tabs/index.d.cts +1 -2
- package/dist/src/tabs/index.d.ts +1 -2
- package/dist/src/tabs/index.js +1 -1
- package/dist/src/toggle/index.cjs +1 -1
- package/dist/src/toggle/index.d.cts +2 -7
- package/dist/src/toggle/index.d.ts +2 -7
- package/dist/src/toggle/index.js +1 -1
- package/dist/src/utils/test/ToggleComponentStrategy-UOGYK2U4.js +1 -0
- package/dist/src/utils/test/{contractTestRunnerPlaywright-FSZDW7IR.js → contractTestRunnerPlaywright-ZKVK7KUM.js} +1 -1
- package/dist/src/utils/test/dsl/index.cjs +1 -1
- package/dist/src/utils/test/dsl/index.js +1 -1
- package/dist/src/utils/test/index.cjs +14 -14
- package/dist/src/utils/test/index.d.cts +1 -0
- package/dist/src/utils/test/index.d.ts +1 -0
- package/dist/src/utils/test/index.js +1 -1
- package/dist/{test-FURQN5KO.js → test-TZFBWFCP.js} +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,12 +16,9 @@ Aria-Ease isn't a utility library. **It's an accessibility infrastructure** that
|
|
|
16
16
|
| Phase | Feature | Status | Impact |
|
|
17
17
|
| ------------------ | --------------------------------------------- | ------------ | --------------------------------------------- |
|
|
18
18
|
| **🔧 Development** | Component utilities for accessible patterns | ✅ Available | Build it right from the start |
|
|
19
|
-
| **⚡ Linting** | ESLint rules to enforce accessible coding | 🚧 Roadmap | Catch mistakes as you type |
|
|
20
19
|
| **🔍 Pre-Deploy** | Axe-core powered static accessibility audit | ✅ Available | Verify before it ships |
|
|
21
20
|
| **🧪 Testing** | WAI-ARIA APG contract testing with Playwright | ✅ Available | Fast, determinic component accessibility test |
|
|
22
21
|
| **🚀 CI/CD** | Accessibility as deployment gatekeeper | ✅ Available | Block inaccessible code from production |
|
|
23
|
-
| **📊 Production** | Real user signal monitoring and replay | 🚧 Roadmap | Understand how users actually interact |
|
|
24
|
-
| **📈 Insights** | Dashboard for reporting and analytics | 🚧 Roadmap | Visualize accessibility health |
|
|
25
22
|
|
|
26
23
|
---
|
|
27
24
|
|
|
@@ -31,16 +28,16 @@ Aria-Ease isn't a utility library. **It's an accessibility infrastructure** that
|
|
|
31
28
|
|
|
32
29
|
**Traditional approach:** Build features → Manual testing → Find accessibility issues → Fix them → Manual testing again → Ship (maybe)
|
|
33
30
|
|
|
34
|
-
**Aria-Ease approach:** Build with accessible baseline utilities → Automated audits catch issues → Contract tests verify consistent
|
|
31
|
+
**Aria-Ease approach:** Build with accessible baseline utilities → Automated audits catch issues → Contract tests verify consistent component behaviors → CI/CD gates deployment → Ship with confidence
|
|
35
32
|
|
|
36
33
|
### What Makes This Different?
|
|
37
34
|
|
|
38
|
-
#### 1. **Component Utilities**
|
|
35
|
+
#### 1. **Component Utilities**
|
|
39
36
|
|
|
40
37
|
Reusable accessible interaction patterns based on Aria-Ease's baseline interpretation of WAI-ARIA APG guidance. Not the only valid implementation, but a proven, consistent place to start. Tree-shakable, framework-agnostic, production-ready.
|
|
41
38
|
|
|
42
39
|
```javascript
|
|
43
|
-
// Instead of 50+ lines managing ARIA
|
|
40
|
+
// Instead of 50+ lines managing ARIA accessibility states and interactions...
|
|
44
41
|
import { makeMenuAccessible } from "aria-ease/menu";
|
|
45
42
|
|
|
46
43
|
const menu = makeMenuAccessible({
|
|
@@ -50,19 +47,19 @@ const menu = makeMenuAccessible({
|
|
|
50
47
|
}); // Arrow keys, Escape, focus management — all handled
|
|
51
48
|
```
|
|
52
49
|
|
|
53
|
-
#### 2. **Static Audit**
|
|
50
|
+
#### 2. **Static Audit**
|
|
54
51
|
|
|
55
|
-
Axe-core powered CLI that scans your entire site and generates
|
|
52
|
+
Axe-core powered CLI that scans your entire site and generates multi-format reports in HTML, CSV or JSON. Run it locally or in CI/CD.
|
|
56
53
|
|
|
57
54
|
```bash
|
|
58
55
|
npx aria-ease audit --url https://yoursite.com
|
|
59
56
|
```
|
|
60
57
|
|
|
61
|
-
#### 3. **Contract Testing**
|
|
58
|
+
#### 3. **Contract Testing**
|
|
62
59
|
|
|
63
60
|
This is the game-changer. Encode a deterministic, testable interpretation of WAI-ARIA APG guidance into JSON "contracts" using Aria-Ease DSL API, and validate your contract against your component using Aria-Ease's Playwright runner with isolated test-harness architecture. Run it locally or in CI/CD.
|
|
64
61
|
|
|
65
|
-
Teams and experts can enforce their own standards
|
|
62
|
+
Teams and experts can enforce their own standards, maintain reusability and consistency, and prevent regression.
|
|
66
63
|
|
|
67
64
|
**The result?** Component interaction testing that feels closer to unit testing than manual QA.
|
|
68
65
|
|
|
@@ -72,9 +69,9 @@ npx aria-ease test
|
|
|
72
69
|
# ✓ 26 assertions in ~1 second in CI
|
|
73
70
|
```
|
|
74
71
|
|
|
75
|
-
**Why this matters:** Before,
|
|
72
|
+
**Why this matters:** Before, testing for regression in combobox meant testing every interaction manually. Now, Aria-Ease automates the repeatable, deterministic aspects of testing a combobox: keyboard interaction, ARIA state updates, visibility, and semantic attributes.
|
|
76
73
|
|
|
77
|
-
#### 4. **CI/CD Integration**
|
|
74
|
+
#### 4. **CI/CD Integration**
|
|
78
75
|
|
|
79
76
|
Turn accessibility into a deployment invariant. Add audit and test commands to your pipeline — if they fail, deployment is blocked.
|
|
80
77
|
|
|
@@ -90,22 +87,10 @@ jobs:
|
|
|
90
87
|
# Only deploy if both pass ☝️
|
|
91
88
|
```
|
|
92
89
|
|
|
93
|
-
Real example from our docs site: Push to branch → Accessibility checks run → Green check mark → Deploys to
|
|
90
|
+
Real example from our docs site: Push to branch → Accessibility checks run → Green check mark → Deploys to Prod. Red X → Deploy blocked.
|
|
94
91
|
|
|
95
92
|
**No one has any excuse to ship inaccessible code anymore.**
|
|
96
93
|
|
|
97
|
-
#### 5. **Linting** (Roadmap)
|
|
98
|
-
|
|
99
|
-
ESLint rules that enforce accessible coding patterns as you type. Catch issues before they compile.
|
|
100
|
-
|
|
101
|
-
#### 6. **Production Monitoring** (Roadmap)
|
|
102
|
-
|
|
103
|
-
Real user signal monitoring, interaction replay, and analytics. Understand how assistive technology users actually experience your app.
|
|
104
|
-
|
|
105
|
-
#### 7. **Insights Dashboard** (Roadmap)
|
|
106
|
-
|
|
107
|
-
Visualize accessibility health across your entire application. Track progress, identify patterns, generate reports.
|
|
108
|
-
|
|
109
94
|
---
|
|
110
95
|
|
|
111
96
|
## ✨ Features
|
|
@@ -113,9 +98,9 @@ Visualize accessibility health across your entire application. Track progress, i
|
|
|
113
98
|
- 🎯 **Tree-shakable** - Import only what you need (1.4KB - 3.7KB per component)
|
|
114
99
|
- ♿ **WCAG Compliant** - Follows WAI-ARIA best practices
|
|
115
100
|
- ⌨️ **Keyboard Interaction** - Full keyboard support out of the box
|
|
116
|
-
- 🧪 **Contract Testing** - Built-in
|
|
101
|
+
- 🧪 **Contract Testing** - Built-in accessibility interaction testing framework
|
|
117
102
|
- 🎭 **Framework Agnostic** - Works with React, Vue, vanilla JS, etc.
|
|
118
|
-
- 🔍 **CLI Audit Tool** - Automated accessibility testing for your sites
|
|
103
|
+
- 🔍 **CLI Audit Tool** - Automated static accessibility testing for your sites
|
|
119
104
|
- 📦 **TypeScript Support** - Full type definitions included
|
|
120
105
|
|
|
121
106
|
## 📦 Installation
|
|
@@ -156,9 +141,7 @@ export default {
|
|
|
156
141
|
out: "./accessibility-reports",
|
|
157
142
|
},
|
|
158
143
|
},
|
|
159
|
-
test: {
|
|
160
|
-
strictness: "balanced", // 'minimal' | 'balanced' | 'strict' | 'paranoid'
|
|
161
|
-
},
|
|
144
|
+
test: {...},
|
|
162
145
|
};
|
|
163
146
|
```
|
|
164
147
|
|
|
@@ -180,7 +163,7 @@ The CLI will automatically find and load your config file, with validation to ca
|
|
|
180
163
|
|
|
181
164
|
### Contract DSL Build Workflow
|
|
182
165
|
|
|
183
|
-
You can author custom component contracts as readable DSL files and compile them with a built-in CLI command.
|
|
166
|
+
You can author custom component interaction contracts as readable DSL files and compile them with a built-in CLI command.
|
|
184
167
|
|
|
185
168
|
1. Create one or more `*.contract.mjs` files that export a contract built with `contract("component.name", ...)`.
|
|
186
169
|
2. Configure contract sources in `ariaease.config.js`.
|
|
@@ -191,16 +174,7 @@ Example config with multiple contract sources:
|
|
|
191
174
|
|
|
192
175
|
```javascript
|
|
193
176
|
export default {
|
|
194
|
-
test: {
|
|
195
|
-
strictness: "balanced",
|
|
196
|
-
components: [
|
|
197
|
-
{
|
|
198
|
-
name: "combobox",
|
|
199
|
-
path: "./tests/external-contracts/combobox.listbox.contract.json",
|
|
200
|
-
strategyPath: "./tests/external-strategies/CustomComboboxStrategy.js",
|
|
201
|
-
},
|
|
202
|
-
],
|
|
203
|
-
},
|
|
177
|
+
test: {...},
|
|
204
178
|
contracts: [
|
|
205
179
|
{
|
|
206
180
|
src: "./tests/external-contracts/**/*.contract.mjs",
|
|
@@ -296,6 +270,11 @@ useEffect(() => {
|
|
|
296
270
|
menuId: "menu-div",
|
|
297
271
|
menuItemsClass: "profile-menu-items",
|
|
298
272
|
triggerId: "display-button",
|
|
273
|
+
callback: {
|
|
274
|
+
onExpandedChange: (expanded) => {
|
|
275
|
+
// Side effect
|
|
276
|
+
},
|
|
277
|
+
},
|
|
299
278
|
});
|
|
300
279
|
|
|
301
280
|
return () => menuRef.current.cleanup(); // Clean up on unmount
|
|
@@ -311,6 +290,11 @@ const menu = Menu.makeMenuAccessible({
|
|
|
311
290
|
menuId: "dropdown-menu",
|
|
312
291
|
menuItemsClass: "menu-item",
|
|
313
292
|
triggerId: "menu-button",
|
|
293
|
+
callback: {
|
|
294
|
+
onExpandedChange: (expanded) => {
|
|
295
|
+
// Side effect
|
|
296
|
+
},
|
|
297
|
+
},
|
|
314
298
|
});
|
|
315
299
|
|
|
316
300
|
// Programmatically control
|
|
@@ -358,6 +342,12 @@ useEffect(() => {
|
|
|
358
342
|
comboboxInputId: "search-input",
|
|
359
343
|
listBoxId: "suggestions-list",
|
|
360
344
|
listBoxItemsClass: "suggestion-item",
|
|
345
|
+
callback: {
|
|
346
|
+
onSelect: (option) => {...} //when a listbox option is selected
|
|
347
|
+
onExpandedChange: (expanded) => {...} //when a combobox listbox opens or closes
|
|
348
|
+
onActiveDescendantChange: (optId, item) => {...} //when combobox aria-activedescendant changes
|
|
349
|
+
onClear: () => {...} //when combobox input (if present) is cleared by Escape key
|
|
350
|
+
}
|
|
361
351
|
});
|
|
362
352
|
|
|
363
353
|
return () => {
|
|
@@ -378,15 +368,11 @@ const combobox = Combobox.makeComboboxAccessible({
|
|
|
378
368
|
listBoxId: "fruits-listbox",
|
|
379
369
|
listBoxItemsClass: "list-option",
|
|
380
370
|
callback: {
|
|
381
|
-
onSelect: (option) => {
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
onOpenChange: (isOpen) => {
|
|
387
|
-
console.log("Listbox is", isOpen ? "open" : "closed");
|
|
388
|
-
},
|
|
389
|
-
},
|
|
371
|
+
onSelect: (option) => {...} //when a listbox option is selected
|
|
372
|
+
onExpandedChange: (expanded) => {...} //when a combobox listbox opens or closes
|
|
373
|
+
onActiveDescendantChange: (optId, item) => {...} //when combobox aria-activedescendant changes
|
|
374
|
+
onClear: () => {...} //when combobox input (if present) is cleared by Escape key
|
|
375
|
+
}
|
|
390
376
|
});
|
|
391
377
|
|
|
392
378
|
// Programmatically control
|
|
@@ -444,6 +430,9 @@ useEffect(() => {
|
|
|
444
430
|
triggersClass: "accordion-trigger",
|
|
445
431
|
panelsClass: "accordion-panel",
|
|
446
432
|
allowMultipleOpen: false, // Only one panel open at a time (default)
|
|
433
|
+
callback: {
|
|
434
|
+
onExpandedChange: (index, expanded) => {...}
|
|
435
|
+
}
|
|
447
436
|
});
|
|
448
437
|
|
|
449
438
|
return () => accordion.cleanup();
|
|
@@ -508,6 +497,9 @@ useEffect(() => {
|
|
|
508
497
|
const checkboxGroup = makeCheckboxAccessible({
|
|
509
498
|
checkboxGroupId: "checkbox-group",
|
|
510
499
|
checkboxesClass: "custom-checkbox",
|
|
500
|
+
callback: {
|
|
501
|
+
onCheckedChange: (index, checked) => {...}
|
|
502
|
+
}
|
|
511
503
|
});
|
|
512
504
|
|
|
513
505
|
return () => checkboxGroup.cleanup();
|
|
@@ -566,6 +558,9 @@ useEffect(() => {
|
|
|
566
558
|
radioGroupId: "radio-group",
|
|
567
559
|
radiosClass: "custom-radio",
|
|
568
560
|
defaultSelectedIndex: 0, // Initially selected (optional)
|
|
561
|
+
callback: {
|
|
562
|
+
onValueChange: (index, value) => {...}
|
|
563
|
+
}
|
|
569
564
|
});
|
|
570
565
|
|
|
571
566
|
return () => radioGroup.cleanup();
|
|
@@ -620,6 +615,11 @@ import { makeToggleAccessible } from "aria-ease/toggle";
|
|
|
620
615
|
const toggle = makeToggleAccessible({
|
|
621
616
|
toggleId: "mute-button",
|
|
622
617
|
isSingleToggle: true,
|
|
618
|
+
callback: {
|
|
619
|
+
onPressedChange: (pressed) => {
|
|
620
|
+
console.log("Toggle has pressed of value pressed");
|
|
621
|
+
},
|
|
622
|
+
},
|
|
623
623
|
});
|
|
624
624
|
|
|
625
625
|
// Toggle button group
|
|
@@ -627,6 +627,11 @@ const toggleGroup = makeToggleAccessible({
|
|
|
627
627
|
toggleId: "toolbar",
|
|
628
628
|
togglesClass: "toggle-btn",
|
|
629
629
|
isSingleToggle: false,
|
|
630
|
+
callback: {
|
|
631
|
+
onPressedChange: (index, pressed) => {
|
|
632
|
+
console.log("Toggle at index has pressed of value pressed");
|
|
633
|
+
},
|
|
634
|
+
},
|
|
630
635
|
});
|
|
631
636
|
|
|
632
637
|
// Programmatic control
|
|
@@ -701,8 +706,9 @@ afterAll(async () => {
|
|
|
701
706
|
describe("Shopify User Menu Accessibility Test", () => {
|
|
702
707
|
test("renders Shopify user menu without accessibility violation(s)", async () => {
|
|
703
708
|
await testUiComponent(
|
|
704
|
-
"menu",
|
|
705
|
-
|
|
709
|
+
"menu",
|
|
710
|
+
"http://localhost:5173/test-harness?component=menu",
|
|
711
|
+
);
|
|
706
712
|
});
|
|
707
713
|
});
|
|
708
714
|
```
|
|
@@ -765,7 +771,6 @@ Or override per test call:
|
|
|
765
771
|
```javascript
|
|
766
772
|
await testUiComponent(
|
|
767
773
|
"menu",
|
|
768
|
-
null,
|
|
769
774
|
"http://localhost:5173/test-harness?component=menu",
|
|
770
775
|
{
|
|
771
776
|
strictness: "strict",
|
|
@@ -788,7 +793,7 @@ Aria-Ease is designed to be lightweight and tree-shakable:
|
|
|
788
793
|
| `aria-ease/menu` | ~6.7KB |
|
|
789
794
|
| `aria-ease/block` | ~1.7KB |
|
|
790
795
|
| `aria-ease/combobox` | ~8.1KB |
|
|
791
|
-
| Full bundle (all components) | ~
|
|
796
|
+
| Full bundle (all components) | ~659KB (uncompressed) |
|
|
792
797
|
|
|
793
798
|
**💡 Tip:** Always import individual components for optimal bundle size:
|
|
794
799
|
|
|
@@ -820,27 +825,6 @@ useEffect(() => {
|
|
|
820
825
|
|
|
821
826
|
---
|
|
822
827
|
|
|
823
|
-
## 🎨 Focus Styling
|
|
824
|
-
|
|
825
|
-
Aria-Ease handles ARIA attributes and keyboard interaction, but **you must provide visible focus styles**:
|
|
826
|
-
|
|
827
|
-
```css
|
|
828
|
-
:focus {
|
|
829
|
-
outline: 2px solid rgba(0, 91, 211, 1);
|
|
830
|
-
outline-offset: 2px;
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
/* Or custom styles */
|
|
834
|
-
.menu-item:focus {
|
|
835
|
-
background: #e3f2fd;
|
|
836
|
-
box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.3);
|
|
837
|
-
}
|
|
838
|
-
```
|
|
839
|
-
|
|
840
|
-
Without visible focus indicators, keyboard users cannot tell which element is active.
|
|
841
|
-
|
|
842
|
-
---
|
|
843
|
-
|
|
844
828
|
## 🌐 Browser Support
|
|
845
829
|
|
|
846
830
|
Aria-Ease supports all modern browsers:
|
|
@@ -997,6 +981,7 @@ export default {
|
|
|
997
981
|
out: "./accessibility-reports",
|
|
998
982
|
},
|
|
999
983
|
},
|
|
984
|
+
test: {...}
|
|
1000
985
|
contracts: [
|
|
1001
986
|
{
|
|
1002
987
|
src: "./tests/external-contracts/**/*.contract.mjs",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as r}from"./chunk-SM6ZKEDR.js";import"./chunk-CNU4N4AY.js";var i=class{constructor(e,o,s=400,t=400){this.mainSelector=e;this.selectors=o;this.actionTimeoutMs=s;this.assertionTimeoutMs=t}async resetState(e){if(!this.selectors.toggle||!this.selectors.relative)return;let o=this.selectors.toggle;if(!o)return;let s=await e.locator(o).all();for(let t of s)if(await t.getAttribute("aria-pressed")==="true"){await t.click({timeout:this.actionTimeoutMs});let a=e.locator(`#${t}`);await(0,r.expect)(a).toHaveAttribute("aria-pressed","false",{timeout:this.assertionTimeoutMs}).catch(()=>{})}}async shouldSkipTest(){return!1}getMainSelector(){return this.mainSelector}};export{i as ToggleComponentStrategy};
|