@techsio/storybook-better-a11y 0.0.6 → 0.0.8

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 (36) hide show
  1. package/dist/{visionSimulatorFilters.js → 100.js} +23 -1
  2. package/dist/{apcaChecker.js → 699.js} +253 -1
  3. package/dist/index.js +6 -5
  4. package/dist/manager.js +1540 -11
  5. package/dist/postinstall.js +1 -1
  6. package/dist/preview.js +1 -68
  7. package/dist/rslib-runtime.js +37 -0
  8. package/package.json +1 -1
  9. package/dist/AccessibilityRuleMaps.js +0 -532
  10. package/dist/a11yRunner.js +0 -105
  11. package/dist/a11yRunner.test.js +0 -21
  12. package/dist/a11yRunnerUtils.js +0 -30
  13. package/dist/a11yRunnerUtils.test.js +0 -61
  14. package/dist/apcaChecker.test.js +0 -124
  15. package/dist/axeRuleMappingHelper.js +0 -4
  16. package/dist/components/A11YPanel.js +0 -140
  17. package/dist/components/A11YPanel.stories.js +0 -198
  18. package/dist/components/A11YPanel.test.js +0 -110
  19. package/dist/components/A11yContext.js +0 -438
  20. package/dist/components/A11yContext.test.js +0 -277
  21. package/dist/components/Report/Details.js +0 -169
  22. package/dist/components/Report/Report.js +0 -106
  23. package/dist/components/Report/Report.stories.js +0 -86
  24. package/dist/components/Tabs.js +0 -54
  25. package/dist/components/TestDiscrepancyMessage.js +0 -55
  26. package/dist/components/TestDiscrepancyMessage.stories.js +0 -40
  27. package/dist/components/VisionSimulator.js +0 -83
  28. package/dist/components/VisionSimulator.stories.js +0 -56
  29. package/dist/constants.js +0 -25
  30. package/dist/manager.test.js +0 -86
  31. package/dist/params.js +0 -0
  32. package/dist/preview.test.js +0 -215
  33. package/dist/results.mock.js +0 -874
  34. package/dist/types.js +0 -6
  35. package/dist/utils.js +0 -21
  36. package/dist/withVisionSimulator.js +0 -41
@@ -1,277 +0,0 @@
1
- import { act, cleanup, render } from "@testing-library/react";
2
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
3
- import { Fragment, createElement, useState } from "react";
4
- import { STORY_FINISHED, STORY_RENDER_PHASE_CHANGED } from "storybook/internal/core-events";
5
- import { EVENTS } from "../constants.js";
6
- import { A11yContextProvider, useA11yContext } from "./A11yContext.js";
7
- import * as __rspack_external_storybook_manager_api_d834c1f5 from "storybook/manager-api";
8
- vi.mock('storybook/manager-api');
9
- const mockedApi = vi.mocked(__rspack_external_storybook_manager_api_d834c1f5);
10
- const storyId = 'button--primary';
11
- const axeResult = {
12
- incomplete: [
13
- {
14
- id: 'color-contrast',
15
- impact: 'serious',
16
- tags: [],
17
- description: 'Ensures the contrast between foreground and background colors meets WCAG 2 AA contrast ratio thresholds',
18
- help: 'Elements must have sufficient color contrast',
19
- helpUrl: 'https://dequeuniversity.com/rules/axe/3.2/color-contrast?application=axeAPI',
20
- nodes: []
21
- }
22
- ],
23
- passes: [
24
- {
25
- id: 'aria-allowed-attr',
26
- impact: void 0,
27
- tags: [],
28
- description: "Ensures ARIA attributes are allowed for an element's role",
29
- help: 'Elements must only use allowed ARIA attributes',
30
- helpUrl: 'https://dequeuniversity.com/rules/axe/3.2/aria-allowed-attr?application=axeAPI',
31
- nodes: []
32
- }
33
- ],
34
- violations: [
35
- {
36
- id: 'color-contrast',
37
- impact: 'serious',
38
- tags: [],
39
- description: 'Ensures the contrast between foreground and background colors meets WCAG 2 AA contrast ratio thresholds',
40
- help: 'Elements must have sufficient color contrast',
41
- helpUrl: 'https://dequeuniversity.com/rules/axe/3.2/color-contrast?application=axeAPI',
42
- nodes: []
43
- }
44
- ]
45
- };
46
- describe('A11yContext', ()=>{
47
- afterEach(()=>{
48
- cleanup();
49
- });
50
- const onAllStatusChange = vi.fn();
51
- const getAll = vi.fn();
52
- const set = vi.fn();
53
- const onSelect = vi.fn();
54
- const unset = vi.fn();
55
- const getCurrentStoryData = vi.fn();
56
- const getParameters = vi.fn();
57
- const getQueryParam = vi.fn();
58
- beforeEach(()=>{
59
- mockedApi.experimental_getStatusStore.mockReturnValue({
60
- onAllStatusChange,
61
- getAll,
62
- set,
63
- onSelect,
64
- unset
65
- });
66
- mockedApi.useAddonState.mockImplementation((_, defaultState)=>useState(defaultState));
67
- mockedApi.useChannel.mockReturnValue(vi.fn());
68
- getCurrentStoryData.mockReturnValue({
69
- id: storyId,
70
- type: 'story'
71
- });
72
- getParameters.mockReturnValue({});
73
- mockedApi.useStorybookApi.mockReturnValue({
74
- getCurrentStoryData,
75
- getParameters,
76
- getQueryParam
77
- });
78
- mockedApi.useParameter.mockReturnValue({
79
- manual: false
80
- });
81
- mockedApi.useStorybookState.mockReturnValue({
82
- storyId
83
- });
84
- mockedApi.useGlobals.mockReturnValue([
85
- {
86
- a11y: {}
87
- }
88
- ]);
89
- mockedApi.useChannel.mockClear();
90
- mockedApi.useStorybookApi.mockClear();
91
- mockedApi.useAddonState.mockClear();
92
- mockedApi.useParameter.mockClear();
93
- mockedApi.useStorybookState.mockClear();
94
- mockedApi.useGlobals.mockClear();
95
- });
96
- it('should render children', ()=>{
97
- const { getByTestId } = render(/*#__PURE__*/ createElement(A11yContextProvider, null, /*#__PURE__*/ createElement("div", {
98
- "data-testid": "child"
99
- })));
100
- expect(getByTestId('child')).toBeTruthy();
101
- });
102
- it('should handle STORY_FINISHED event correctly', ()=>{
103
- const emit = vi.fn();
104
- mockedApi.useChannel.mockReturnValue(emit);
105
- const Component = ()=>{
106
- const { results } = useA11yContext();
107
- return /*#__PURE__*/ createElement(Fragment, null, !!results?.passes.length && /*#__PURE__*/ createElement("div", {
108
- "data-testid": "anyPassesResults"
109
- }, JSON.stringify(results.passes)), !!results?.incomplete.length && /*#__PURE__*/ createElement("div", {
110
- "data-testid": "anyIncompleteResults"
111
- }, JSON.stringify(results.incomplete)), !!results?.violations.length && /*#__PURE__*/ createElement("div", {
112
- "data-testid": "anyViolationsResults"
113
- }, JSON.stringify(results.violations)));
114
- };
115
- const { queryByTestId } = render(/*#__PURE__*/ createElement(A11yContextProvider, null, /*#__PURE__*/ createElement(Component, null)));
116
- expect(queryByTestId('anyPassesResults')).toBeFalsy();
117
- expect(queryByTestId('anyIncompleteResults')).toBeFalsy();
118
- expect(queryByTestId('anyViolationsResults')).toBeFalsy();
119
- const useChannelArgs = mockedApi.useChannel.mock.calls[0][0];
120
- const storyFinishedPayload = {
121
- storyId,
122
- status: 'error',
123
- reporters: [
124
- {
125
- type: 'a11y',
126
- result: axeResult,
127
- status: 'failed',
128
- version: 1
129
- }
130
- ]
131
- };
132
- act(()=>useChannelArgs[STORY_FINISHED](storyFinishedPayload));
133
- expect(queryByTestId('anyPassesResults')).toHaveTextContent(JSON.stringify(axeResult.passes));
134
- expect(queryByTestId('anyIncompleteResults')).toHaveTextContent(JSON.stringify(axeResult.incomplete));
135
- expect(queryByTestId('anyViolationsResults')).toHaveTextContent(JSON.stringify(axeResult.violations));
136
- });
137
- it('should set discrepancy to cliFailedButModeManual when in manual mode (set via globals)', ()=>{
138
- mockedApi.useGlobals.mockReturnValue([
139
- {
140
- a11y: {
141
- manual: true
142
- }
143
- }
144
- ]);
145
- mockedApi.experimental_useStatusStore.mockReturnValue('status-value:error');
146
- const Component = ()=>{
147
- const { discrepancy } = useA11yContext();
148
- return /*#__PURE__*/ createElement("div", {
149
- "data-testid": "discrepancy"
150
- }, discrepancy);
151
- };
152
- const { getByTestId } = render(/*#__PURE__*/ createElement(A11yContextProvider, null, /*#__PURE__*/ createElement(Component, null)));
153
- expect(getByTestId('discrepancy').textContent).toBe('cliFailedButModeManual');
154
- });
155
- it('should set discrepancy to cliPassedBrowserFailed', ()=>{
156
- mockedApi.useParameter.mockReturnValue({
157
- manual: true
158
- });
159
- mockedApi.experimental_useStatusStore.mockReturnValue('status-value:success');
160
- const Component = ()=>{
161
- const { discrepancy } = useA11yContext();
162
- return /*#__PURE__*/ createElement("div", {
163
- "data-testid": "discrepancy"
164
- }, discrepancy);
165
- };
166
- const { getByTestId } = render(/*#__PURE__*/ createElement(A11yContextProvider, null, /*#__PURE__*/ createElement(Component, null)));
167
- const storyFinishedPayload = {
168
- storyId,
169
- status: 'error',
170
- reporters: [
171
- {
172
- type: 'a11y',
173
- result: axeResult,
174
- status: 'failed',
175
- version: 1
176
- }
177
- ]
178
- };
179
- const useChannelArgs = mockedApi.useChannel.mock.calls[0][0];
180
- act(()=>useChannelArgs[STORY_FINISHED](storyFinishedPayload));
181
- expect(getByTestId('discrepancy').textContent).toBe('cliPassedBrowserFailed');
182
- });
183
- it('should handle STORY_RENDER_PHASE_CHANGED event correctly', ()=>{
184
- const emit = vi.fn();
185
- mockedApi.useChannel.mockReturnValue(emit);
186
- const Component = ()=>{
187
- const { status } = useA11yContext();
188
- return /*#__PURE__*/ createElement("div", {
189
- "data-testid": "status"
190
- }, status);
191
- };
192
- const { queryByTestId } = render(/*#__PURE__*/ createElement(A11yContextProvider, null, /*#__PURE__*/ createElement(Component, null)));
193
- expect(queryByTestId('status')).toHaveTextContent('initial');
194
- const useChannelArgs = mockedApi.useChannel.mock.calls[0][0];
195
- act(()=>useChannelArgs[STORY_RENDER_PHASE_CHANGED]({
196
- newPhase: 'loading'
197
- }));
198
- expect(queryByTestId('status')).toHaveTextContent('initial');
199
- act(()=>useChannelArgs[STORY_RENDER_PHASE_CHANGED]({
200
- newPhase: 'afterEach'
201
- }));
202
- expect(queryByTestId('status')).toHaveTextContent('running');
203
- });
204
- it('should handle STORY_RENDER_PHASE_CHANGED event correctly when in manual mode (set via globals)', ()=>{
205
- mockedApi.useGlobals.mockReturnValue([
206
- {
207
- a11y: {
208
- manual: true
209
- }
210
- }
211
- ]);
212
- const emit = vi.fn();
213
- mockedApi.useChannel.mockReturnValue(emit);
214
- const Component = ()=>{
215
- const { status } = useA11yContext();
216
- return /*#__PURE__*/ createElement("div", {
217
- "data-testid": "status"
218
- }, status);
219
- };
220
- const { queryByTestId } = render(/*#__PURE__*/ createElement(A11yContextProvider, null, /*#__PURE__*/ createElement(Component, null)));
221
- expect(queryByTestId('status')).toHaveTextContent('manual');
222
- const useChannelArgs = mockedApi.useChannel.mock.calls[0][0];
223
- act(()=>useChannelArgs[STORY_RENDER_PHASE_CHANGED]({
224
- newPhase: 'loading'
225
- }));
226
- expect(queryByTestId('status')).toHaveTextContent('manual');
227
- act(()=>useChannelArgs[STORY_RENDER_PHASE_CHANGED]({
228
- newPhase: 'afterEach'
229
- }));
230
- expect(queryByTestId('status')).toHaveTextContent('manual');
231
- });
232
- it('should handle STORY_FINISHED event with error correctly', ()=>{
233
- const emit = vi.fn();
234
- mockedApi.useChannel.mockReturnValue(emit);
235
- const Component = ()=>{
236
- const { error } = useA11yContext();
237
- return /*#__PURE__*/ createElement("div", {
238
- "data-testid": "error"
239
- }, error ? error.message : 'No Error');
240
- };
241
- const { getByTestId } = render(/*#__PURE__*/ createElement(A11yContextProvider, null, /*#__PURE__*/ createElement(Component, null)));
242
- expect(getByTestId('error').textContent).toBe('No Error');
243
- const useChannelArgs = mockedApi.useChannel.mock.calls[0][0];
244
- const storyFinishedPayload = {
245
- storyId,
246
- status: 'error',
247
- reporters: [
248
- {
249
- status: 'failed',
250
- version: 1,
251
- type: 'a11y',
252
- result: {
253
- error: new Error('Test error')
254
- }
255
- }
256
- ]
257
- };
258
- act(()=>useChannelArgs[STORY_FINISHED](storyFinishedPayload));
259
- expect(getByTestId('error').textContent).toBe('Test error');
260
- });
261
- it('should handle manual run correctly', ()=>{
262
- const emit = vi.fn();
263
- mockedApi.useChannel.mockReturnValue(emit);
264
- const Component = ()=>{
265
- const { handleManual } = useA11yContext();
266
- return /*#__PURE__*/ createElement("button", {
267
- onClick: handleManual,
268
- "data-testid": "manualRunButton"
269
- }, "Run Manual");
270
- };
271
- const { getByTestId } = render(/*#__PURE__*/ createElement(A11yContextProvider, null, /*#__PURE__*/ createElement(Component, null)));
272
- act(()=>{
273
- getByTestId('manualRunButton').click();
274
- });
275
- expect(emit).toHaveBeenCalledWith(EVENTS.MANUAL, storyId, expect.any(Object));
276
- });
277
- });
@@ -1,169 +0,0 @@
1
- import react, { Fragment, useCallback, useState } from "react";
2
- import { Button, Link, SyntaxHighlighter } from "storybook/internal/components";
3
- import { CheckIcon, CopyIcon, LocationIcon } from "@storybook/icons";
4
- import { Content, List, Root, Trigger } from "@radix-ui/react-tabs";
5
- import { styled } from "storybook/theming";
6
- import { getFriendlySummaryForAxeResult } from "../../axeRuleMappingHelper.js";
7
- import { useA11yContext } from "../A11yContext.js";
8
- const StyledSyntaxHighlighter = styled(SyntaxHighlighter)(({ theme })=>({
9
- fontSize: theme.typography.size.s1
10
- }), ({ language })=>'css' === language && {
11
- '.selector ~ span:nth-last-of-type(-n+3)': {
12
- display: 'none'
13
- }
14
- });
15
- const Info = styled.div({
16
- display: 'flex',
17
- flexDirection: 'column'
18
- });
19
- const RuleId = styled.div(({ theme })=>({
20
- display: 'block',
21
- color: theme.textMutedColor,
22
- fontFamily: theme.typography.fonts.mono,
23
- fontSize: theme.typography.size.s1,
24
- marginTop: -8,
25
- marginBottom: 12,
26
- '@container (min-width: 800px)': {
27
- display: 'none'
28
- }
29
- }));
30
- const Description = styled.p({
31
- margin: 0
32
- });
33
- const Wrapper = styled.div({
34
- display: 'flex',
35
- flexDirection: 'column',
36
- padding: '0 15px 20px 15px',
37
- gap: 20
38
- });
39
- const Columns = styled.div({
40
- gap: 15,
41
- '@container (min-width: 800px)': {
42
- display: 'grid',
43
- gridTemplateColumns: '50% 50%'
44
- }
45
- });
46
- const Details_Content = styled.div(({ theme, side })=>({
47
- display: 'left' === side ? 'flex' : 'none',
48
- flexDirection: 'column',
49
- gap: 15,
50
- margin: 'left' === side ? '15px 0' : 0,
51
- padding: 'left' === side ? '0 15px' : 0,
52
- borderLeft: 'left' === side ? `1px solid ${theme.color.border}` : 'none',
53
- '&:focus-visible': {
54
- outline: 'none',
55
- borderRadius: 4,
56
- boxShadow: `0 0 0 1px inset ${theme.color.secondary}`
57
- },
58
- '@container (min-width: 800px)': {
59
- display: 'left' === side ? 'none' : 'flex'
60
- }
61
- }));
62
- const Item = styled(Button)(({ theme })=>({
63
- fontFamily: theme.typography.fonts.mono,
64
- fontWeight: theme.typography.weight.regular,
65
- color: theme.textMutedColor,
66
- height: 40,
67
- overflow: 'hidden',
68
- textOverflow: 'ellipsis',
69
- whiteSpace: 'nowrap',
70
- display: 'block',
71
- width: '100%',
72
- textAlign: 'left',
73
- padding: '0 12px',
74
- '&[data-state="active"]': {
75
- color: theme.color.secondary,
76
- backgroundColor: theme.background.hoverable
77
- }
78
- }));
79
- const Messages = styled.div({
80
- display: 'flex',
81
- flexDirection: 'column',
82
- gap: 10
83
- });
84
- const Actions = styled.div({
85
- display: 'flex',
86
- gap: 10
87
- });
88
- const CopyButton = ({ onClick })=>{
89
- const [copied, setCopied] = useState(false);
90
- const handleClick = useCallback(()=>{
91
- onClick();
92
- setCopied(true);
93
- const timeout = setTimeout(()=>setCopied(false), 2000);
94
- return ()=>clearTimeout(timeout);
95
- }, [
96
- onClick
97
- ]);
98
- return /*#__PURE__*/ react.createElement(Button, {
99
- ariaLabel: false,
100
- onClick: handleClick
101
- }, copied ? /*#__PURE__*/ react.createElement(CheckIcon, null) : /*#__PURE__*/ react.createElement(CopyIcon, null), " ", copied ? 'Copied' : 'Copy link');
102
- };
103
- const Details = ({ id, item, type, selection, handleSelectionChange })=>/*#__PURE__*/ react.createElement(Wrapper, {
104
- id: id
105
- }, /*#__PURE__*/ react.createElement(Info, null, /*#__PURE__*/ react.createElement(RuleId, null, item.id), /*#__PURE__*/ react.createElement(Description, null, getFriendlySummaryForAxeResult(item), ' ', /*#__PURE__*/ react.createElement(Link, {
106
- href: item.helpUrl,
107
- target: "_blank",
108
- rel: "noopener noreferrer",
109
- withArrow: true
110
- }, "Learn how to resolve this violation"))), /*#__PURE__*/ react.createElement(Root, {
111
- defaultValue: selection,
112
- orientation: "vertical",
113
- value: selection,
114
- onValueChange: handleSelectionChange,
115
- asChild: true
116
- }, /*#__PURE__*/ react.createElement(Columns, null, /*#__PURE__*/ react.createElement(List, {
117
- "aria-label": type
118
- }, item.nodes.map((node, index)=>{
119
- const key = `${type}.${item.id}.${index + 1}`;
120
- return /*#__PURE__*/ react.createElement(Fragment, {
121
- key: key
122
- }, /*#__PURE__*/ react.createElement(Trigger, {
123
- value: key,
124
- asChild: true
125
- }, /*#__PURE__*/ react.createElement(Item, {
126
- ariaLabel: false,
127
- variant: "ghost",
128
- size: "medium",
129
- id: key
130
- }, index + 1, ". ", node.html)), /*#__PURE__*/ react.createElement(Content, {
131
- value: key,
132
- asChild: true
133
- }, /*#__PURE__*/ react.createElement(Details_Content, {
134
- side: "left"
135
- }, getContent(node))));
136
- })), item.nodes.map((node, index)=>{
137
- const key = `${type}.${item.id}.${index + 1}`;
138
- return /*#__PURE__*/ react.createElement(Content, {
139
- key: key,
140
- value: key,
141
- asChild: true
142
- }, /*#__PURE__*/ react.createElement(Details_Content, {
143
- side: "right"
144
- }, getContent(node)));
145
- }))));
146
- function getContent(node) {
147
- const { handleCopyLink, handleJumpToElement } = useA11yContext();
148
- const { any, all, none, html, target } = node;
149
- const rules = [
150
- ...any,
151
- ...all,
152
- ...none
153
- ];
154
- return /*#__PURE__*/ react.createElement(react.Fragment, null, /*#__PURE__*/ react.createElement(Messages, null, rules.map((rule)=>/*#__PURE__*/ react.createElement("div", {
155
- key: rule.id
156
- }, `${rule.message}${/(\.|: [^.]+\.*)$/.test(rule.message) ? '' : '.'}`))), /*#__PURE__*/ react.createElement(Actions, null, /*#__PURE__*/ react.createElement(Button, {
157
- ariaLabel: false,
158
- onClick: ()=>handleJumpToElement(node.target.toString())
159
- }, /*#__PURE__*/ react.createElement(LocationIcon, null), " Jump to element"), /*#__PURE__*/ react.createElement(CopyButton, {
160
- onClick: ()=>handleCopyLink(node.linkPath)
161
- })), /*#__PURE__*/ react.createElement(StyledSyntaxHighlighter, {
162
- language: "jsx",
163
- wrapLongLines: true
164
- }, `/* element */\n${html}`), /*#__PURE__*/ react.createElement(StyledSyntaxHighlighter, {
165
- language: "css",
166
- wrapLongLines: true
167
- }, `/* selector */\n${target} {}`));
168
- }
169
- export { Details };
@@ -1,106 +0,0 @@
1
- import react from "react";
2
- import { Badge, Button, EmptyTabContent } from "storybook/internal/components";
3
- import { ChevronSmallDownIcon } from "@storybook/icons";
4
- import { styled } from "storybook/theming";
5
- import { getTitleForAxeResult } from "../../axeRuleMappingHelper.js";
6
- import { RuleType } from "../../types.js";
7
- import { Details } from "./Details.js";
8
- const impactStatus = {
9
- minor: 'neutral',
10
- moderate: 'warning',
11
- serious: 'negative',
12
- critical: 'critical'
13
- };
14
- const impactLabels = {
15
- minor: 'Minor',
16
- moderate: 'Moderate',
17
- serious: 'Serious',
18
- critical: 'Critical'
19
- };
20
- const Wrapper = styled.div(({ theme })=>({
21
- display: 'flex',
22
- flexDirection: 'column',
23
- width: '100%',
24
- borderBottom: `1px solid ${theme.appBorderColor}`,
25
- containerType: 'inline-size',
26
- fontSize: theme.typography.size.s2
27
- }));
28
- const Icon = styled(ChevronSmallDownIcon)({
29
- transition: 'transform 0.1s ease-in-out'
30
- });
31
- const HeaderBar = styled.div(({ theme })=>({
32
- display: 'flex',
33
- justifyContent: 'space-between',
34
- alignItems: 'center',
35
- gap: 6,
36
- padding: '6px 10px 6px 15px',
37
- minHeight: 40,
38
- background: 'none',
39
- color: 'inherit',
40
- textAlign: 'left',
41
- cursor: 'pointer',
42
- width: '100%',
43
- '&:hover': {
44
- color: theme.color.secondary
45
- }
46
- }));
47
- const Title = styled.div(({ theme })=>({
48
- display: 'flex',
49
- alignItems: 'baseline',
50
- flexGrow: 1,
51
- fontSize: theme.typography.size.s2,
52
- gap: 8
53
- }));
54
- const RuleId = styled.div(({ theme })=>({
55
- display: 'none',
56
- color: theme.textMutedColor,
57
- fontFamily: theme.typography.fonts.mono,
58
- fontSize: theme.typography.size.s1,
59
- '@container (min-width: 800px)': {
60
- display: 'block'
61
- }
62
- }));
63
- const Count = styled.div(({ theme })=>({
64
- display: 'flex',
65
- alignItems: 'center',
66
- justifyContent: 'center',
67
- color: theme.textMutedColor,
68
- width: 28,
69
- height: 28
70
- }));
71
- const Report = ({ items, empty, type, handleSelectionChange, selectedItems, toggleOpen })=>/*#__PURE__*/ react.createElement(react.Fragment, null, items && items.length ? items.map((item)=>{
72
- const id = `${type}.${item.id}`;
73
- const detailsId = `details:${id}`;
74
- const selection = selectedItems.get(id);
75
- const title = getTitleForAxeResult(item);
76
- return /*#__PURE__*/ react.createElement(Wrapper, {
77
- key: id
78
- }, /*#__PURE__*/ react.createElement(HeaderBar, {
79
- onClick: (event)=>toggleOpen(event, type, item),
80
- "data-active": !!selection
81
- }, /*#__PURE__*/ react.createElement(Title, null, /*#__PURE__*/ react.createElement("strong", null, title), /*#__PURE__*/ react.createElement(RuleId, null, item.id)), item.impact && /*#__PURE__*/ react.createElement(Badge, {
82
- status: type === RuleType.PASS ? 'neutral' : impactStatus[item.impact]
83
- }, impactLabels[item.impact]), /*#__PURE__*/ react.createElement(Count, null, item.nodes.length), /*#__PURE__*/ react.createElement(Button, {
84
- onClick: (event)=>toggleOpen(event, type, item),
85
- ariaLabel: `${selection ? 'Collapse' : 'Expand'} details for: ${title}`,
86
- "aria-expanded": !!selection,
87
- "aria-controls": detailsId,
88
- variant: "ghost",
89
- padding: "small"
90
- }, /*#__PURE__*/ react.createElement(Icon, {
91
- style: {
92
- transform: `rotate(${selection ? -180 : 0}deg)`
93
- }
94
- }))), selection ? /*#__PURE__*/ react.createElement(Details, {
95
- id: detailsId,
96
- item: item,
97
- type: type,
98
- selection: selection,
99
- handleSelectionChange: handleSelectionChange
100
- }) : /*#__PURE__*/ react.createElement("div", {
101
- id: detailsId
102
- }));
103
- }) : /*#__PURE__*/ react.createElement(EmptyTabContent, {
104
- title: empty
105
- }));
106
- export { Report };
@@ -1,86 +0,0 @@
1
- import react from "react";
2
- import { ManagerContext } from "storybook/manager-api";
3
- import { fn } from "storybook/test";
4
- import { styled } from "storybook/theming";
5
- import preview from "../../../../../.storybook/preview";
6
- import { results } from "../../results.mock.js";
7
- import { RuleType } from "../../types.js";
8
- import { Report } from "./Report.js";
9
- const StyledWrapper = styled.div(({ theme })=>({
10
- backgroundColor: theme.background.content,
11
- fontSize: theme.typography.size.s2 - 1,
12
- color: theme.color.defaultText,
13
- display: 'block',
14
- height: '100%',
15
- position: 'absolute',
16
- left: 0,
17
- right: 0,
18
- bottom: 0,
19
- overflow: 'auto'
20
- }));
21
- const managerContext = {
22
- state: {},
23
- api: {
24
- getDocsUrl: fn().mockName('api::getDocsUrl')
25
- }
26
- };
27
- const meta = preview.meta({
28
- title: 'Report',
29
- component: Report,
30
- decorators: [
31
- (Story)=>/*#__PURE__*/ react.createElement(ManagerContext.Provider, {
32
- value: managerContext
33
- }, /*#__PURE__*/ react.createElement(StyledWrapper, {
34
- id: "panel-tab-content"
35
- }, /*#__PURE__*/ react.createElement(Story, null)))
36
- ],
37
- parameters: {
38
- layout: 'fullscreen'
39
- },
40
- args: {
41
- items: [],
42
- empty: 'No issues found',
43
- type: RuleType.VIOLATION,
44
- handleSelectionChange: fn().mockName('handleSelectionChange'),
45
- selectedItems: new Map(),
46
- toggleOpen: fn().mockName('toggleOpen')
47
- }
48
- });
49
- const Empty = meta.story({});
50
- const Violations = meta.story({
51
- args: {
52
- items: results.violations,
53
- type: RuleType.VIOLATION,
54
- selectedItems: new Map([
55
- [
56
- `${RuleType.VIOLATION}.${results.violations["0"].id}`,
57
- `${RuleType.VIOLATION}.${results.violations["0"].id}.3`
58
- ]
59
- ])
60
- }
61
- });
62
- const Incomplete = meta.story({
63
- args: {
64
- items: results.incomplete,
65
- type: RuleType.INCOMPLETION,
66
- selectedItems: new Map([
67
- [
68
- `${RuleType.INCOMPLETION}.${results.incomplete["1"].id}`,
69
- `${RuleType.INCOMPLETION}.${results.incomplete["1"].id}.2`
70
- ]
71
- ])
72
- }
73
- });
74
- const Passes = meta.story({
75
- args: {
76
- items: results.passes,
77
- type: RuleType.PASS,
78
- selectedItems: new Map([
79
- [
80
- `${RuleType.PASS}.${results.passes["2"].id}`,
81
- `${RuleType.PASS}.${results.passes["2"].id}.1`
82
- ]
83
- ])
84
- }
85
- });
86
- export { Empty, Incomplete, Passes, Violations };