Skip to content

Commit e5912a7

Browse files
authored
Merge branch 'next' into yann/fix-vitest-with-multiple-projects
2 parents e9a6379 + 56d576d commit e5912a7

File tree

28 files changed

+449
-290
lines changed

28 files changed

+449
-290
lines changed

code/addons/a11y/src/a11yRunner.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { ElementA11yParameterError } from 'storybook/internal/preview-errors';
33
import { global } from '@storybook/global';
44

55
import type { AxeResults, ContextProp, ContextSpec } from 'axe-core';
6-
import { addons } from 'storybook/preview-api';
6+
import { addons, waitForAnimations } from 'storybook/preview-api';
77

88
import { withLinkPaths } from './a11yRunnerUtils';
99
import { EVENTS } from './constants';
@@ -113,6 +113,7 @@ export const run = async (input: A11yParameters = DEFAULT_PARAMETERS, storyId: s
113113

114114
channel.on(EVENTS.MANUAL, async (storyId: string, input: A11yParameters = DEFAULT_PARAMETERS) => {
115115
try {
116+
await waitForAnimations();
116117
const result = await run(input, storyId);
117118
// Axe result contains class instances, which telejson deserializes in a
118119
// way that violates:

code/addons/a11y/src/components/A11YPanel.stories.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ const meta = preview.meta({
5454
});
5555

5656
const context = {
57+
parameters: {},
5758
handleManual: fn(),
5859
highlighted: false,
5960
toggleHighlight: fn(),
@@ -70,7 +71,8 @@ const context = {
7071
};
7172

7273
const Template = (
73-
args: Pick<A11yContextStore, 'results' | 'error' | 'status' | 'discrepancy' | 'selectedItems'>
74+
args: Pick<A11yContextStore, 'results' | 'error' | 'status' | 'discrepancy' | 'selectedItems'> &
75+
Pick<Partial<A11yContextStore>, 'parameters'>
7476
) => (
7577
<A11yContext.Provider value={{ ...context, ...args }}>
7678
<ManagerContext.Provider value={managerContext}>
@@ -95,6 +97,21 @@ export const Initializing = meta.story({
9597
},
9698
});
9799

100+
export const Disabled = meta.story({
101+
render: () => {
102+
return (
103+
<Template
104+
results={emptyResults}
105+
status="initial"
106+
error={null}
107+
discrepancy={null}
108+
selectedItems={new Map()}
109+
parameters={{ disable: true }}
110+
/>
111+
);
112+
},
113+
});
114+
98115
export const Manual = meta.story({
99116
render: () => {
100117
return (

code/addons/a11y/src/components/A11YPanel.test.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const emptyResults: EnhancedResults = {
3737
describe('A11YPanel', () => {
3838
it('should render initializing state', () => {
3939
mockedUseA11yContext.mockReturnValue({
40+
parameters: {},
4041
results: emptyResults,
4142
status: 'initial',
4243
handleManual: vi.fn(),
@@ -55,6 +56,7 @@ describe('A11YPanel', () => {
5556
it('should render manual state', () => {
5657
const handleManual = vi.fn();
5758
mockedUseA11yContext.mockReturnValue({
59+
parameters: {},
5860
results: emptyResults,
5961
status: 'manual',
6062
handleManual,
@@ -76,6 +78,7 @@ describe('A11YPanel', () => {
7678

7779
it('should render running state', () => {
7880
mockedUseA11yContext.mockReturnValue({
81+
parameters: {},
7982
results: emptyResults,
8083
status: 'running',
8184
handleManual: vi.fn(),
@@ -95,6 +98,7 @@ describe('A11YPanel', () => {
9598

9699
it('should render error state', () => {
97100
mockedUseA11yContext.mockReturnValue({
101+
parameters: {},
98102
results: emptyResults,
99103
status: 'error',
100104
handleManual: vi.fn(),
@@ -113,6 +117,7 @@ describe('A11YPanel', () => {
113117

114118
it('should render error state with object error', () => {
115119
mockedUseA11yContext.mockReturnValue({
120+
parameters: {},
116121
results: emptyResults,
117122
status: 'error',
118123
handleManual: vi.fn(),

code/addons/a11y/src/components/A11YPanel.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ const Centered = styled.span(({ theme }) => ({
5555

5656
export const A11YPanel: React.FC = () => {
5757
const {
58+
parameters,
5859
tab,
5960
results,
6061
status,
@@ -142,6 +143,21 @@ export const A11YPanel: React.FC = () => {
142143
];
143144
}, [tab, results, handleSelectionChange, selectedItems, toggleOpen]);
144145

146+
if (parameters.disable || parameters.test === 'off') {
147+
return (
148+
<Centered>
149+
<div>
150+
<strong>Accessibility tests are disabled for this story</strong>
151+
<p>
152+
Update{' '}
153+
<code>{parameters.disable ? 'parameters.a11y.disable' : 'parameters.a11y.test'}</code>{' '}
154+
to enable accessibility tests.
155+
</p>
156+
</div>
157+
</Centered>
158+
);
159+
}
160+
145161
return (
146162
<>
147163
{discrepancy && <TestDiscrepancyMessage discrepancy={discrepancy} />}

code/addons/a11y/src/components/A11yContext.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import React, { createContext, useCallback, useContext, useEffect, useMemo, useS
44
import {
55
STORY_CHANGED,
66
STORY_FINISHED,
7+
STORY_HOT_UPDATED,
78
STORY_RENDER_PHASE_CHANGED,
89
type StoryFinishedPayload,
910
} from 'storybook/internal/core-events';
@@ -35,6 +36,7 @@ import type { TestDiscrepancy } from './TestDiscrepancyMessage';
3536
const unhighlightedSelectors = ['html', 'body', 'main'];
3637

3738
export interface A11yContextStore {
39+
parameters: A11yParameters;
3840
results: EnhancedResults | undefined;
3941
highlighted: boolean;
4042
toggleHighlight: () => void;
@@ -63,6 +65,7 @@ const colorsByType = {
6365
};
6466

6567
export const A11yContext = createContext<A11yContextStore>({
68+
parameters: {},
6669
results: undefined,
6770
highlighted: false,
6871
toggleHighlight: () => {},
@@ -263,8 +266,12 @@ export const A11yContextProvider: FC<PropsWithChildren> = (props) => {
263266
[STORY_CHANGED]: () => setSelectedItems(new Map()),
264267
[STORY_RENDER_PHASE_CHANGED]: handleReset,
265268
[STORY_FINISHED]: handleReport,
269+
[STORY_HOT_UPDATED]: () => {
270+
setStatus('running');
271+
emit(EVENTS.MANUAL, storyId, parameters);
272+
},
266273
},
267-
[handleReset, handleReport, handleSelect, handleError, handleResult]
274+
[handleReset, handleReport, handleSelect, handleError, handleResult, parameters, storyId]
268275
);
269276

270277
const handleManual = useCallback(() => {
@@ -381,6 +388,7 @@ export const A11yContextProvider: FC<PropsWithChildren> = (props) => {
381388
return (
382389
<A11yContext.Provider
383390
value={{
391+
parameters,
384392
results,
385393
highlighted,
386394
toggleHighlight: handleToggleHighlight,

code/addons/a11y/src/components/Report/Details.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,10 @@ const Info = styled.div({
3434
const RuleId = styled.div(({ theme }) => ({
3535
display: 'block',
3636
color: theme.textMutedColor,
37-
marginTop: -10,
38-
marginBottom: 10,
37+
fontFamily: theme.typography.fonts.mono,
38+
fontSize: theme.typography.size.s1,
39+
marginTop: -8,
40+
marginBottom: 12,
3941

4042
'@container (min-width: 800px)': {
4143
display: 'none',
@@ -142,7 +144,7 @@ export const Details = ({ id, item, type, selection, handleSelectionChange }: De
142144
<Description>
143145
{getFriendlySummaryForAxeResult(item)}{' '}
144146
<Link href={item.helpUrl} target="_blank" withArrow>
145-
How to resolve this
147+
Learn how to resolve this violation
146148
</Link>
147149
</Description>
148150
</Info>

code/addons/a11y/src/components/Report/Report.tsx

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,38 @@
1-
import type { FC } from 'react';
1+
import type { ComponentProps, FC } from 'react';
22
import React from 'react';
33

4-
import { EmptyTabContent, IconButton } from 'storybook/internal/components';
4+
import { Badge, EmptyTabContent, IconButton } from 'storybook/internal/components';
55

66
import { ChevronSmallDownIcon } from '@storybook/icons';
77

8+
import type { ImpactValue } from 'axe-core';
89
import { styled } from 'storybook/theming';
910

1011
import { getTitleForAxeResult } from '../../axeRuleMappingHelper';
11-
import type { EnhancedResult, RuleType } from '../../types';
12+
import { type EnhancedResult, RuleType } from '../../types';
1213
import { Details } from './Details';
1314

15+
const impactStatus: Record<NonNullable<ImpactValue>, ComponentProps<typeof Badge>['status']> = {
16+
minor: 'neutral',
17+
moderate: 'warning',
18+
serious: 'negative',
19+
critical: 'critical',
20+
};
21+
22+
const impactLabels: Record<NonNullable<ImpactValue>, string> = {
23+
minor: 'Minor',
24+
moderate: 'Moderate',
25+
serious: 'Serious',
26+
critical: 'Critical',
27+
};
28+
1429
const Wrapper = styled.div(({ theme }) => ({
1530
display: 'flex',
1631
flexDirection: 'column',
1732
width: '100%',
1833
borderBottom: `1px solid ${theme.appBorderColor}`,
1934
containerType: 'inline-size',
35+
fontSize: theme.typography.size.s2,
2036
}));
2137

2238
const Icon = styled(ChevronSmallDownIcon)({
@@ -40,11 +56,24 @@ const HeaderBar = styled.div(({ theme }) => ({
4056
},
4157
}));
4258

43-
const Title = styled.div({
59+
const Title = styled.div(({ theme }) => ({
4460
display: 'flex',
61+
alignItems: 'baseline',
4562
flexGrow: 1,
46-
gap: 6,
47-
});
63+
fontSize: theme.typography.size.s2,
64+
gap: 8,
65+
}));
66+
67+
const RuleId = styled.div(({ theme }) => ({
68+
display: 'none',
69+
color: theme.textMutedColor,
70+
fontFamily: theme.typography.fonts.mono,
71+
fontSize: theme.typography.size.s1,
72+
73+
'@container (min-width: 800px)': {
74+
display: 'block',
75+
},
76+
}));
4877

4978
const Count = styled.div(({ theme }) => ({
5079
display: 'flex',
@@ -84,7 +113,13 @@ export const Report: FC<ReportProps> = ({
84113
<HeaderBar onClick={(event) => toggleOpen(event, type, item)} data-active={!!selection}>
85114
<Title>
86115
<strong>{title}</strong>
116+
<RuleId>{item.id}</RuleId>
87117
</Title>
118+
{item.impact && (
119+
<Badge status={type === RuleType.PASS ? 'neutral' : impactStatus[item.impact]}>
120+
{impactLabels[item.impact]}
121+
</Badge>
122+
)}
88123
<Count>{item.nodes.length}</Count>
89124
<IconButton
90125
onClick={(event) => toggleOpen(event, type, item)}

code/addons/a11y/src/types.ts

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
import type { AxeResults, ElementContext, NodeResult, Result, RunOptions, Spec } from 'axe-core';
1+
import type { AxeResults, NodeResult, Result } from 'axe-core';
2+
3+
import type { A11yParameters as A11yParams } from './params';
24

35
export type A11YReport = EnhancedResults | { error: Error };
46

@@ -8,27 +10,7 @@ export interface A11yParameters {
810
*
911
* @see https://storybook.js.org/docs/writing-tests/accessibility-testing
1012
*/
11-
a11y?: {
12-
/** Manual configuration for specific elements */
13-
element?: ElementContext;
14-
15-
/**
16-
* Configuration for the accessibility rules
17-
*
18-
* @see https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#api-name-axeconfigure
19-
*/
20-
config?: Spec;
21-
22-
/**
23-
* Options for the accessibility checks To learn more about the available options,
24-
*
25-
* @see https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#options-parameter
26-
*/
27-
options?: RunOptions;
28-
29-
/** Remove the addon panel and disable the addon's behavior */
30-
disable?: boolean;
31-
};
13+
a11y?: A11yParams;
3214
}
3315

3416
export interface A11yGlobals {

code/addons/docs/src/blocks/blocks/Canvas.stories.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,8 @@ export const PropSource: Story = {
158158
},
159159
};
160160

161-
export const PropInlineStory: Story = {
162-
name: 'Prop story = { ..., inline: true }',
161+
export const PropIframeStory: Story = {
162+
name: 'Prop story = { ..., inline: false }',
163163
args: {
164164
of: ButtonStories.Primary,
165165
story: { inline: false, height: '200px' },

code/addons/docs/src/blocks/blocks/Canvas.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ export const Canvas: FC<CanvasProps> = (props) => {
7878
props.additionalActions ?? story.parameters.docs?.canvas?.additionalActions;
7979
const sourceState = props.sourceState ?? story.parameters.docs?.canvas?.sourceState ?? 'hidden';
8080
const className = props.className ?? story.parameters.docs?.canvas?.className;
81+
// By default, stories will be iframed, but most frameworks support inline rendering and override that in a docs entry file
82+
const inline = props.story?.inline ?? story.parameters?.docs?.story?.inline ?? false;
8183

8284
return (
8385
<PurePreview
@@ -87,6 +89,7 @@ export const Canvas: FC<CanvasProps> = (props) => {
8789
additionalActions={additionalActions}
8890
className={className}
8991
layout={layout}
92+
inline={inline}
9093
>
9194
<Story of={of || story.moduleExport} meta={props.meta} {...props.story} />
9295
</PurePreview>

0 commit comments

Comments
 (0)