@arbor-education/design-system.components 0.6.0 → 0.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/CHANGELOG.md +35 -0
- package/bin/createComponent.sh +2 -2
- package/dist/components/avatar/Avatar.d.ts +1 -1
- package/dist/components/avatar/Avatar.d.ts.map +1 -1
- package/dist/components/avatar/Avatar.js +1 -1
- package/dist/components/avatar/Avatar.js.map +1 -1
- package/dist/components/avatar/Avatar.stories.d.ts.map +1 -1
- package/dist/components/avatar/Avatar.stories.js +7 -0
- package/dist/components/avatar/Avatar.stories.js.map +1 -1
- package/dist/components/badge/Badge.d.ts +12 -0
- package/dist/components/badge/Badge.d.ts.map +1 -0
- package/dist/components/badge/Badge.js +6 -0
- package/dist/components/badge/Badge.js.map +1 -0
- package/dist/components/badge/Badge.stories.d.ts +10 -0
- package/dist/components/badge/Badge.stories.d.ts.map +1 -0
- package/dist/components/badge/Badge.stories.js +51 -0
- package/dist/components/badge/Badge.stories.js.map +1 -0
- package/dist/components/badge/Badge.test.d.ts +2 -0
- package/dist/components/badge/Badge.test.d.ts.map +1 -0
- package/dist/components/badge/Badge.test.js +23 -0
- package/dist/components/badge/Badge.test.js.map +1 -0
- package/dist/components/card/Card.js +1 -1
- package/dist/components/card/Card.js.map +1 -1
- package/dist/components/combobox/Combobox.d.ts +16 -0
- package/dist/components/combobox/Combobox.d.ts.map +1 -0
- package/dist/components/combobox/Combobox.js +195 -0
- package/dist/components/combobox/Combobox.js.map +1 -0
- package/dist/components/combobox/Combobox.stories.d.ts +24 -0
- package/dist/components/combobox/Combobox.stories.d.ts.map +1 -0
- package/dist/components/combobox/Combobox.stories.js +246 -0
- package/dist/components/combobox/Combobox.stories.js.map +1 -0
- package/dist/components/combobox/Combobox.test.d.ts +2 -0
- package/dist/components/combobox/Combobox.test.d.ts.map +1 -0
- package/dist/components/combobox/Combobox.test.js +798 -0
- package/dist/components/combobox/Combobox.test.js.map +1 -0
- package/dist/components/combobox/ComboboxButtonTrigger.d.ts +28 -0
- package/dist/components/combobox/ComboboxButtonTrigger.d.ts.map +1 -0
- package/dist/components/combobox/ComboboxButtonTrigger.js +64 -0
- package/dist/components/combobox/ComboboxButtonTrigger.js.map +1 -0
- package/dist/components/combobox/ComboboxListbox.d.ts +44 -0
- package/dist/components/combobox/ComboboxListbox.d.ts.map +1 -0
- package/dist/components/combobox/ComboboxListbox.js +37 -0
- package/dist/components/combobox/ComboboxListbox.js.map +1 -0
- package/dist/components/combobox/ComboboxOptionRow.d.ts +23 -0
- package/dist/components/combobox/ComboboxOptionRow.d.ts.map +1 -0
- package/dist/components/combobox/ComboboxOptionRow.js +27 -0
- package/dist/components/combobox/ComboboxOptionRow.js.map +1 -0
- package/dist/components/combobox/ComboboxTrigger.d.ts +35 -0
- package/dist/components/combobox/ComboboxTrigger.d.ts.map +1 -0
- package/dist/components/combobox/ComboboxTrigger.js +15 -0
- package/dist/components/combobox/ComboboxTrigger.js.map +1 -0
- package/dist/components/combobox/buildListboxDisplayOptions.d.ts +3 -0
- package/dist/components/combobox/buildListboxDisplayOptions.d.ts.map +1 -0
- package/dist/components/combobox/buildListboxDisplayOptions.js +13 -0
- package/dist/components/combobox/buildListboxDisplayOptions.js.map +1 -0
- package/dist/components/combobox/buildListboxDisplayOptions.test.d.ts +2 -0
- package/dist/components/combobox/buildListboxDisplayOptions.test.d.ts.map +1 -0
- package/dist/components/combobox/buildListboxDisplayOptions.test.js +22 -0
- package/dist/components/combobox/buildListboxDisplayOptions.test.js.map +1 -0
- package/dist/components/combobox/comboboxKeyboardTypes.d.ts +41 -0
- package/dist/components/combobox/comboboxKeyboardTypes.d.ts.map +1 -0
- package/dist/components/combobox/comboboxKeyboardTypes.js +2 -0
- package/dist/components/combobox/comboboxKeyboardTypes.js.map +1 -0
- package/dist/components/combobox/highlightLabel.d.ts +10 -0
- package/dist/components/combobox/highlightLabel.d.ts.map +1 -0
- package/dist/components/combobox/highlightLabel.js +18 -0
- package/dist/components/combobox/highlightLabel.js.map +1 -0
- package/dist/components/combobox/normaliseComboboxQuery.d.ts +2 -0
- package/dist/components/combobox/normaliseComboboxQuery.d.ts.map +1 -0
- package/dist/components/combobox/normaliseComboboxQuery.js +2 -0
- package/dist/components/combobox/normaliseComboboxQuery.js.map +1 -0
- package/dist/components/combobox/types.d.ts +46 -0
- package/dist/components/combobox/types.d.ts.map +1 -0
- package/dist/components/combobox/types.js +2 -0
- package/dist/components/combobox/types.js.map +1 -0
- package/dist/components/combobox/useChipSelection.d.ts +11 -0
- package/dist/components/combobox/useChipSelection.d.ts.map +1 -0
- package/dist/components/combobox/useChipSelection.js +35 -0
- package/dist/components/combobox/useChipSelection.js.map +1 -0
- package/dist/components/combobox/useComboboxChipKeyboard.d.ts +3 -0
- package/dist/components/combobox/useComboboxChipKeyboard.d.ts.map +1 -0
- package/dist/components/combobox/useComboboxChipKeyboard.js +103 -0
- package/dist/components/combobox/useComboboxChipKeyboard.js.map +1 -0
- package/dist/components/combobox/useComboboxChipKeyboard.test.d.ts +2 -0
- package/dist/components/combobox/useComboboxChipKeyboard.test.d.ts.map +1 -0
- package/dist/components/combobox/useComboboxChipKeyboard.test.js +116 -0
- package/dist/components/combobox/useComboboxChipKeyboard.test.js.map +1 -0
- package/dist/components/combobox/useComboboxKeyboard.d.ts +4 -0
- package/dist/components/combobox/useComboboxKeyboard.d.ts.map +1 -0
- package/dist/components/combobox/useComboboxKeyboard.js +68 -0
- package/dist/components/combobox/useComboboxKeyboard.js.map +1 -0
- package/dist/components/combobox/useComboboxListboxDom.d.ts +11 -0
- package/dist/components/combobox/useComboboxListboxDom.d.ts.map +1 -0
- package/dist/components/combobox/useComboboxListboxDom.js +15 -0
- package/dist/components/combobox/useComboboxListboxDom.js.map +1 -0
- package/dist/components/combobox/useComboboxListboxKeyboard.d.ts +3 -0
- package/dist/components/combobox/useComboboxListboxKeyboard.d.ts.map +1 -0
- package/dist/components/combobox/useComboboxListboxKeyboard.js +143 -0
- package/dist/components/combobox/useComboboxListboxKeyboard.js.map +1 -0
- package/dist/components/combobox/useComboboxListboxKeyboard.test.d.ts +2 -0
- package/dist/components/combobox/useComboboxListboxKeyboard.test.d.ts.map +1 -0
- package/dist/components/combobox/useComboboxListboxKeyboard.test.js +152 -0
- package/dist/components/combobox/useComboboxListboxKeyboard.test.js.map +1 -0
- package/dist/components/combobox/useComboboxPopoverBehavior.d.ts +38 -0
- package/dist/components/combobox/useComboboxPopoverBehavior.d.ts.map +1 -0
- package/dist/components/combobox/useComboboxPopoverBehavior.js +104 -0
- package/dist/components/combobox/useComboboxPopoverBehavior.js.map +1 -0
- package/dist/components/combobox/useComboboxState.d.ts +27 -0
- package/dist/components/combobox/useComboboxState.d.ts.map +1 -0
- package/dist/components/combobox/useComboboxState.js +122 -0
- package/dist/components/combobox/useComboboxState.js.map +1 -0
- package/dist/components/combobox/useElementWidth.d.ts +2 -0
- package/dist/components/combobox/useElementWidth.d.ts.map +1 -0
- package/dist/components/combobox/useElementWidth.js +31 -0
- package/dist/components/combobox/useElementWidth.js.map +1 -0
- package/dist/components/combobox/useVisibleChips.d.ts +21 -0
- package/dist/components/combobox/useVisibleChips.d.ts.map +1 -0
- package/dist/components/combobox/useVisibleChips.js +59 -0
- package/dist/components/combobox/useVisibleChips.js.map +1 -0
- package/dist/components/combobox/useVisibleChips.test.d.ts +2 -0
- package/dist/components/combobox/useVisibleChips.test.d.ts.map +1 -0
- package/dist/components/combobox/useVisibleChips.test.js +81 -0
- package/dist/components/combobox/useVisibleChips.test.js.map +1 -0
- package/dist/components/dot/Dot.d.ts +8 -0
- package/dist/components/dot/Dot.d.ts.map +1 -0
- package/dist/components/dot/Dot.js +6 -0
- package/dist/components/dot/Dot.js.map +1 -0
- package/dist/components/dot/Dot.stories.d.ts +15 -0
- package/dist/components/dot/Dot.stories.d.ts.map +1 -0
- package/dist/components/dot/Dot.stories.js +25 -0
- package/dist/components/dot/Dot.stories.js.map +1 -0
- package/dist/components/dot/Dot.test.d.ts +2 -0
- package/dist/components/dot/Dot.test.d.ts.map +1 -0
- package/dist/components/dot/Dot.test.js +19 -0
- package/dist/components/dot/Dot.test.js.map +1 -0
- package/dist/components/formField/FormField.d.ts +8 -4
- package/dist/components/formField/FormField.d.ts.map +1 -1
- package/dist/components/formField/FormField.js +7 -6
- package/dist/components/formField/FormField.js.map +1 -1
- package/dist/components/formField/FormField.stories.d.ts +1 -0
- package/dist/components/formField/FormField.stories.d.ts.map +1 -1
- package/dist/components/formField/FormField.stories.js +13 -1
- package/dist/components/formField/FormField.stories.js.map +1 -1
- package/dist/components/formField/FormField.test.js +10 -0
- package/dist/components/formField/FormField.test.js.map +1 -1
- package/dist/components/icon/allowedIcons.d.ts +1 -0
- package/dist/components/icon/allowedIcons.d.ts.map +1 -1
- package/dist/components/icon/allowedIcons.js +2 -1
- package/dist/components/icon/allowedIcons.js.map +1 -1
- package/dist/components/progress/Progress.stories.d.ts +49 -49
- package/dist/components/row/Row.d.ts +10 -0
- package/dist/components/row/Row.d.ts.map +1 -0
- package/dist/components/row/Row.js +17 -0
- package/dist/components/row/Row.js.map +1 -0
- package/dist/components/row/Row.stories.d.ts +15 -0
- package/dist/components/row/Row.stories.d.ts.map +1 -0
- package/dist/components/row/Row.stories.js +65 -0
- package/dist/components/row/Row.stories.js.map +1 -0
- package/dist/components/row/Row.test.d.ts +2 -0
- package/dist/components/row/Row.test.d.ts.map +1 -0
- package/dist/components/row/Row.test.js +62 -0
- package/dist/components/row/Row.test.js.map +1 -0
- package/dist/components/section/Section.stories.d.ts +27 -0
- package/dist/components/section/Section.stories.d.ts.map +1 -1
- package/dist/components/section/Section.stories.js +45 -1
- package/dist/components/section/Section.stories.js.map +1 -1
- package/dist/components/singleUser/SingleUser.d.ts +15 -0
- package/dist/components/singleUser/SingleUser.d.ts.map +1 -0
- package/dist/components/singleUser/SingleUser.js +9 -0
- package/dist/components/singleUser/SingleUser.js.map +1 -0
- package/dist/components/singleUser/SingleUser.stories.d.ts +11 -0
- package/dist/components/singleUser/SingleUser.stories.d.ts.map +1 -0
- package/dist/components/singleUser/SingleUser.stories.js +52 -0
- package/dist/components/singleUser/SingleUser.stories.js.map +1 -0
- package/dist/components/singleUser/SingleUser.test.d.ts +2 -0
- package/dist/components/singleUser/SingleUser.test.d.ts.map +1 -0
- package/dist/components/singleUser/SingleUser.test.js +30 -0
- package/dist/components/singleUser/SingleUser.test.js.map +1 -0
- package/dist/components/table/cellRenderers/SelectDropdownCellRenderer.d.ts.map +1 -1
- package/dist/components/table/cellRenderers/SelectDropdownCellRenderer.js +9 -3
- package/dist/components/table/cellRenderers/SelectDropdownCellRenderer.js.map +1 -1
- package/dist/components/tabs/TabsItem.stories.d.ts +2 -2
- package/dist/components/tag/Tag.d.ts +9 -6
- package/dist/components/tag/Tag.d.ts.map +1 -1
- package/dist/components/tag/Tag.js +8 -2
- package/dist/components/tag/Tag.js.map +1 -1
- package/dist/components/tag/Tag.stories.d.ts +11 -6
- package/dist/components/tag/Tag.stories.d.ts.map +1 -1
- package/dist/components/tag/Tag.stories.js +68 -4
- package/dist/components/tag/Tag.stories.js.map +1 -1
- package/dist/components/tag/Tag.test.js +86 -50
- package/dist/components/tag/Tag.test.js.map +1 -1
- package/dist/components/toggle/Toggle.d.ts +3 -0
- package/dist/components/toggle/Toggle.d.ts.map +1 -0
- package/dist/components/toggle/Toggle.js +8 -0
- package/dist/components/toggle/Toggle.js.map +1 -0
- package/dist/components/toggle/Toggle.stories.d.ts +97 -0
- package/dist/components/toggle/Toggle.stories.d.ts.map +1 -0
- package/dist/components/toggle/Toggle.stories.js +186 -0
- package/dist/components/toggle/Toggle.stories.js.map +1 -0
- package/dist/components/toggle/Toggle.test.d.ts +2 -0
- package/dist/components/toggle/Toggle.test.d.ts.map +1 -0
- package/dist/components/toggle/Toggle.test.js +58 -0
- package/dist/components/toggle/Toggle.test.js.map +1 -0
- package/dist/index.css +703 -25
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +35 -25
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +31 -25
- package/dist/index.js.map +1 -1
- package/dist/mocks/comboboxStoryOptions.d.ts +5 -0
- package/dist/mocks/comboboxStoryOptions.d.ts.map +1 -0
- package/dist/mocks/comboboxStoryOptions.js +22 -0
- package/dist/mocks/comboboxStoryOptions.js.map +1 -0
- package/dist/utils/isSelectAllChord.d.ts +5 -0
- package/dist/utils/isSelectAllChord.d.ts.map +1 -0
- package/dist/utils/isSelectAllChord.js +7 -0
- package/dist/utils/isSelectAllChord.js.map +1 -0
- package/dist/utils/isSelectAllChord.test.d.ts +2 -0
- package/dist/utils/isSelectAllChord.test.d.ts.map +1 -0
- package/dist/utils/isSelectAllChord.test.js +19 -0
- package/dist/utils/isSelectAllChord.test.js.map +1 -0
- package/dist/utils/nextCircularIndex.d.ts +3 -0
- package/dist/utils/nextCircularIndex.d.ts.map +1 -0
- package/dist/utils/nextCircularIndex.js +10 -0
- package/dist/utils/nextCircularIndex.js.map +1 -0
- package/dist/utils/nextCircularIndex.test.d.ts +2 -0
- package/dist/utils/nextCircularIndex.test.d.ts.map +1 -0
- package/dist/utils/nextCircularIndex.test.js +23 -0
- package/dist/utils/nextCircularIndex.test.js.map +1 -0
- package/dist/utils/scrollElementIntoViewById.d.ts +2 -0
- package/dist/utils/scrollElementIntoViewById.d.ts.map +1 -0
- package/dist/utils/scrollElementIntoViewById.js +16 -0
- package/dist/utils/scrollElementIntoViewById.js.map +1 -0
- package/dist/utils/scrollElementIntoViewById.test.d.ts +2 -0
- package/dist/utils/scrollElementIntoViewById.test.d.ts.map +1 -0
- package/dist/utils/scrollElementIntoViewById.test.js +31 -0
- package/dist/utils/scrollElementIntoViewById.test.js.map +1 -0
- package/package.json +1 -1
- package/src/components/avatar/Avatar.stories.tsx +8 -0
- package/src/components/avatar/Avatar.tsx +3 -3
- package/src/components/badge/Badge.stories.tsx +74 -0
- package/src/components/badge/Badge.test.tsx +28 -0
- package/src/components/badge/Badge.tsx +35 -0
- package/src/components/badge/badge.scss +86 -0
- package/src/components/card/Card.tsx +1 -1
- package/src/components/combobox/Combobox.stories.tsx +340 -0
- package/src/components/combobox/Combobox.test.tsx +1160 -0
- package/src/components/combobox/Combobox.tsx +434 -0
- package/src/components/combobox/ComboboxButtonTrigger.tsx +195 -0
- package/src/components/combobox/ComboboxListbox.tsx +224 -0
- package/src/components/combobox/ComboboxOptionRow.tsx +128 -0
- package/src/components/combobox/ComboboxTrigger.tsx +134 -0
- package/src/components/combobox/buildListboxDisplayOptions.test.ts +24 -0
- package/src/components/combobox/buildListboxDisplayOptions.ts +12 -0
- package/src/components/combobox/combobox.scss +390 -0
- package/src/components/combobox/comboboxKeyboardTypes.ts +45 -0
- package/src/components/combobox/highlightLabel.tsx +42 -0
- package/src/components/combobox/normaliseComboboxQuery.ts +1 -0
- package/src/components/combobox/types.ts +53 -0
- package/src/components/combobox/useChipSelection.ts +53 -0
- package/src/components/combobox/useComboboxChipKeyboard.test.tsx +141 -0
- package/src/components/combobox/useComboboxChipKeyboard.ts +121 -0
- package/src/components/combobox/useComboboxKeyboard.ts +108 -0
- package/src/components/combobox/useComboboxListboxDom.ts +36 -0
- package/src/components/combobox/useComboboxListboxKeyboard.test.tsx +186 -0
- package/src/components/combobox/useComboboxListboxKeyboard.ts +172 -0
- package/src/components/combobox/useComboboxPopoverBehavior.ts +179 -0
- package/src/components/combobox/useComboboxState.ts +232 -0
- package/src/components/combobox/useElementWidth.ts +40 -0
- package/src/components/combobox/useVisibleChips.test.tsx +91 -0
- package/src/components/combobox/useVisibleChips.ts +100 -0
- package/src/components/dot/Dot.stories.tsx +41 -0
- package/src/components/dot/Dot.test.tsx +21 -0
- package/src/components/dot/Dot.tsx +18 -0
- package/src/components/dot/dot.scss +35 -0
- package/src/components/formField/FormField.stories.tsx +30 -1
- package/src/components/formField/FormField.test.tsx +20 -0
- package/src/components/formField/FormField.tsx +11 -5
- package/src/components/formField/inputs/number/numberInput.scss +12 -4
- package/src/components/icon/allowedIcons.tsx +2 -0
- package/src/components/pill/pill.scss +4 -6
- package/src/components/row/Row.stories.tsx +85 -0
- package/src/components/row/Row.test.tsx +82 -0
- package/src/components/row/Row.tsx +54 -0
- package/src/components/row/row.scss +61 -0
- package/src/components/section/Section.stories.tsx +56 -0
- package/src/components/singleUser/SingleUser.stories.tsx +63 -0
- package/src/components/singleUser/SingleUser.test.tsx +61 -0
- package/src/components/singleUser/SingleUser.tsx +45 -0
- package/src/components/singleUser/singleUser.scss +14 -0
- package/src/components/table/cellRenderers/SelectDropdownCellRenderer.tsx +19 -3
- package/src/components/tag/Tag.stories.tsx +88 -6
- package/src/components/tag/Tag.test.tsx +110 -44
- package/src/components/tag/Tag.tsx +38 -14
- package/src/components/tag/tag.scss +45 -30
- package/src/components/toggle/Toggle.stories.tsx +239 -0
- package/src/components/toggle/Toggle.test.tsx +66 -0
- package/src/components/toggle/Toggle.tsx +12 -0
- package/src/components/toggle/toggle.scss +126 -0
- package/src/index.scss +6 -0
- package/src/index.ts +48 -31
- package/src/mocks/comboboxStoryOptions.ts +25 -0
- package/src/tokens.scss +33 -4
- package/src/utils/isSelectAllChord.test.ts +24 -0
- package/src/utils/isSelectAllChord.ts +8 -0
- package/src/utils/nextCircularIndex.test.ts +26 -0
- package/src/utils/nextCircularIndex.ts +15 -0
- package/src/utils/scrollElementIntoViewById.test.ts +38 -0
- package/src/utils/scrollElementIntoViewById.ts +20 -0
- package/tokens/json/Arbor.json +3828 -3704
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
.ds-row {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: row;
|
|
4
|
+
justify-content: space-between;
|
|
5
|
+
align-items: center;
|
|
6
|
+
background-color: var(--section-list-row-default-color-background);
|
|
7
|
+
padding: var(--section-list-row-spacing-vertical) var(--section-list-row-spacing-horizontal);
|
|
8
|
+
border-radius: var(--section-list-row-radius);
|
|
9
|
+
|
|
10
|
+
.ds-row__icon-click {
|
|
11
|
+
flex-shrink: 0;
|
|
12
|
+
margin-left: var(--spacing-small);
|
|
13
|
+
stroke: var(--section-list-row-default-color-icon-arrow);
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
&.ds-icon-arrow-right {
|
|
17
|
+
display: none;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
&--clickable {
|
|
22
|
+
cursor: pointer;
|
|
23
|
+
|
|
24
|
+
&:hover {
|
|
25
|
+
background-color: var(--section-list-row-hover-hover-bg);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
&:focus {
|
|
30
|
+
box-shadow: 0 0 0 3px var(--color-brand-300);
|
|
31
|
+
outline: none;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
&:hover {
|
|
35
|
+
.ds-row__icon-click {
|
|
36
|
+
stroke: var(--section-list-row-hover-color-icon-arrow);
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
&.ds-icon-chevron-right {
|
|
40
|
+
display: none;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
&.ds-icon-arrow-right {
|
|
44
|
+
display: block;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
&__label {
|
|
50
|
+
min-width: 190px;
|
|
51
|
+
font-weight: var(--font-weight-semi-bold);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
&__value {
|
|
55
|
+
flex-grow: 1;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
&__note {
|
|
59
|
+
font-style: italic;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Meta } from '@storybook/react-vite';
|
|
2
2
|
import { Section } from './Section';
|
|
3
|
+
import { Row } from 'Components/row/Row';
|
|
3
4
|
|
|
4
5
|
const meta: Meta<typeof Section> = {
|
|
5
6
|
title: 'Components/Section',
|
|
@@ -31,4 +32,59 @@ export const NestedSections = {
|
|
|
31
32
|
},
|
|
32
33
|
};
|
|
33
34
|
|
|
35
|
+
export const WithRows = {
|
|
36
|
+
args: {
|
|
37
|
+
title: 'Student Details',
|
|
38
|
+
children: [
|
|
39
|
+
<Row key={1} label="First Name" value="Jacob" />,
|
|
40
|
+
<Row key={2} label="Last Name" value="Black" />,
|
|
41
|
+
<Row key={3} label="Year Group" value="Year 10" note="2024/2025" />,
|
|
42
|
+
<Row key={4} label="Form Group" value="10A" />,
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const WithClickableRows = {
|
|
48
|
+
args: {
|
|
49
|
+
title: 'Quick Links',
|
|
50
|
+
buttonText: 'Edit',
|
|
51
|
+
children: [
|
|
52
|
+
<Row key={1} label="Attendance" value="96%" note="Above target" onClick={() => { console.log('click!'); }} />,
|
|
53
|
+
<Row key={2} label="Behaviour" value="3 positive points" onClick={() => { console.log('click!'); }} />,
|
|
54
|
+
<Row key={3} label="Assessment" value="On track" note="Last updated 2 days ago" onClick={() => { console.log('click!'); }} />,
|
|
55
|
+
],
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const CollapsibleWithRows = {
|
|
60
|
+
args: {
|
|
61
|
+
title: 'Contact Information',
|
|
62
|
+
collapsible: true,
|
|
63
|
+
children: [
|
|
64
|
+
<Row key={1} label="Email" value="jacob.black@forks.edu" />,
|
|
65
|
+
<Row key={2} label="Phone" value="01onal 555 0123" />,
|
|
66
|
+
<Row key={3} label="Address" value="La Push, Washington" note="Primary" />,
|
|
67
|
+
],
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export const NestedSectionsWithRows = {
|
|
72
|
+
args: {
|
|
73
|
+
title: 'Student Profile',
|
|
74
|
+
collapsible: true,
|
|
75
|
+
children: [
|
|
76
|
+
<Section key={1} title="Personal Details" collapsible>
|
|
77
|
+
<Row label="First Name" value="Jacob" />
|
|
78
|
+
<Row label="Last Name" value="Black" />
|
|
79
|
+
<Row label="Date of Birth" value="14/01/1990" note="Age 36" />
|
|
80
|
+
</Section>,
|
|
81
|
+
<Section key={2} title="Academic" collapsible>
|
|
82
|
+
<Row label="Year Group" value="Year 10" note="2024/2025" />
|
|
83
|
+
<Row label="Form Group" value="10A" />
|
|
84
|
+
<Row label="Attendance" value="96%" note="Above target" onClick={() => { console.log('click!'); }} />
|
|
85
|
+
</Section>,
|
|
86
|
+
],
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
|
|
34
90
|
export default meta;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { SingleUser } from './SingleUser';
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof SingleUser> = {
|
|
5
|
+
title: 'Components/SingleUser',
|
|
6
|
+
component: SingleUser,
|
|
7
|
+
tags: ['autodocs'],
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default meta;
|
|
11
|
+
|
|
12
|
+
type Story = StoryObj<typeof SingleUser>;
|
|
13
|
+
|
|
14
|
+
const withDescription = (story: Story, description: string): Story => ({
|
|
15
|
+
...story,
|
|
16
|
+
parameters: {
|
|
17
|
+
...story.parameters,
|
|
18
|
+
docs: {
|
|
19
|
+
...story.parameters?.docs,
|
|
20
|
+
description: {
|
|
21
|
+
story: description,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const sampleSrc = 'https://i.pravatar.cc/150?img=12';
|
|
28
|
+
|
|
29
|
+
export const WithImage: Story = withDescription({
|
|
30
|
+
args: {
|
|
31
|
+
label: 'Jordan Matthews',
|
|
32
|
+
src: sampleSrc,
|
|
33
|
+
},
|
|
34
|
+
}, 'Displays `SingleUser` with an avatar image and the default small layout.');
|
|
35
|
+
|
|
36
|
+
export const WithInitials: Story = withDescription({
|
|
37
|
+
args: {
|
|
38
|
+
label: 'Riley Chen',
|
|
39
|
+
initials: 'RC',
|
|
40
|
+
},
|
|
41
|
+
}, 'Uses initials when no image source is provided.');
|
|
42
|
+
|
|
43
|
+
export const Placeholder: Story = withDescription({
|
|
44
|
+
args: {
|
|
45
|
+
label: 'Invited user',
|
|
46
|
+
},
|
|
47
|
+
}, 'Shows the placeholder avatar treatment when neither image nor initials are supplied.');
|
|
48
|
+
|
|
49
|
+
export const MediumAvatar: Story = withDescription({
|
|
50
|
+
name: 'Size override (medium)',
|
|
51
|
+
args: {
|
|
52
|
+
label: 'Taylor Brooks',
|
|
53
|
+
initials: 'TB',
|
|
54
|
+
size: 'medium',
|
|
55
|
+
},
|
|
56
|
+
}, 'Demonstrates overriding the default avatar size within the SingleUser pill.');
|
|
57
|
+
|
|
58
|
+
export const LongLabel: Story = withDescription({
|
|
59
|
+
args: {
|
|
60
|
+
label: 'Dr. Alexandrina Constantinopolous-Worthington',
|
|
61
|
+
initials: 'AC',
|
|
62
|
+
},
|
|
63
|
+
}, 'Exercises the component with a longer label so text wrapping and spacing can be reviewed.');
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import '@testing-library/jest-dom/vitest';
|
|
2
|
+
import { render, screen } from '@testing-library/react';
|
|
3
|
+
import { describe, expect, test } from 'vitest';
|
|
4
|
+
import { SingleUser } from './SingleUser';
|
|
5
|
+
|
|
6
|
+
describe('SingleUser', () => {
|
|
7
|
+
test('renders label text', () => {
|
|
8
|
+
render(
|
|
9
|
+
<SingleUser
|
|
10
|
+
label="Jamie Smith"
|
|
11
|
+
initials="JS"
|
|
12
|
+
/>,
|
|
13
|
+
);
|
|
14
|
+
expect(screen.getByText('Jamie Smith')).toBeInTheDocument();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test('hides Avatar from screen readers', () => {
|
|
18
|
+
const { container } = render(
|
|
19
|
+
<SingleUser
|
|
20
|
+
label="Pat Lee"
|
|
21
|
+
initials="PL"
|
|
22
|
+
/>,
|
|
23
|
+
);
|
|
24
|
+
const avatar = container.querySelector('.ds-avatar');
|
|
25
|
+
expect(avatar).toHaveAttribute('aria-hidden', 'true');
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('defaults Avatar to small size', () => {
|
|
29
|
+
const { container } = render(
|
|
30
|
+
<SingleUser
|
|
31
|
+
label="Sam"
|
|
32
|
+
initials="S"
|
|
33
|
+
/>,
|
|
34
|
+
);
|
|
35
|
+
expect(container.querySelector('.ds-avatar--small')).toBeInTheDocument();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test('allows size override', () => {
|
|
39
|
+
const { container } = render(
|
|
40
|
+
<SingleUser
|
|
41
|
+
label="Sam"
|
|
42
|
+
initials="S"
|
|
43
|
+
size="medium"
|
|
44
|
+
/>,
|
|
45
|
+
);
|
|
46
|
+
expect(container.querySelector('.ds-avatar--medium')).toBeInTheDocument();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('applies className to root and avatarClassName to Avatar', () => {
|
|
50
|
+
const { container } = render(
|
|
51
|
+
<SingleUser
|
|
52
|
+
label="User"
|
|
53
|
+
initials="U"
|
|
54
|
+
className="my-chip"
|
|
55
|
+
avatarClassName="my-avatar"
|
|
56
|
+
/>,
|
|
57
|
+
);
|
|
58
|
+
expect(container.querySelector('.ds-single-user.my-chip')).toBeInTheDocument();
|
|
59
|
+
expect(container.querySelector('.ds-avatar.my-avatar')).toBeInTheDocument();
|
|
60
|
+
});
|
|
61
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
2
|
+
import { Avatar, type AvatarProps, type AvatarSize } from 'Components/avatar/Avatar';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
export type SingleUserProps = {
|
|
6
|
+
label: string;
|
|
7
|
+
className?: string;
|
|
8
|
+
avatarClassName?: string;
|
|
9
|
+
size?: AvatarSize;
|
|
10
|
+
} & Omit<AvatarProps, 'className' | 'alt' | 'size'>;
|
|
11
|
+
|
|
12
|
+
export const SingleUser = React.forwardRef<HTMLSpanElement, SingleUserProps>(
|
|
13
|
+
(
|
|
14
|
+
{
|
|
15
|
+
label,
|
|
16
|
+
className,
|
|
17
|
+
avatarClassName,
|
|
18
|
+
size = 'small',
|
|
19
|
+
...avatarProps
|
|
20
|
+
},
|
|
21
|
+
ref,
|
|
22
|
+
) => {
|
|
23
|
+
return (
|
|
24
|
+
<span
|
|
25
|
+
ref={ref}
|
|
26
|
+
className={classNames('ds-single-user', className)}
|
|
27
|
+
>
|
|
28
|
+
|
|
29
|
+
<Avatar
|
|
30
|
+
{...avatarProps}
|
|
31
|
+
size={size}
|
|
32
|
+
aria-hidden="true"
|
|
33
|
+
alt=""
|
|
34
|
+
className={avatarClassName}
|
|
35
|
+
/>
|
|
36
|
+
|
|
37
|
+
<span className="ds-single-user__label">
|
|
38
|
+
{label}
|
|
39
|
+
</span>
|
|
40
|
+
</span>
|
|
41
|
+
);
|
|
42
|
+
},
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
SingleUser.displayName = 'SingleUser';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
.ds-single-user {
|
|
2
|
+
box-sizing: border-box;
|
|
3
|
+
display: inline-flex;
|
|
4
|
+
align-items: center;
|
|
5
|
+
gap: var(--single-user-spacing-gap);
|
|
6
|
+
padding-block: 0;
|
|
7
|
+
padding-inline: 0 var(--single-user-spacing-padding-inline-end);
|
|
8
|
+
border-radius: var(--single-user-radius);
|
|
9
|
+
border: var(--single-user-border-width) solid var(--single-user-color-border);
|
|
10
|
+
background-color: var(--single-user-color-background);
|
|
11
|
+
color: var(--single-user-color-text);
|
|
12
|
+
font-size: var(--single-user-font-size);
|
|
13
|
+
line-height: var(--line-height-tight);
|
|
14
|
+
}
|
|
@@ -13,6 +13,13 @@ import { useComponentDidMount } from 'Utils/hooks/useComponentDidMount';
|
|
|
13
13
|
type SelectDropdownCellRendererProps = CustomCellRendererProps
|
|
14
14
|
& SelectDropdownInputProps;
|
|
15
15
|
|
|
16
|
+
type SelectDropdownCellRendererOption = Omit<
|
|
17
|
+
SelectDropdownInputProps['options'][number],
|
|
18
|
+
'value'
|
|
19
|
+
> & {
|
|
20
|
+
value: string | number;
|
|
21
|
+
};
|
|
22
|
+
|
|
16
23
|
export const SelectDropdownCellRenderer = (
|
|
17
24
|
props: SelectDropdownCellRendererProps,
|
|
18
25
|
) => {
|
|
@@ -31,6 +38,12 @@ export const SelectDropdownCellRenderer = (
|
|
|
31
38
|
alwaysShowPlaceholder = false,
|
|
32
39
|
} = props;
|
|
33
40
|
|
|
41
|
+
const rawOptions: SelectDropdownCellRendererOption[] = options;
|
|
42
|
+
const normalisedOptions: SelectDropdownInputProps['options'] = rawOptions.map(option => ({
|
|
43
|
+
...option,
|
|
44
|
+
value: String(option.value),
|
|
45
|
+
}));
|
|
46
|
+
|
|
34
47
|
const valueStr = value != null && value !== '' ? String(value) : '';
|
|
35
48
|
const initialSelectedValues = valueStr ? [valueStr] : [];
|
|
36
49
|
|
|
@@ -65,15 +78,18 @@ export const SelectDropdownCellRenderer = (
|
|
|
65
78
|
aria-describedBy={ariaDescribedBy}
|
|
66
79
|
aria-invalid={ariaInvalid}
|
|
67
80
|
alwaysShowPlaceholder={alwaysShowPlaceholder}
|
|
68
|
-
options={
|
|
81
|
+
options={normalisedOptions}
|
|
69
82
|
placeholder={placeholder}
|
|
70
83
|
initialSelectedValues={initialSelectedValues}
|
|
71
84
|
open={isOpen}
|
|
72
85
|
onOpenChange={setIsOpen}
|
|
73
86
|
multiple={false}
|
|
74
87
|
onSelectionChange={(newValue) => {
|
|
75
|
-
if (column) {
|
|
76
|
-
|
|
88
|
+
if (column && newValue[0] != null) {
|
|
89
|
+
const selectedOption = rawOptions.find(
|
|
90
|
+
option => String(option.value) === newValue[0],
|
|
91
|
+
);
|
|
92
|
+
node.setDataValue(column, selectedOption?.value ?? newValue[0]);
|
|
77
93
|
}
|
|
78
94
|
}}
|
|
79
95
|
/>
|
|
@@ -1,16 +1,98 @@
|
|
|
1
|
-
import type { Meta } from '@storybook/react-vite';
|
|
2
|
-
import {
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { fn } from '@storybook/test';
|
|
3
|
+
import { Dot } from 'Components/dot/Dot';
|
|
4
|
+
import { Icon } from 'Components/icon/Icon';
|
|
5
|
+
import { Tag, type TagColor } from './Tag';
|
|
3
6
|
|
|
4
7
|
const meta: Meta<typeof Tag> = {
|
|
5
8
|
tags: ['autodocs'],
|
|
6
9
|
title: 'Components/Tag',
|
|
7
10
|
component: Tag,
|
|
11
|
+
parameters: {
|
|
12
|
+
docs: {
|
|
13
|
+
description: {
|
|
14
|
+
component:
|
|
15
|
+
'Displays compact tag content with optional start/end slots and removable actions. Removable tags keep their remove button in the tab order by default; composite parents such as Combobox can pass `removeButtonTabIndex={-1}` for roving tab focus.',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
8
19
|
};
|
|
9
20
|
|
|
10
|
-
export
|
|
21
|
+
export default meta;
|
|
22
|
+
|
|
23
|
+
type Story = StoryObj<typeof Tag>;
|
|
24
|
+
|
|
25
|
+
const withDescription = (story: Story, description: string): Story => ({
|
|
26
|
+
...story,
|
|
27
|
+
parameters: {
|
|
28
|
+
...story.parameters,
|
|
29
|
+
docs: {
|
|
30
|
+
...story.parameters?.docs,
|
|
31
|
+
description: {
|
|
32
|
+
story: description,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
export const Default: Story = withDescription({
|
|
39
|
+
args: { children: 'Tag content' },
|
|
40
|
+
}, 'Shows the default neutral Tag with plain text content.');
|
|
41
|
+
|
|
42
|
+
export const WithColour: Story = withDescription({
|
|
43
|
+
args: { children: 'Blue tag', color: 'blue' },
|
|
44
|
+
}, 'Applies one of the semantic colour variants to the Tag.');
|
|
45
|
+
|
|
46
|
+
export const Selected: Story = withDescription({
|
|
47
|
+
args: { children: 'Selected tag', color: 'blue', selected: true },
|
|
48
|
+
}, 'Shows the selected treatment, which intentionally prioritises selection styling over the base colour variant.');
|
|
49
|
+
|
|
50
|
+
export const WithDot: Story = withDescription({
|
|
11
51
|
args: {
|
|
12
|
-
|
|
52
|
+
children: 'With dot',
|
|
53
|
+
slotStart: <Dot colour="purple" />,
|
|
13
54
|
},
|
|
14
|
-
};
|
|
55
|
+
}, 'Uses `slotStart` to render a decorative dot before the label.');
|
|
15
56
|
|
|
16
|
-
export
|
|
57
|
+
export const WithIcon: Story = withDescription({
|
|
58
|
+
args: {
|
|
59
|
+
children: 'Alice Johnson',
|
|
60
|
+
slotStart: <Icon name="user" size={12} />,
|
|
61
|
+
},
|
|
62
|
+
}, 'Uses `slotStart` to show an icon before the Tag label.');
|
|
63
|
+
|
|
64
|
+
export const Removable: Story = withDescription({
|
|
65
|
+
args: {
|
|
66
|
+
children: 'Removable tag',
|
|
67
|
+
onRemove: fn(),
|
|
68
|
+
removeLabel: 'Remove removable tag',
|
|
69
|
+
},
|
|
70
|
+
}, 'Demonstrates a removable Tag with the default close affordance and a custom accessible remove label. The remove button is tabbable by default.');
|
|
71
|
+
|
|
72
|
+
export const RemovableWithIcon: Story = withDescription({
|
|
73
|
+
args: {
|
|
74
|
+
children: 'Alice Johnson',
|
|
75
|
+
slotStart: <Icon name="user" size={12} />,
|
|
76
|
+
onRemove: fn(),
|
|
77
|
+
removeLabel: 'Remove Alice Johnson',
|
|
78
|
+
},
|
|
79
|
+
}, 'Combines a leading icon with the removable Tag interaction.');
|
|
80
|
+
|
|
81
|
+
export const WithSlotEnd: Story = withDescription({
|
|
82
|
+
args: {
|
|
83
|
+
children: 'Custom end',
|
|
84
|
+
slotEnd: <Icon name="chevron-down" size={12} />,
|
|
85
|
+
},
|
|
86
|
+
}, 'Uses `slotEnd` to render trailing custom content.');
|
|
87
|
+
|
|
88
|
+
const allColours: TagColor[] = ['neutral', 'orange', 'blue', 'green', 'purple', 'teal', 'salmon', 'yellow'];
|
|
89
|
+
|
|
90
|
+
export const AllColours: Story = withDescription({
|
|
91
|
+
render: () => (
|
|
92
|
+
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
|
|
93
|
+
{allColours.map(color => (
|
|
94
|
+
<Tag key={color} color={color}>{color}</Tag>
|
|
95
|
+
))}
|
|
96
|
+
</div>
|
|
97
|
+
),
|
|
98
|
+
}, 'Displays every available Tag colour variant side by side.');
|
|
@@ -1,65 +1,131 @@
|
|
|
1
|
-
import { describe, expect, test } from 'vitest';
|
|
1
|
+
import { describe, expect, test, vi } from 'vitest';
|
|
2
2
|
import { render, screen } from '@testing-library/react';
|
|
3
|
-
import
|
|
3
|
+
import userEvent from '@testing-library/user-event';
|
|
4
4
|
import '@testing-library/jest-dom/vitest';
|
|
5
|
+
import { Tag } from './Tag';
|
|
6
|
+
import { Dot } from 'Components/dot/Dot';
|
|
5
7
|
|
|
6
8
|
describe('Tag', () => {
|
|
7
|
-
test('
|
|
8
|
-
render(<Tag
|
|
9
|
-
expect(screen.getByText(
|
|
9
|
+
test('renders children as text content', () => {
|
|
10
|
+
render(<Tag>Hello</Tag>);
|
|
11
|
+
expect(screen.getByText('Hello')).toBeInTheDocument();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test('has default color neutral', () => {
|
|
15
|
+
const { container } = render(<Tag>Neutral</Tag>);
|
|
16
|
+
expect(container.querySelector('.ds-tag')).toHaveClass('ds-tag--neutral');
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test('applies custom color class', () => {
|
|
20
|
+
const { container } = render(<Tag color="blue">Blue</Tag>);
|
|
21
|
+
expect(container.querySelector('.ds-tag')).toHaveClass('ds-tag--blue');
|
|
10
22
|
});
|
|
11
23
|
|
|
12
|
-
test('
|
|
13
|
-
render(<Tag
|
|
14
|
-
expect(
|
|
24
|
+
test('applies selected class when selected is true', () => {
|
|
25
|
+
const { container } = render(<Tag selected>Selected</Tag>);
|
|
26
|
+
expect(container.querySelector('.ds-tag')).toHaveClass('ds-tag--selected');
|
|
15
27
|
});
|
|
16
28
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
29
|
+
describe('slotStart', () => {
|
|
30
|
+
test('renders slotStart content', () => {
|
|
31
|
+
const { container } = render(<Tag slotStart={<Dot colour="purple" />}>With dot</Tag>);
|
|
32
|
+
expect(container.querySelector('.ds-tag__slot-start .ds-dot--purple')).toBeInTheDocument();
|
|
33
|
+
expect(container.querySelector('.ds-tag__slot-start .ds-dot')).toHaveAttribute('aria-hidden', 'true');
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('does not render slot-start wrapper when slotStart is not provided', () => {
|
|
37
|
+
const { container } = render(<Tag>No slot</Tag>);
|
|
38
|
+
expect(container.querySelector('.ds-tag__slot-start')).not.toBeInTheDocument();
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
describe('slotEnd', () => {
|
|
43
|
+
test('renders slotEnd content', () => {
|
|
44
|
+
const { container } = render(<Tag slotEnd={<span>End</span>}>With end</Tag>);
|
|
45
|
+
expect(container.querySelector('.ds-tag__slot-end')).toHaveTextContent('End');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('does not render slot-end wrapper when slotEnd is not provided', () => {
|
|
49
|
+
const { container } = render(<Tag>No slot</Tag>);
|
|
50
|
+
expect(container.querySelector('.ds-tag__slot-end')).not.toBeInTheDocument();
|
|
51
|
+
});
|
|
20
52
|
});
|
|
21
53
|
|
|
22
|
-
describe('
|
|
23
|
-
test('
|
|
24
|
-
render(<Tag
|
|
25
|
-
expect(screen.
|
|
54
|
+
describe('onRemove', () => {
|
|
55
|
+
test('renders remove button when onRemove is provided', () => {
|
|
56
|
+
render(<Tag onRemove={() => {}}>Removable</Tag>);
|
|
57
|
+
expect(screen.getByRole('button', { name: 'Remove' })).toBeInTheDocument();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test('uses a custom remove label when provided', () => {
|
|
61
|
+
render(
|
|
62
|
+
<Tag onRemove={() => {}} removeLabel="Remove Alice Johnson">
|
|
63
|
+
Removable
|
|
64
|
+
</Tag>,
|
|
65
|
+
);
|
|
66
|
+
expect(screen.getByRole('button', { name: 'Remove Alice Johnson' })).toBeInTheDocument();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test('keeps the remove button in the tab order by default', () => {
|
|
70
|
+
render(<Tag onRemove={() => {}}>Removable</Tag>);
|
|
71
|
+
expect(screen.getByRole('button', { name: 'Remove' })).toHaveAttribute('tabindex', '0');
|
|
26
72
|
});
|
|
27
73
|
|
|
28
|
-
test('
|
|
29
|
-
render(
|
|
30
|
-
|
|
74
|
+
test('allows composite parents to remove the button from the tab order', () => {
|
|
75
|
+
render(
|
|
76
|
+
<Tag onRemove={() => {}} removeButtonTabIndex={-1}>
|
|
77
|
+
Removable
|
|
78
|
+
</Tag>,
|
|
79
|
+
);
|
|
80
|
+
expect(screen.getByRole('button', { name: 'Remove' })).toHaveAttribute('tabindex', '-1');
|
|
31
81
|
});
|
|
32
82
|
|
|
33
|
-
test('
|
|
34
|
-
render(<Tag
|
|
35
|
-
|
|
36
|
-
expect(dot).toHaveClass('ds-tag__dot');
|
|
37
|
-
expect(dot).toHaveClass('ds-tag__dot--purple');
|
|
83
|
+
test('does not render remove button when onRemove is not provided', () => {
|
|
84
|
+
render(<Tag>Static</Tag>);
|
|
85
|
+
expect(screen.queryByRole('button', { name: 'Remove' })).not.toBeInTheDocument();
|
|
38
86
|
});
|
|
39
87
|
|
|
40
|
-
test('
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
88
|
+
test('fires onRemove callback when close button is clicked', async () => {
|
|
89
|
+
const onRemove = vi.fn();
|
|
90
|
+
render(<Tag onRemove={onRemove}>Removable</Tag>);
|
|
91
|
+
|
|
92
|
+
await userEvent.click(screen.getByRole('button', { name: 'Remove' }));
|
|
93
|
+
expect(onRemove).toHaveBeenCalledOnce();
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test('stops event propagation on remove click', async () => {
|
|
97
|
+
const onRemove = vi.fn();
|
|
98
|
+
const outerClick = vi.fn();
|
|
99
|
+
render(
|
|
100
|
+
<div onClick={outerClick}>
|
|
101
|
+
<Tag onRemove={onRemove}>Removable</Tag>
|
|
102
|
+
</div>,
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
await userEvent.click(screen.getByRole('button', { name: 'Remove' }));
|
|
106
|
+
expect(onRemove).toHaveBeenCalledOnce();
|
|
107
|
+
expect(outerClick).not.toHaveBeenCalled();
|
|
57
108
|
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
describe('combined slots', () => {
|
|
112
|
+
test('renders slotStart, children, slotEnd, and remove button in correct order', () => {
|
|
113
|
+
const { container } = render(
|
|
114
|
+
<Tag
|
|
115
|
+
slotStart={<span>S</span>}
|
|
116
|
+
slotEnd={<span>E</span>}
|
|
117
|
+
onRemove={() => {}}
|
|
118
|
+
>
|
|
119
|
+
Label
|
|
120
|
+
</Tag>,
|
|
121
|
+
);
|
|
58
122
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
expect(
|
|
62
|
-
expect(
|
|
123
|
+
const tag = container.querySelector('.ds-tag')!;
|
|
124
|
+
const children = Array.from(tag.children);
|
|
125
|
+
expect(children[0]).toHaveClass('ds-tag__slot-start');
|
|
126
|
+
expect(children[1]).toHaveClass('ds-tag__label');
|
|
127
|
+
expect(children[2]).toHaveClass('ds-tag__slot-end');
|
|
128
|
+
expect(children[3]).toHaveClass('ds-tag__remove');
|
|
63
129
|
});
|
|
64
130
|
});
|
|
65
131
|
});
|