@primer/components 32.0.2-rc.859381a1 → 32.1.1-rc.b4502a34
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/CHANGELOG.md +13 -1
- package/dist/browser.esm.js +9 -2
- package/dist/browser.esm.js.map +1 -1
- package/dist/browser.umd.js +9 -2
- package/dist/browser.umd.js.map +1 -1
- package/docs/content/ActionList2.mdx +23 -3
- package/docs/content/Avatar.mdx +21 -1
- package/docs/content/AvatarStack.mdx +23 -3
- package/docs/content/BranchName.md +24 -4
- package/docs/content/Breadcrumbs.md +22 -1
- package/docs/content/Buttons.md +2 -1
- package/docs/content/Checkbox.md +118 -0
- package/docs/content/CircleBadge.md +1 -0
- package/docs/content/CircleOcticon.md +2 -1
- package/docs/content/CounterLabel.md +1 -1
- package/docs/content/Details.md +2 -1
- package/docs/content/Dialog.md +1 -0
- package/docs/content/Dialog2.mdx +1 -0
- package/docs/content/Dropdown.md +1 -0
- package/docs/content/DropdownMenu.mdx +1 -0
- package/docs/content/FilterList.md +1 -0
- package/docs/content/FilteredSearch.md +1 -0
- package/docs/content/Flash.md +1 -0
- package/docs/content/FormGroup.md +1 -0
- package/docs/content/Header.md +1 -0
- package/docs/content/Heading.md +8 -4
- package/docs/content/Label.md +1 -0
- package/docs/content/LabelGroup.md +1 -0
- package/docs/content/Link.md +1 -0
- package/docs/content/Overlay.mdx +1 -0
- package/docs/content/Pagehead.md +1 -0
- package/docs/content/Pagination.md +1 -0
- package/docs/content/PointerBox.md +1 -0
- package/docs/content/Popover.md +1 -0
- package/docs/content/Portal.mdx +1 -0
- package/docs/content/Position.md +2 -9
- package/docs/content/ProgressBar.mdx +1 -0
- package/docs/content/SelectMenu.md +1 -0
- package/docs/content/SideNav.md +1 -0
- package/docs/content/StateLabel.md +1 -0
- package/docs/content/StyledOcticon.md +1 -1
- package/docs/content/SubNav.md +1 -0
- package/docs/content/TabNav.md +1 -0
- package/docs/content/Text.md +10 -3
- package/docs/content/TextInput.md +9 -1
- package/docs/content/Timeline.md +1 -0
- package/docs/content/Tooltip.md +1 -0
- package/docs/content/Truncate.md +1 -0
- package/docs/content/UnderlineNav.md +1 -0
- package/docs/content/status.mdx +10 -0
- package/docs/src/@primer/gatsby-theme-doctocat/mdx-components.js +9 -0
- package/docs/src/@primer/gatsby-theme-doctocat/nav.yml +4 -0
- package/docs/src/component-statuses.js +74 -0
- package/lib/ActionList/Item.js +3 -3
- package/lib/ActionList2/Item.js +3 -1
- package/lib/ActionList2/List.js +1 -2
- package/lib/ActionList2/Selection.js +3 -1
- package/lib/Autocomplete/Autocomplete.d.ts +1 -0
- package/lib/Autocomplete/AutocompleteInput.d.ts +1 -0
- package/lib/Button/Button.d.ts +1 -0
- package/lib/Button/ButtonClose.d.ts +2 -1
- package/lib/Button/ButtonDanger.d.ts +1 -0
- package/lib/Button/ButtonInvisible.d.ts +1 -0
- package/lib/Button/ButtonOutline.d.ts +1 -0
- package/lib/Button/ButtonPrimary.d.ts +1 -0
- package/lib/Checkbox.d.ts +29 -0
- package/lib/Checkbox.js +64 -0
- package/lib/CircleOcticon.d.ts +1 -0
- package/lib/Dialog.d.ts +3 -2
- package/lib/Dropdown.d.ts +4 -0
- package/lib/DropdownMenu/DropdownButton.d.ts +2 -1
- package/lib/FilterList.d.ts +1 -0
- package/lib/Position.d.ts +4 -4
- package/lib/SelectMenu/SelectMenu.d.ts +10 -4
- package/lib/SelectMenu/SelectMenuItem.d.ts +1 -1
- package/lib/SelectMenu/SelectMenuModal.d.ts +1 -1
- package/lib/TextInputWithTokens.d.ts +1 -0
- package/lib/Token/AvatarToken.d.ts +1 -1
- package/lib/Token/IssueLabelToken.d.ts +1 -1
- package/lib/Token/Token.d.ts +1 -1
- package/lib/__tests__/ActionList2.test.d.ts +1 -0
- package/lib/__tests__/ActionList2.test.js +117 -0
- package/lib/__tests__/Checkbox.test.d.ts +2 -0
- package/lib/__tests__/Checkbox.test.js +189 -0
- package/lib/__tests__/themePreval.test.d.ts +1 -0
- package/lib/__tests__/themePreval.test.js +14 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +8 -0
- package/lib/stories/ActionList2.stories.js +20 -6
- package/lib/stories/Checkbox.stories.js +227 -0
- package/lib/utils/testing.d.ts +1 -0
- package/lib/utils/testing.js +29 -0
- package/lib-esm/ActionList/Item.js +3 -3
- package/lib-esm/ActionList2/Item.js +3 -1
- package/lib-esm/ActionList2/List.js +1 -2
- package/lib-esm/ActionList2/Selection.js +3 -1
- package/lib-esm/Autocomplete/Autocomplete.d.ts +1 -0
- package/lib-esm/Autocomplete/AutocompleteInput.d.ts +1 -0
- package/lib-esm/Button/Button.d.ts +1 -0
- package/lib-esm/Button/ButtonClose.d.ts +2 -1
- package/lib-esm/Button/ButtonDanger.d.ts +1 -0
- package/lib-esm/Button/ButtonInvisible.d.ts +1 -0
- package/lib-esm/Button/ButtonOutline.d.ts +1 -0
- package/lib-esm/Button/ButtonPrimary.d.ts +1 -0
- package/lib-esm/Checkbox.d.ts +29 -0
- package/lib-esm/Checkbox.js +44 -0
- package/lib-esm/CircleOcticon.d.ts +1 -0
- package/lib-esm/Dialog.d.ts +3 -2
- package/lib-esm/Dropdown.d.ts +4 -0
- package/lib-esm/DropdownMenu/DropdownButton.d.ts +2 -1
- package/lib-esm/FilterList.d.ts +1 -0
- package/lib-esm/Position.d.ts +4 -4
- package/lib-esm/SelectMenu/SelectMenu.d.ts +10 -4
- package/lib-esm/SelectMenu/SelectMenuItem.d.ts +1 -1
- package/lib-esm/SelectMenu/SelectMenuModal.d.ts +1 -1
- package/lib-esm/TextInputWithTokens.d.ts +1 -0
- package/lib-esm/Token/AvatarToken.d.ts +1 -1
- package/lib-esm/Token/IssueLabelToken.d.ts +1 -1
- package/lib-esm/Token/Token.d.ts +1 -1
- package/lib-esm/__tests__/ActionList2.test.d.ts +1 -0
- package/lib-esm/__tests__/ActionList2.test.js +105 -2
- package/lib-esm/__tests__/Checkbox.test.d.ts +2 -0
- package/lib-esm/__tests__/Checkbox.test.js +169 -0
- package/lib-esm/__tests__/themePreval.test.d.ts +1 -0
- package/lib-esm/__tests__/themePreval.test.js +7 -0
- package/lib-esm/index.d.ts +2 -0
- package/lib-esm/index.js +1 -0
- package/lib-esm/stories/ActionList2.stories.js +20 -6
- package/lib-esm/stories/Checkbox.stories.js +197 -0
- package/lib-esm/utils/testing.d.ts +1 -0
- package/lib-esm/utils/testing.js +24 -0
- package/package-lock.json +179 -20
- package/package.json +2 -2
- package/src/ActionList/Item.tsx +2 -1
- package/src/ActionList2/Item.tsx +3 -2
- package/src/ActionList2/List.tsx +1 -6
- package/src/ActionList2/Selection.tsx +2 -1
- package/src/Checkbox.tsx +75 -0
- package/src/__tests__/ActionList2.test.tsx +111 -2
- package/src/__tests__/Checkbox.test.tsx +155 -0
- package/src/__tests__/__snapshots__/Autocomplete.test.tsx.snap +13 -0
- package/src/__tests__/__snapshots__/Checkbox.test.tsx.snap +16 -0
- package/src/__tests__/__snapshots__/themePreval.test.ts.snap +3176 -0
- package/src/__tests__/themePreval.test.ts +8 -0
- package/src/index.ts +3 -0
- package/src/stories/ActionList2.stories.tsx +22 -8
- package/src/stories/Checkbox.stories.tsx +164 -0
- package/src/utils/testing.tsx +22 -0
- package/stats.html +1 -1
- package/docs/content/TextInputTokens.mdx +0 -89
- package/lib/ActionList2/Header.d.ts +0 -26
- package/lib/ActionList2/Header.js +0 -55
- package/lib-esm/ActionList2/Header.d.ts +0 -26
- package/lib-esm/ActionList2/Header.js +0 -44
- package/src/ActionList2/Header.tsx +0 -58
@@ -0,0 +1,8 @@
|
|
1
|
+
import fs from 'fs'
|
2
|
+
import path from 'path'
|
3
|
+
|
4
|
+
test('snapshot theme-preval.js', () => {
|
5
|
+
// Snapshot test the build output of theme-preval.js to catch any unexpected changes
|
6
|
+
const themePrevalFile = fs.readFileSync(path.resolve(__dirname, '../../lib/theme-preval.js'), 'utf8')
|
7
|
+
expect(themePrevalFile).toMatchSnapshot()
|
8
|
+
})
|
package/src/index.ts
CHANGED
@@ -169,4 +169,7 @@ export type {TruncateProps} from './Truncate'
|
|
169
169
|
export {default as UnderlineNav} from './UnderlineNav'
|
170
170
|
export type {UnderlineNavProps, UnderlineNavLinkProps} from './UnderlineNav'
|
171
171
|
|
172
|
+
export {default as Checkbox} from './Checkbox'
|
173
|
+
export type {CheckboxProps} from './Checkbox'
|
174
|
+
|
172
175
|
export {SSRProvider, useSSRSafeId} from './utils/ssr'
|
@@ -801,7 +801,7 @@ export function AllCombinations(): JSX.Element {
|
|
801
801
|
L + I + B<ActionList.Description variant="inline">inline description</ActionList.Description>
|
802
802
|
<ActionList.Description variant="block">Block description</ActionList.Description>
|
803
803
|
</ActionList.Item>
|
804
|
-
<ActionList.Item>
|
804
|
+
<ActionList.Item disabled>
|
805
805
|
<ActionList.LeadingVisual>
|
806
806
|
<StarIcon />
|
807
807
|
</ActionList.LeadingVisual>
|
@@ -810,7 +810,7 @@ export function AllCombinations(): JSX.Element {
|
|
810
810
|
<StarIcon />
|
811
811
|
</ActionList.TrailingVisual>
|
812
812
|
</ActionList.Item>
|
813
|
-
<ActionList.Item>
|
813
|
+
<ActionList.Item disabled>
|
814
814
|
<ActionList.LeadingVisual>
|
815
815
|
<StarIcon />
|
816
816
|
</ActionList.LeadingVisual>
|
@@ -819,7 +819,7 @@ export function AllCombinations(): JSX.Element {
|
|
819
819
|
<StarIcon />
|
820
820
|
</ActionList.TrailingVisual>
|
821
821
|
</ActionList.Item>
|
822
|
-
<ActionList.Item>
|
822
|
+
<ActionList.Item disabled>
|
823
823
|
I + B + T<ActionList.Description variant="inline">inline description</ActionList.Description>
|
824
824
|
<ActionList.Description variant="block">Block description</ActionList.Description>
|
825
825
|
<ActionList.TrailingVisual>
|
@@ -1051,9 +1051,14 @@ export function MemexGroupBy(): JSX.Element {
|
|
1051
1051
|
<h1>Memex GroupBy List</h1>
|
1052
1052
|
<ErsatzOverlay>
|
1053
1053
|
<ActionList>
|
1054
|
-
<ActionList.Group title="Group by" selectionVariant="single">
|
1054
|
+
<ActionList.Group title="Group by" selectionVariant="single" role="listbox">
|
1055
1055
|
{options.map((option, index) => (
|
1056
|
-
<ActionList.Item
|
1056
|
+
<ActionList.Item
|
1057
|
+
key={index}
|
1058
|
+
selected={index === selectedIndex}
|
1059
|
+
onSelect={() => setSelectedIndex(index)}
|
1060
|
+
role="option"
|
1061
|
+
>
|
1057
1062
|
<ActionList.LeadingVisual>{option.icon}</ActionList.LeadingVisual>
|
1058
1063
|
{option.text}
|
1059
1064
|
</ActionList.Item>
|
@@ -1119,10 +1124,11 @@ export function MemexSortable(): JSX.Element {
|
|
1119
1124
|
<ErsatzOverlay>
|
1120
1125
|
<DndProvider backend={HTML5Backend}>
|
1121
1126
|
<ActionList selectionVariant="multiple">
|
1122
|
-
<ActionList.Group title="Visible fields (can be reordered)">
|
1127
|
+
<ActionList.Group title="Visible fields (can be reordered)" role="listbox">
|
1123
1128
|
{visibleOptions.map(option => (
|
1124
1129
|
<SortableItem
|
1125
1130
|
key={option.text}
|
1131
|
+
role="option"
|
1126
1132
|
option={option}
|
1127
1133
|
onSelect={() => toggle(option.text)}
|
1128
1134
|
reorder={reorder}
|
@@ -1130,6 +1136,7 @@ export function MemexSortable(): JSX.Element {
|
|
1130
1136
|
))}
|
1131
1137
|
</ActionList.Group>
|
1132
1138
|
<ActionList.Group
|
1139
|
+
role="listbox"
|
1133
1140
|
title="Hidden fields"
|
1134
1141
|
selectionVariant={
|
1135
1142
|
/** selectionVariant override on Group: disable selection if there are no options */
|
@@ -1137,7 +1144,12 @@ export function MemexSortable(): JSX.Element {
|
|
1137
1144
|
}
|
1138
1145
|
>
|
1139
1146
|
{hiddenOptions.map((option, index) => (
|
1140
|
-
<ActionList.Item
|
1147
|
+
<ActionList.Item
|
1148
|
+
key={index}
|
1149
|
+
role="option"
|
1150
|
+
selected={option.selected}
|
1151
|
+
onSelect={() => toggle(option.text)}
|
1152
|
+
>
|
1141
1153
|
<ActionList.LeadingVisual>{option.icon}</ActionList.LeadingVisual>
|
1142
1154
|
{option.text}
|
1143
1155
|
</ActionList.Item>
|
@@ -1154,10 +1166,11 @@ MemexSortable.storyName = 'Memex Sortable List'
|
|
1154
1166
|
|
1155
1167
|
type SortableItemProps = {
|
1156
1168
|
option: Option
|
1169
|
+
role: ItemProps['role']
|
1157
1170
|
onSelect: ItemProps['onSelect']
|
1158
1171
|
reorder: ({optionToMove, moveAfterOption}: {optionToMove: Option; moveAfterOption: Option}) => void
|
1159
1172
|
}
|
1160
|
-
const SortableItem: React.FC<SortableItemProps> = ({option, onSelect, reorder}) => {
|
1173
|
+
const SortableItem: React.FC<SortableItemProps> = ({option, role, onSelect, reorder}) => {
|
1161
1174
|
const [{isDragging}, dragRef] = useDrag(() => ({
|
1162
1175
|
type: 'ITEM',
|
1163
1176
|
item: option,
|
@@ -1178,6 +1191,7 @@ const SortableItem: React.FC<SortableItemProps> = ({option, onSelect, reorder})
|
|
1178
1191
|
|
1179
1192
|
return (
|
1180
1193
|
<ActionList.Item
|
1194
|
+
role={role}
|
1181
1195
|
ref={element => dragRef(element) && dropRef(element)} // merge refs
|
1182
1196
|
selected={option.selected}
|
1183
1197
|
onSelect={onSelect}
|
@@ -0,0 +1,164 @@
|
|
1
|
+
import React, {useLayoutEffect, useRef, useState} from 'react'
|
2
|
+
import {Meta} from '@storybook/react'
|
3
|
+
import styled from 'styled-components'
|
4
|
+
|
5
|
+
import {BaseStyles, Box, Checkbox, CheckboxProps, Text, ThemeProvider} from '..'
|
6
|
+
import {action} from '@storybook/addon-actions'
|
7
|
+
import {COMMON, get} from '../constants'
|
8
|
+
|
9
|
+
export default {
|
10
|
+
title: 'Forms/Checkbox',
|
11
|
+
component: Checkbox,
|
12
|
+
decorators: [
|
13
|
+
Story => {
|
14
|
+
return (
|
15
|
+
<ThemeProvider>
|
16
|
+
<BaseStyles>
|
17
|
+
<Box paddingTop={5}>{Story()}</Box>
|
18
|
+
</BaseStyles>
|
19
|
+
</ThemeProvider>
|
20
|
+
)
|
21
|
+
}
|
22
|
+
],
|
23
|
+
argTypes: {
|
24
|
+
sx: {
|
25
|
+
table: {
|
26
|
+
disable: true
|
27
|
+
}
|
28
|
+
},
|
29
|
+
disabled: {
|
30
|
+
name: 'Disabled',
|
31
|
+
defaultValue: false,
|
32
|
+
control: {
|
33
|
+
type: 'boolean'
|
34
|
+
}
|
35
|
+
}
|
36
|
+
}
|
37
|
+
} as Meta
|
38
|
+
|
39
|
+
const StyledLabel = styled.label`
|
40
|
+
user-select: none;
|
41
|
+
font-weight: 600;
|
42
|
+
font-size: 14px;
|
43
|
+
line-height: 18px;
|
44
|
+
margin-left: 16px;
|
45
|
+
${COMMON}
|
46
|
+
`
|
47
|
+
|
48
|
+
const StyledSubLabel = styled(Text)`
|
49
|
+
color: ${get('colors.fg.muted')};
|
50
|
+
font-size: 13px;
|
51
|
+
${COMMON}
|
52
|
+
`
|
53
|
+
|
54
|
+
export const Default = (args: CheckboxProps) => {
|
55
|
+
const [isChecked, setChecked] = useState<boolean>(false)
|
56
|
+
|
57
|
+
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
58
|
+
setChecked(event.target.checked)
|
59
|
+
action('Change event triggered')
|
60
|
+
}
|
61
|
+
|
62
|
+
return (
|
63
|
+
<>
|
64
|
+
<Box as="form" sx={{p: 3, display: 'flex', alignItems: 'flex-start'}}>
|
65
|
+
<Checkbox id="controlled-checkbox" onChange={handleChange} checked={isChecked} {...args} />
|
66
|
+
<StyledLabel htmlFor="controlled-checkbox">
|
67
|
+
<Text sx={{display: 'block'}}>Default checkbox</Text>
|
68
|
+
<StyledSubLabel>controlled</StyledSubLabel>
|
69
|
+
</StyledLabel>
|
70
|
+
</Box>
|
71
|
+
<Box as="form" sx={{p: 3, display: 'flex', alignItems: 'flex-start'}}>
|
72
|
+
<Checkbox id="always-checked-checkbox" checked {...args} />
|
73
|
+
<StyledLabel htmlFor="always-checked-checkbox">
|
74
|
+
<Text sx={{display: 'block'}}>Always checked</Text>
|
75
|
+
<StyledSubLabel>checked="true"</StyledSubLabel>
|
76
|
+
</StyledLabel>
|
77
|
+
</Box>
|
78
|
+
<Box as="form" sx={{p: 3, display: 'flex', alignItems: 'flex-start'}}>
|
79
|
+
<Checkbox id="always-unchecked-checkbox" checked={false} {...args} />
|
80
|
+
<StyledLabel htmlFor="always-unchecked-checkbox">
|
81
|
+
<Text sx={{display: 'block'}}>Always unchecked</Text>
|
82
|
+
<StyledSubLabel>checked="false"</StyledSubLabel>
|
83
|
+
</StyledLabel>
|
84
|
+
</Box>
|
85
|
+
<Box as="form" sx={{p: 3, display: 'flex', alignItems: 'flex-start'}}>
|
86
|
+
<Checkbox id="disabled-checkbox" disabled checked={false} />
|
87
|
+
<StyledLabel htmlFor="disabled-checkbox">
|
88
|
+
<Text sx={{display: 'block'}}>Inactive</Text>
|
89
|
+
<StyledSubLabel>disabled="true"</StyledSubLabel>
|
90
|
+
</StyledLabel>
|
91
|
+
</Box>
|
92
|
+
</>
|
93
|
+
)
|
94
|
+
}
|
95
|
+
|
96
|
+
export const Uncontrolled = (args: CheckboxProps) => {
|
97
|
+
const checkboxRef = useRef<HTMLInputElement | null>(null)
|
98
|
+
|
99
|
+
useLayoutEffect(() => {
|
100
|
+
if (checkboxRef.current) {
|
101
|
+
checkboxRef.current.checked = true
|
102
|
+
}
|
103
|
+
}, [])
|
104
|
+
|
105
|
+
return (
|
106
|
+
<Box as="form" sx={{p: 3, display: 'flex', alignItems: 'flex-start'}}>
|
107
|
+
<Checkbox id="uncontrolled-checkbox" ref={checkboxRef} {...args} />
|
108
|
+
<StyledLabel htmlFor="uncontrolled-checkbox">
|
109
|
+
<Text sx={{display: 'block'}}>Uncontrolled checkbox</Text>
|
110
|
+
<StyledSubLabel>Checked by default</StyledSubLabel>
|
111
|
+
</StyledLabel>
|
112
|
+
</Box>
|
113
|
+
)
|
114
|
+
}
|
115
|
+
|
116
|
+
export const Indeterminate = (args: CheckboxProps) => {
|
117
|
+
const [checkboxes, setCheckboxes] = useState<boolean[]>([false, false, false, false])
|
118
|
+
|
119
|
+
const handleChange = (_: React.ChangeEvent<HTMLInputElement>, index: number) => {
|
120
|
+
const newCheckboxes = [...checkboxes]
|
121
|
+
newCheckboxes[index] = !checkboxes[index]
|
122
|
+
setCheckboxes(newCheckboxes)
|
123
|
+
}
|
124
|
+
|
125
|
+
const handleIndeterminateChange = () => {
|
126
|
+
if (checkboxes.every(checkbox => checkbox)) {
|
127
|
+
return setCheckboxes(checkboxes.map(() => false))
|
128
|
+
}
|
129
|
+
|
130
|
+
const newCheckboxes = checkboxes.map(() => true)
|
131
|
+
setCheckboxes(newCheckboxes)
|
132
|
+
}
|
133
|
+
|
134
|
+
return (
|
135
|
+
<>
|
136
|
+
<Box as="form" sx={{p: 3, display: 'flex', alignItems: 'flex-start'}}>
|
137
|
+
<Checkbox
|
138
|
+
id="indeterminate-checkbox"
|
139
|
+
checked={checkboxes.every(Boolean)}
|
140
|
+
onChange={handleIndeterminateChange}
|
141
|
+
indeterminate={!checkboxes.every(Boolean)}
|
142
|
+
/>
|
143
|
+
<StyledLabel htmlFor="controlled-checkbox">
|
144
|
+
<Text sx={{display: 'block'}}>Default checkbox</Text>
|
145
|
+
<StyledSubLabel>controlled</StyledSubLabel>
|
146
|
+
</StyledLabel>
|
147
|
+
</Box>
|
148
|
+
|
149
|
+
{checkboxes.map((field, index) => (
|
150
|
+
<Box key={`sub-checkbox-${index}`} as="form" sx={{p: 1, pl: 7, display: 'flex', alignItems: 'flex-start'}}>
|
151
|
+
<Checkbox
|
152
|
+
id={`sub-checkbox-${index}`}
|
153
|
+
checked={checkboxes[index]}
|
154
|
+
onChange={event => handleChange(event, index)}
|
155
|
+
{...args}
|
156
|
+
/>
|
157
|
+
<StyledLabel htmlFor={`sub-checkbox-${index}`}>
|
158
|
+
<Text sx={{display: 'block'}}>Checkbox {index + 1}</Text>
|
159
|
+
</StyledLabel>
|
160
|
+
</Box>
|
161
|
+
))}
|
162
|
+
</>
|
163
|
+
)
|
164
|
+
}
|
package/src/utils/testing.tsx
CHANGED
@@ -3,6 +3,9 @@ import {promisify} from 'util'
|
|
3
3
|
import renderer from 'react-test-renderer'
|
4
4
|
import enzyme from 'enzyme'
|
5
5
|
import Adapter from '@wojtekmaj/enzyme-adapter-react-17'
|
6
|
+
import {cleanup, render as HTMLRender} from '@testing-library/react'
|
7
|
+
import {axe, toHaveNoViolations} from 'jest-axe'
|
8
|
+
import type {Story as StoryType} from '@storybook/react'
|
6
9
|
import {ThemeProvider} from '..'
|
7
10
|
import {default as defaultTheme} from '../theme'
|
8
11
|
|
@@ -240,3 +243,22 @@ export function checkExports(path: string, exports: Record<any, any>): void {
|
|
240
243
|
expect(mod).toSetExports(exports)
|
241
244
|
})
|
242
245
|
}
|
246
|
+
|
247
|
+
expect.extend(toHaveNoViolations)
|
248
|
+
export function checkStoriesForAxeViolations(name: string) {
|
249
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
250
|
+
const stories = require(`../stories/${name}.stories`)
|
251
|
+
|
252
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- _meta
|
253
|
+
const {default: _meta, ...Stories} = stories
|
254
|
+
Object.values(Stories).map(Story => {
|
255
|
+
if (typeof Story !== 'function') return
|
256
|
+
|
257
|
+
it(`story ${(Story as StoryType).storyName} should have no axe violations`, async () => {
|
258
|
+
const {container} = HTMLRender(<Story />)
|
259
|
+
const results = await axe(container)
|
260
|
+
expect(results).toHaveNoViolations()
|
261
|
+
cleanup()
|
262
|
+
})
|
263
|
+
})
|
264
|
+
}
|