@techsio/storybook-better-a11y 0.0.6 → 0.0.7
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/dist/{visionSimulatorFilters.js → 100.js} +23 -1
- package/dist/{apcaChecker.js → 699.js} +253 -1
- package/dist/index.js +6 -5
- package/dist/manager.js +1540 -11
- package/dist/postinstall.js +1 -1
- package/dist/preview.js +1 -68
- package/dist/rslib-runtime.js +37 -0
- package/package.json +1 -1
- package/dist/AccessibilityRuleMaps.js +0 -532
- package/dist/a11yRunner.js +0 -105
- package/dist/a11yRunner.test.js +0 -21
- package/dist/a11yRunnerUtils.js +0 -30
- package/dist/a11yRunnerUtils.test.js +0 -61
- package/dist/apcaChecker.test.js +0 -124
- package/dist/axeRuleMappingHelper.js +0 -4
- package/dist/components/A11YPanel.js +0 -140
- package/dist/components/A11YPanel.stories.js +0 -198
- package/dist/components/A11YPanel.test.js +0 -110
- package/dist/components/A11yContext.js +0 -438
- package/dist/components/A11yContext.test.js +0 -277
- package/dist/components/Report/Details.js +0 -169
- package/dist/components/Report/Report.js +0 -106
- package/dist/components/Report/Report.stories.js +0 -86
- package/dist/components/Tabs.js +0 -54
- package/dist/components/TestDiscrepancyMessage.js +0 -55
- package/dist/components/TestDiscrepancyMessage.stories.js +0 -40
- package/dist/components/VisionSimulator.js +0 -83
- package/dist/components/VisionSimulator.stories.js +0 -56
- package/dist/constants.js +0 -25
- package/dist/manager.test.js +0 -86
- package/dist/params.js +0 -0
- package/dist/preview.test.js +0 -215
- package/dist/results.mock.js +0 -874
- package/dist/types.js +0 -6
- package/dist/utils.js +0 -21
- package/dist/withVisionSimulator.js +0 -41
package/dist/a11yRunner.js
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { ElementA11yParameterError } from "storybook/internal/preview-errors";
|
|
2
|
-
import { global } from "@storybook/global";
|
|
3
|
-
import { addons, waitForAnimations } from "storybook/preview-api";
|
|
4
|
-
import { withLinkPaths } from "./a11yRunnerUtils.js";
|
|
5
|
-
import { runAPCACheck } from "./apcaChecker.js";
|
|
6
|
-
import { EVENTS } from "./constants.js";
|
|
7
|
-
const { document: a11yRunner_document } = global;
|
|
8
|
-
const channel = addons.getChannel();
|
|
9
|
-
const DEFAULT_PARAMETERS = {
|
|
10
|
-
config: {},
|
|
11
|
-
options: {}
|
|
12
|
-
};
|
|
13
|
-
const DISABLED_RULES = [
|
|
14
|
-
'region'
|
|
15
|
-
];
|
|
16
|
-
const queue = [];
|
|
17
|
-
let isRunning = false;
|
|
18
|
-
const runNext = async ()=>{
|
|
19
|
-
if (0 === queue.length) {
|
|
20
|
-
isRunning = false;
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
isRunning = true;
|
|
24
|
-
const next = queue.shift();
|
|
25
|
-
if (next) await next();
|
|
26
|
-
runNext();
|
|
27
|
-
};
|
|
28
|
-
const run = async (input = DEFAULT_PARAMETERS, storyId)=>{
|
|
29
|
-
const axeCore = await import("axe-core");
|
|
30
|
-
const axe = axeCore?.default || globalThis.axe;
|
|
31
|
-
const { config = {}, options = {} } = input;
|
|
32
|
-
if (input.element) throw new ElementA11yParameterError();
|
|
33
|
-
const context = {
|
|
34
|
-
include: a11yRunner_document?.body,
|
|
35
|
-
exclude: [
|
|
36
|
-
'.sb-wrapper',
|
|
37
|
-
'#storybook-docs',
|
|
38
|
-
'#storybook-highlights-root'
|
|
39
|
-
]
|
|
40
|
-
};
|
|
41
|
-
if (input.context) {
|
|
42
|
-
const hasInclude = 'object' == typeof input.context && 'include' in input.context && void 0 !== input.context.include;
|
|
43
|
-
const hasExclude = 'object' == typeof input.context && 'exclude' in input.context && void 0 !== input.context.exclude;
|
|
44
|
-
if (hasInclude) context.include = input.context.include;
|
|
45
|
-
else if (!hasInclude && !hasExclude) context.include = input.context;
|
|
46
|
-
if (hasExclude) context.exclude = context.exclude.concat(input.context.exclude);
|
|
47
|
-
}
|
|
48
|
-
axe.reset();
|
|
49
|
-
const configWithDefault = {
|
|
50
|
-
...config,
|
|
51
|
-
rules: [
|
|
52
|
-
...DISABLED_RULES.map((id)=>({
|
|
53
|
-
id,
|
|
54
|
-
enabled: false
|
|
55
|
-
})),
|
|
56
|
-
...config?.rules ?? []
|
|
57
|
-
]
|
|
58
|
-
};
|
|
59
|
-
axe.configure(configWithDefault);
|
|
60
|
-
return new Promise((resolve, reject)=>{
|
|
61
|
-
const highlightsRoot = a11yRunner_document?.getElementById('storybook-highlights-root');
|
|
62
|
-
if (highlightsRoot) highlightsRoot.style.display = 'none';
|
|
63
|
-
const task = async ()=>{
|
|
64
|
-
try {
|
|
65
|
-
const result = await axe.run(context, options);
|
|
66
|
-
let contextElement = a11yRunner_document;
|
|
67
|
-
if (context.include instanceof Element) contextElement = context.include;
|
|
68
|
-
else if (Array.isArray(context.include)) {
|
|
69
|
-
const first = context.include[0];
|
|
70
|
-
if (first instanceof Element) contextElement = first;
|
|
71
|
-
else if ('string' == typeof first) contextElement = a11yRunner_document.querySelector(first) || a11yRunner_document;
|
|
72
|
-
} else if ('string' == typeof context.include) contextElement = a11yRunner_document.querySelector(context.include) || a11yRunner_document;
|
|
73
|
-
const excludeSelectors = Array.isArray(context.exclude) ? context.exclude.filter((value)=>'string' == typeof value) : 'string' == typeof context.exclude ? [
|
|
74
|
-
context.exclude
|
|
75
|
-
] : [];
|
|
76
|
-
const apcaResult = await runAPCACheck(contextElement, input.apca, excludeSelectors);
|
|
77
|
-
if (apcaResult.nodes.length > 0) result.violations.push(apcaResult);
|
|
78
|
-
else result.passes.push(apcaResult);
|
|
79
|
-
const resultWithLinks = withLinkPaths(result, storyId);
|
|
80
|
-
globalThis.__TECHSIO_A11Y_RESULTS__ = {
|
|
81
|
-
storyId,
|
|
82
|
-
results: resultWithLinks,
|
|
83
|
-
timestamp: Date.now()
|
|
84
|
-
};
|
|
85
|
-
resolve(resultWithLinks);
|
|
86
|
-
} catch (error) {
|
|
87
|
-
reject(error);
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
queue.push(task);
|
|
91
|
-
if (!isRunning) runNext();
|
|
92
|
-
if (highlightsRoot) highlightsRoot.style.display = '';
|
|
93
|
-
});
|
|
94
|
-
};
|
|
95
|
-
channel.on(EVENTS.MANUAL, async (storyId, input = DEFAULT_PARAMETERS)=>{
|
|
96
|
-
try {
|
|
97
|
-
await waitForAnimations();
|
|
98
|
-
const result = await run(input, storyId);
|
|
99
|
-
const resultJson = JSON.parse(JSON.stringify(result));
|
|
100
|
-
channel.emit(EVENTS.RESULT, resultJson, storyId);
|
|
101
|
-
} catch (error) {
|
|
102
|
-
channel.emit(EVENTS.ERROR, error);
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
export { run };
|
package/dist/a11yRunner.test.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
-
import { addons } from "storybook/preview-api";
|
|
3
|
-
import { EVENTS } from "./constants.js";
|
|
4
|
-
vi.mock('storybook/preview-api');
|
|
5
|
-
const mockedAddons = vi.mocked(addons);
|
|
6
|
-
describe('a11yRunner', ()=>{
|
|
7
|
-
let mockChannel;
|
|
8
|
-
beforeEach(()=>{
|
|
9
|
-
mockedAddons.getChannel.mockReset();
|
|
10
|
-
mockChannel = {
|
|
11
|
-
on: vi.fn(),
|
|
12
|
-
emit: vi.fn()
|
|
13
|
-
};
|
|
14
|
-
mockedAddons.getChannel.mockReturnValue(mockChannel);
|
|
15
|
-
});
|
|
16
|
-
it('should listen to events', async ()=>{
|
|
17
|
-
await import("./a11yRunner.js");
|
|
18
|
-
expect(mockedAddons.getChannel).toHaveBeenCalled();
|
|
19
|
-
expect(mockChannel.on).toHaveBeenCalledWith(EVENTS.MANUAL, expect.any(Function));
|
|
20
|
-
});
|
|
21
|
-
});
|
package/dist/a11yRunnerUtils.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { global } from "@storybook/global";
|
|
2
|
-
import { PANEL_ID } from "./constants.js";
|
|
3
|
-
const { document: a11yRunnerUtils_document } = global;
|
|
4
|
-
const withLinkPaths = (results, storyId)=>{
|
|
5
|
-
const pathname = a11yRunnerUtils_document.location.pathname.replace(/iframe\.html$/, '');
|
|
6
|
-
const enhancedResults = {
|
|
7
|
-
...results
|
|
8
|
-
};
|
|
9
|
-
const propertiesToAugment = [
|
|
10
|
-
'incomplete',
|
|
11
|
-
'passes',
|
|
12
|
-
'violations'
|
|
13
|
-
];
|
|
14
|
-
propertiesToAugment.forEach((key)=>{
|
|
15
|
-
if (Array.isArray(results[key])) enhancedResults[key] = results[key].map((result)=>({
|
|
16
|
-
...result,
|
|
17
|
-
nodes: result.nodes.map((node, index)=>{
|
|
18
|
-
const id = `${key}.${result.id}.${index + 1}`;
|
|
19
|
-
const linkPath = `${pathname}?path=/story/${storyId}&addonPanel=${PANEL_ID}&a11ySelection=${id}`;
|
|
20
|
-
return {
|
|
21
|
-
id,
|
|
22
|
-
...node,
|
|
23
|
-
linkPath
|
|
24
|
-
};
|
|
25
|
-
})
|
|
26
|
-
}));
|
|
27
|
-
});
|
|
28
|
-
return enhancedResults;
|
|
29
|
-
};
|
|
30
|
-
export { withLinkPaths };
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { withLinkPaths } from "./a11yRunnerUtils.js";
|
|
3
|
-
describe('a11yRunnerUtils', ()=>{
|
|
4
|
-
describe('withLinkPaths', ()=>{
|
|
5
|
-
it('should add link paths to the axe results', ()=>{
|
|
6
|
-
const axeResults = {
|
|
7
|
-
violations: [
|
|
8
|
-
{
|
|
9
|
-
id: 'color-contrast',
|
|
10
|
-
nodes: [
|
|
11
|
-
{
|
|
12
|
-
html: '<button>Click me</button>',
|
|
13
|
-
target: [
|
|
14
|
-
'.button'
|
|
15
|
-
]
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
html: '<a href="#">Link</a>',
|
|
19
|
-
target: [
|
|
20
|
-
'.link'
|
|
21
|
-
]
|
|
22
|
-
}
|
|
23
|
-
]
|
|
24
|
-
}
|
|
25
|
-
],
|
|
26
|
-
passes: [
|
|
27
|
-
{
|
|
28
|
-
id: 'button-name',
|
|
29
|
-
nodes: [
|
|
30
|
-
{
|
|
31
|
-
html: '<button>Valid Button</button>',
|
|
32
|
-
target: [
|
|
33
|
-
'.valid-button'
|
|
34
|
-
]
|
|
35
|
-
}
|
|
36
|
-
]
|
|
37
|
-
}
|
|
38
|
-
],
|
|
39
|
-
incomplete: [
|
|
40
|
-
{
|
|
41
|
-
id: 'aria-valid',
|
|
42
|
-
nodes: [
|
|
43
|
-
{
|
|
44
|
-
html: '<div aria-label="test">Test</div>',
|
|
45
|
-
target: [
|
|
46
|
-
'.aria-test'
|
|
47
|
-
]
|
|
48
|
-
}
|
|
49
|
-
]
|
|
50
|
-
}
|
|
51
|
-
],
|
|
52
|
-
inapplicable: []
|
|
53
|
-
};
|
|
54
|
-
const result = withLinkPaths(axeResults, 'test-story-id');
|
|
55
|
-
expect(result.violations[0].nodes[0].linkPath).toBe('/?path=/story/test-story-id&addonPanel=storybook/a11y/panel&a11ySelection=violations.color-contrast.1');
|
|
56
|
-
expect(result.violations[0].nodes[1].linkPath).toBe('/?path=/story/test-story-id&addonPanel=storybook/a11y/panel&a11ySelection=violations.color-contrast.2');
|
|
57
|
-
expect(result.passes[0].nodes[0].linkPath).toBe('/?path=/story/test-story-id&addonPanel=storybook/a11y/panel&a11ySelection=passes.button-name.1');
|
|
58
|
-
expect(result.incomplete[0].nodes[0].linkPath).toBe('/?path=/story/test-story-id&addonPanel=storybook/a11y/panel&a11ySelection=incomplete.aria-valid.1');
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
});
|
package/dist/apcaChecker.test.js
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
2
|
-
import { runAPCACheck } from "./apcaChecker.js";
|
|
3
|
-
describe('apcaChecker', ()=>{
|
|
4
|
-
let container;
|
|
5
|
-
beforeEach(()=>{
|
|
6
|
-
container = document.createElement('div');
|
|
7
|
-
document.body.appendChild(container);
|
|
8
|
-
});
|
|
9
|
-
afterEach(()=>{
|
|
10
|
-
if (container.parentNode) container.parentNode.removeChild(container);
|
|
11
|
-
});
|
|
12
|
-
it('should detect low contrast text violations', async ()=>{
|
|
13
|
-
const textElement = document.createElement('p');
|
|
14
|
-
textElement.textContent = 'This is test text';
|
|
15
|
-
textElement.style.color = 'rgb(170, 170, 170)';
|
|
16
|
-
textElement.style.backgroundColor = 'rgb(255, 255, 255)';
|
|
17
|
-
textElement.style.fontSize = '16px';
|
|
18
|
-
textElement.style.fontWeight = '400';
|
|
19
|
-
container.appendChild(textElement);
|
|
20
|
-
const result = await runAPCACheck(container);
|
|
21
|
-
expect(result.id).toBe('apca-contrast');
|
|
22
|
-
expect(result.nodes.length).toBeGreaterThan(0);
|
|
23
|
-
expect(result.nodes[0].failureSummary).toContain('Fix any of the following');
|
|
24
|
-
expect(result.nodes[0].failureSummary).toContain('APCA contrast');
|
|
25
|
-
});
|
|
26
|
-
it('should pass for high contrast text', async ()=>{
|
|
27
|
-
const textElement = document.createElement('p');
|
|
28
|
-
textElement.textContent = 'This is test text';
|
|
29
|
-
textElement.style.color = 'rgb(0, 0, 0)';
|
|
30
|
-
textElement.style.backgroundColor = 'rgb(255, 255, 255)';
|
|
31
|
-
textElement.style.fontSize = '16px';
|
|
32
|
-
textElement.style.fontWeight = '400';
|
|
33
|
-
container.appendChild(textElement);
|
|
34
|
-
const result = await runAPCACheck(container);
|
|
35
|
-
expect(result.id).toBe('apca-contrast');
|
|
36
|
-
expect(result.nodes.length).toBe(0);
|
|
37
|
-
});
|
|
38
|
-
it('should skip hidden elements', async ()=>{
|
|
39
|
-
const textElement = document.createElement('p');
|
|
40
|
-
textElement.textContent = 'This is test text';
|
|
41
|
-
textElement.style.color = 'rgb(170, 170, 170)';
|
|
42
|
-
textElement.style.backgroundColor = 'rgb(255, 255, 255)';
|
|
43
|
-
textElement.style.display = 'none';
|
|
44
|
-
container.appendChild(textElement);
|
|
45
|
-
const result = await runAPCACheck(container);
|
|
46
|
-
expect(result.nodes.length).toBe(0);
|
|
47
|
-
});
|
|
48
|
-
it('should skip aria-hidden elements', async ()=>{
|
|
49
|
-
const textElement = document.createElement('p');
|
|
50
|
-
textElement.textContent = 'This is test text';
|
|
51
|
-
textElement.style.color = 'rgb(170, 170, 170)';
|
|
52
|
-
textElement.style.backgroundColor = 'rgb(255, 255, 255)';
|
|
53
|
-
textElement.setAttribute('aria-hidden', 'true');
|
|
54
|
-
container.appendChild(textElement);
|
|
55
|
-
const result = await runAPCACheck(container);
|
|
56
|
-
expect(result.nodes.length).toBe(0);
|
|
57
|
-
});
|
|
58
|
-
it('should use appropriate thresholds for large text', async ()=>{
|
|
59
|
-
const textElement = document.createElement('h1');
|
|
60
|
-
textElement.textContent = 'Large Heading';
|
|
61
|
-
textElement.style.color = 'rgb(100, 100, 100)';
|
|
62
|
-
textElement.style.backgroundColor = 'rgb(255, 255, 255)';
|
|
63
|
-
textElement.style.fontSize = '32px';
|
|
64
|
-
textElement.style.fontWeight = '400';
|
|
65
|
-
container.appendChild(textElement);
|
|
66
|
-
const result = await runAPCACheck(container);
|
|
67
|
-
expect(result.id).toBe('apca-contrast');
|
|
68
|
-
});
|
|
69
|
-
it('should handle elements with inherited background colors', async ()=>{
|
|
70
|
-
const parent = document.createElement('div');
|
|
71
|
-
parent.style.backgroundColor = 'rgb(200, 200, 200)';
|
|
72
|
-
container.appendChild(parent);
|
|
73
|
-
const textElement = document.createElement('p');
|
|
74
|
-
textElement.textContent = 'Nested text';
|
|
75
|
-
textElement.style.color = 'rgb(180, 180, 180)';
|
|
76
|
-
textElement.style.fontSize = '16px';
|
|
77
|
-
parent.appendChild(textElement);
|
|
78
|
-
const result = await runAPCACheck(container);
|
|
79
|
-
expect(result.id).toBe('apca-contrast');
|
|
80
|
-
});
|
|
81
|
-
it('should enforce gold minimum font size for body text', async ()=>{
|
|
82
|
-
const textElement = document.createElement('p');
|
|
83
|
-
textElement.textContent = 'Small body text';
|
|
84
|
-
textElement.style.color = 'rgb(0, 0, 0)';
|
|
85
|
-
textElement.style.backgroundColor = 'rgb(255, 255, 255)';
|
|
86
|
-
textElement.style.fontSize = '12px';
|
|
87
|
-
textElement.style.fontWeight = '400';
|
|
88
|
-
container.appendChild(textElement);
|
|
89
|
-
const result = await runAPCACheck(container, {
|
|
90
|
-
level: 'gold',
|
|
91
|
-
useCase: 'body'
|
|
92
|
-
});
|
|
93
|
-
expect(result.nodes.length).toBeGreaterThan(0);
|
|
94
|
-
expect(result.nodes[0].failureSummary).toContain('minimum 16px');
|
|
95
|
-
});
|
|
96
|
-
it('should flag excessive contrast for large text at silver', async ()=>{
|
|
97
|
-
const textElement = document.createElement('h1');
|
|
98
|
-
textElement.textContent = 'Large heading';
|
|
99
|
-
textElement.style.color = 'rgb(0, 0, 0)';
|
|
100
|
-
textElement.style.backgroundColor = 'rgb(255, 255, 255)';
|
|
101
|
-
textElement.style.fontSize = '40px';
|
|
102
|
-
textElement.style.fontWeight = '400';
|
|
103
|
-
container.appendChild(textElement);
|
|
104
|
-
const result = await runAPCACheck(container, {
|
|
105
|
-
level: 'silver',
|
|
106
|
-
useCase: 'body'
|
|
107
|
-
});
|
|
108
|
-
expect(result.nodes.length).toBeGreaterThan(0);
|
|
109
|
-
expect(result.nodes[0].failureSummary).toContain('exceeds the maximum');
|
|
110
|
-
});
|
|
111
|
-
it('should include proper metadata in results', async ()=>{
|
|
112
|
-
const textElement = document.createElement('p');
|
|
113
|
-
textElement.textContent = 'Test';
|
|
114
|
-
textElement.style.color = 'rgb(170, 170, 170)';
|
|
115
|
-
textElement.style.backgroundColor = 'rgb(255, 255, 255)';
|
|
116
|
-
container.appendChild(textElement);
|
|
117
|
-
const result = await runAPCACheck(container);
|
|
118
|
-
expect(result.id).toBe('apca-contrast');
|
|
119
|
-
expect(result.tags).toContain('wcag3');
|
|
120
|
-
expect(result.tags).toContain('apca');
|
|
121
|
-
expect(result.description).toContain('APCA');
|
|
122
|
-
expect(result.helpUrl).toBeTruthy();
|
|
123
|
-
});
|
|
124
|
-
});
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { combinedRulesMap } from "./AccessibilityRuleMaps.js";
|
|
2
|
-
const getTitleForAxeResult = (axeResult)=>combinedRulesMap[axeResult.id]?.title || axeResult.id;
|
|
3
|
-
const getFriendlySummaryForAxeResult = (axeResult)=>combinedRulesMap[axeResult.id]?.friendlySummary || axeResult.description;
|
|
4
|
-
export { getFriendlySummaryForAxeResult, getTitleForAxeResult };
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import react, { useMemo } from "react";
|
|
2
|
-
import { Badge, Button } from "storybook/internal/components";
|
|
3
|
-
import { SyncIcon } from "@storybook/icons";
|
|
4
|
-
import { styled } from "storybook/theming";
|
|
5
|
-
import { RuleType } from "../types.js";
|
|
6
|
-
import { useA11yContext } from "./A11yContext.js";
|
|
7
|
-
import { Report } from "./Report/Report.js";
|
|
8
|
-
import { Tabs } from "./Tabs.js";
|
|
9
|
-
import { TestDiscrepancyMessage } from "./TestDiscrepancyMessage.js";
|
|
10
|
-
const RotatingIcon = styled(SyncIcon)(({ theme })=>({
|
|
11
|
-
animation: `${theme.animation.rotate360} 1s linear infinite;`,
|
|
12
|
-
margin: 4
|
|
13
|
-
}));
|
|
14
|
-
const Tab = styled.div({
|
|
15
|
-
display: 'flex',
|
|
16
|
-
alignItems: 'center',
|
|
17
|
-
gap: 6
|
|
18
|
-
});
|
|
19
|
-
const Centered = styled.span(({ theme })=>({
|
|
20
|
-
display: 'flex',
|
|
21
|
-
flexDirection: 'column',
|
|
22
|
-
alignItems: 'center',
|
|
23
|
-
justifyContent: 'center',
|
|
24
|
-
textAlign: 'center',
|
|
25
|
-
fontSize: theme.typography.size.s2,
|
|
26
|
-
height: '100%',
|
|
27
|
-
gap: 24,
|
|
28
|
-
div: {
|
|
29
|
-
display: 'flex',
|
|
30
|
-
flexDirection: 'column',
|
|
31
|
-
alignItems: 'center',
|
|
32
|
-
gap: 8
|
|
33
|
-
},
|
|
34
|
-
p: {
|
|
35
|
-
margin: 0,
|
|
36
|
-
color: theme.textMutedColor
|
|
37
|
-
},
|
|
38
|
-
code: {
|
|
39
|
-
display: 'inline-block',
|
|
40
|
-
fontSize: theme.typography.size.s2 - 1,
|
|
41
|
-
backgroundColor: theme.background.app,
|
|
42
|
-
border: `1px solid ${theme.color.border}`,
|
|
43
|
-
borderRadius: 4,
|
|
44
|
-
padding: '2px 3px'
|
|
45
|
-
}
|
|
46
|
-
}));
|
|
47
|
-
const A11YPanel = ()=>{
|
|
48
|
-
const { parameters, tab, results, status, handleManual, error, discrepancy, handleSelectionChange, selectedItems, toggleOpen } = useA11yContext();
|
|
49
|
-
const tabs = useMemo(()=>{
|
|
50
|
-
const { passes, incomplete, violations } = results ?? {
|
|
51
|
-
passes: [],
|
|
52
|
-
incomplete: [],
|
|
53
|
-
violations: []
|
|
54
|
-
};
|
|
55
|
-
return [
|
|
56
|
-
{
|
|
57
|
-
label: /*#__PURE__*/ react.createElement(Tab, null, "Violations", /*#__PURE__*/ react.createElement(Badge, {
|
|
58
|
-
compact: true,
|
|
59
|
-
status: 'violations' === tab ? 'active' : 'neutral'
|
|
60
|
-
}, violations.length)),
|
|
61
|
-
panel: /*#__PURE__*/ react.createElement(Report, {
|
|
62
|
-
items: violations,
|
|
63
|
-
type: RuleType.VIOLATION,
|
|
64
|
-
empty: "No accessibility violations found.",
|
|
65
|
-
handleSelectionChange: handleSelectionChange,
|
|
66
|
-
selectedItems: selectedItems,
|
|
67
|
-
toggleOpen: toggleOpen
|
|
68
|
-
}),
|
|
69
|
-
items: violations,
|
|
70
|
-
type: RuleType.VIOLATION
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
label: /*#__PURE__*/ react.createElement(Tab, null, "Passes", /*#__PURE__*/ react.createElement(Badge, {
|
|
74
|
-
compact: true,
|
|
75
|
-
status: 'passes' === tab ? 'active' : 'neutral'
|
|
76
|
-
}, passes.length)),
|
|
77
|
-
panel: /*#__PURE__*/ react.createElement(Report, {
|
|
78
|
-
items: passes,
|
|
79
|
-
type: RuleType.PASS,
|
|
80
|
-
empty: "No passing accessibility checks found.",
|
|
81
|
-
handleSelectionChange: handleSelectionChange,
|
|
82
|
-
selectedItems: selectedItems,
|
|
83
|
-
toggleOpen: toggleOpen
|
|
84
|
-
}),
|
|
85
|
-
items: passes,
|
|
86
|
-
type: RuleType.PASS
|
|
87
|
-
},
|
|
88
|
-
{
|
|
89
|
-
label: /*#__PURE__*/ react.createElement(Tab, null, "Inconclusive", /*#__PURE__*/ react.createElement(Badge, {
|
|
90
|
-
compact: true,
|
|
91
|
-
status: 'incomplete' === tab ? 'active' : 'neutral'
|
|
92
|
-
}, incomplete.length)),
|
|
93
|
-
panel: /*#__PURE__*/ react.createElement(Report, {
|
|
94
|
-
items: incomplete,
|
|
95
|
-
type: RuleType.INCOMPLETION,
|
|
96
|
-
empty: "No inconclusive accessibility checks found.",
|
|
97
|
-
handleSelectionChange: handleSelectionChange,
|
|
98
|
-
selectedItems: selectedItems,
|
|
99
|
-
toggleOpen: toggleOpen
|
|
100
|
-
}),
|
|
101
|
-
items: incomplete,
|
|
102
|
-
type: RuleType.INCOMPLETION
|
|
103
|
-
}
|
|
104
|
-
];
|
|
105
|
-
}, [
|
|
106
|
-
tab,
|
|
107
|
-
results,
|
|
108
|
-
handleSelectionChange,
|
|
109
|
-
selectedItems,
|
|
110
|
-
toggleOpen
|
|
111
|
-
]);
|
|
112
|
-
if (parameters.disable || 'off' === parameters.test) return /*#__PURE__*/ react.createElement(Centered, null, /*#__PURE__*/ react.createElement("div", null, /*#__PURE__*/ react.createElement("strong", null, "Accessibility tests are disabled for this story"), /*#__PURE__*/ react.createElement("p", null, "Update", ' ', /*#__PURE__*/ react.createElement("code", null, parameters.disable ? 'parameters.a11y.disable' : 'parameters.a11y.test'), ' ', "to enable accessibility tests.")));
|
|
113
|
-
return /*#__PURE__*/ react.createElement(react.Fragment, null, discrepancy && /*#__PURE__*/ react.createElement(TestDiscrepancyMessage, {
|
|
114
|
-
discrepancy: discrepancy
|
|
115
|
-
}), 'ready' === status || 'ran' === status ? /*#__PURE__*/ react.createElement(Tabs, {
|
|
116
|
-
key: "tabs",
|
|
117
|
-
tabs: tabs
|
|
118
|
-
}) : /*#__PURE__*/ react.createElement(Centered, {
|
|
119
|
-
style: {
|
|
120
|
-
marginTop: discrepancy ? '1em' : 0
|
|
121
|
-
}
|
|
122
|
-
}, 'initial' === status && /*#__PURE__*/ react.createElement("div", null, /*#__PURE__*/ react.createElement(RotatingIcon, {
|
|
123
|
-
size: 12
|
|
124
|
-
}), /*#__PURE__*/ react.createElement("strong", null, "Preparing accessibility scan"), /*#__PURE__*/ react.createElement("p", null, "Please wait while the addon is initializing...")), 'manual' === status && /*#__PURE__*/ react.createElement(react.Fragment, null, /*#__PURE__*/ react.createElement("div", null, /*#__PURE__*/ react.createElement("strong", null, "Accessibility tests run manually for this story"), /*#__PURE__*/ react.createElement("p", null, "Results will not show when using the testing module. You can still run accessibility tests manually.")), /*#__PURE__*/ react.createElement(Button, {
|
|
125
|
-
ariaLabel: false,
|
|
126
|
-
size: "medium",
|
|
127
|
-
onClick: handleManual
|
|
128
|
-
}, "Run accessibility scan"), /*#__PURE__*/ react.createElement("p", null, "Update ", /*#__PURE__*/ react.createElement("code", null, "globals.a11y.manual"), " to disable manual mode.")), 'running' === status && /*#__PURE__*/ react.createElement("div", null, /*#__PURE__*/ react.createElement(RotatingIcon, {
|
|
129
|
-
size: 12
|
|
130
|
-
}), /*#__PURE__*/ react.createElement("strong", null, "Accessibility scan in progress"), /*#__PURE__*/ react.createElement("p", null, "Please wait while the accessibility scan is running...")), 'error' === status && /*#__PURE__*/ react.createElement(react.Fragment, null, /*#__PURE__*/ react.createElement("div", null, /*#__PURE__*/ react.createElement("strong", null, "The accessibility scan encountered an error"), /*#__PURE__*/ react.createElement("p", null, 'string' == typeof error ? error : error instanceof Error ? error.toString() : JSON.stringify(error, null, 2))), /*#__PURE__*/ react.createElement(Button, {
|
|
131
|
-
ariaLabel: false,
|
|
132
|
-
size: "medium",
|
|
133
|
-
onClick: handleManual
|
|
134
|
-
}, "Rerun accessibility scan")), 'component-test-error' === status && /*#__PURE__*/ react.createElement(react.Fragment, null, /*#__PURE__*/ react.createElement("div", null, /*#__PURE__*/ react.createElement("strong", null, "This story's component tests failed"), /*#__PURE__*/ react.createElement("p", null, "Automated accessibility tests will not run until this is resolved. You can still test manually.")), /*#__PURE__*/ react.createElement(Button, {
|
|
135
|
-
ariaLabel: false,
|
|
136
|
-
size: "medium",
|
|
137
|
-
onClick: handleManual
|
|
138
|
-
}, "Run accessibility scan"))));
|
|
139
|
-
};
|
|
140
|
-
export { A11YPanel };
|