@arbor-education/design-system.components 0.6.0 → 0.7.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 +25 -0
- 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/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/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 +656 -25
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +34 -25
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -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/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/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 +5 -0
- package/src/index.ts +47 -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
|
@@ -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
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import classNames from 'classnames';
|
|
2
|
+
import { Icon } from 'Components/icon/Icon';
|
|
2
3
|
|
|
3
4
|
export type TagColor = 'neutral'
|
|
4
5
|
| 'orange'
|
|
@@ -9,26 +10,49 @@ export type TagColor = 'neutral'
|
|
|
9
10
|
| 'salmon'
|
|
10
11
|
| 'yellow';
|
|
11
12
|
|
|
12
|
-
export type
|
|
13
|
-
|
|
14
|
-
type TagProps = {
|
|
15
|
-
text: string;
|
|
13
|
+
export type TagProps = {
|
|
14
|
+
children: React.ReactNode;
|
|
16
15
|
color?: TagColor;
|
|
17
|
-
|
|
16
|
+
selected?: boolean;
|
|
17
|
+
slotStart?: React.ReactNode;
|
|
18
|
+
slotEnd?: React.ReactNode;
|
|
19
|
+
onRemove?: () => void;
|
|
20
|
+
removeLabel?: string;
|
|
21
|
+
removeButtonTabIndex?: 0 | -1;
|
|
18
22
|
};
|
|
19
23
|
|
|
20
|
-
export const Tag = ({
|
|
24
|
+
export const Tag = ({
|
|
25
|
+
children,
|
|
26
|
+
color = 'neutral',
|
|
27
|
+
selected = false,
|
|
28
|
+
slotStart,
|
|
29
|
+
slotEnd,
|
|
30
|
+
onRemove,
|
|
31
|
+
removeLabel = 'Remove',
|
|
32
|
+
removeButtonTabIndex = 0,
|
|
33
|
+
}: TagProps): React.JSX.Element => {
|
|
21
34
|
return (
|
|
22
|
-
<span
|
|
23
|
-
|
|
35
|
+
<span className={classNames('ds-tag', `ds-tag--${color}`, {
|
|
36
|
+
'ds-tag--selected': selected,
|
|
37
|
+
})}
|
|
24
38
|
>
|
|
25
|
-
{
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
39
|
+
{slotStart && <span className="ds-tag__slot-start">{slotStart}</span>}
|
|
40
|
+
<span className="ds-tag__label">{children}</span>
|
|
41
|
+
{slotEnd && <span className="ds-tag__slot-end">{slotEnd}</span>}
|
|
42
|
+
{onRemove && (
|
|
43
|
+
<button
|
|
44
|
+
type="button"
|
|
45
|
+
className="ds-tag__remove"
|
|
46
|
+
aria-label={removeLabel}
|
|
47
|
+
onClick={(e) => {
|
|
48
|
+
e.stopPropagation();
|
|
49
|
+
onRemove();
|
|
50
|
+
}}
|
|
51
|
+
tabIndex={removeButtonTabIndex}
|
|
52
|
+
>
|
|
53
|
+
<Icon name="x" size={12} />
|
|
54
|
+
</button>
|
|
30
55
|
)}
|
|
31
|
-
{text}
|
|
32
56
|
</span>
|
|
33
57
|
);
|
|
34
58
|
};
|
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
.ds-tag {
|
|
2
|
-
display: flex;
|
|
3
|
-
padding:
|
|
2
|
+
display: inline-flex;
|
|
3
|
+
padding: 0 var(--tag-spacing-horizontal);
|
|
4
4
|
align-items: center;
|
|
5
5
|
gap: var(--tag-spacing-gap-horizontal);
|
|
6
6
|
border-radius: var(--tag-radius);
|
|
7
|
+
border: var(--border-weight) solid transparent;
|
|
8
|
+
box-sizing: border-box;
|
|
7
9
|
flex-grow: 0;
|
|
8
10
|
width: fit-content;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
white-space: nowrap;
|
|
12
|
+
max-width: 100%;
|
|
13
|
+
height: var(--tag-height);
|
|
11
14
|
font-style: normal;
|
|
12
|
-
line-height: 150%;
|
|
15
|
+
line-height: 150%;
|
|
13
16
|
|
|
14
17
|
&--neutral {
|
|
15
18
|
color: var(--tag-neutral-color-text);
|
|
16
19
|
background: var(--tag-neutral-color-background);
|
|
17
20
|
}
|
|
18
|
-
|
|
21
|
+
|
|
19
22
|
&--orange {
|
|
20
23
|
color: var(--tag-category-orange-color-text);
|
|
21
24
|
background: var(--tag-category-orange-color-background);
|
|
@@ -50,38 +53,50 @@
|
|
|
50
53
|
color: var(--tag-category-yellow-color-text);
|
|
51
54
|
background: var(--tag-category-yellow-color-background);
|
|
52
55
|
}
|
|
53
|
-
}
|
|
54
56
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
&--purple {
|
|
61
|
-
background-color: var(--color-extended-colours-purple-500);
|
|
57
|
+
&--selected {
|
|
58
|
+
background: var(--tag-selected-color-background);
|
|
59
|
+
color: var(--tag-neutral-color-text);
|
|
60
|
+
border-color: var(--tag-selected-color-border);
|
|
62
61
|
}
|
|
63
62
|
|
|
64
|
-
|
|
65
|
-
background-color: var(--color-extended-colours-salmon-500);
|
|
66
|
-
}
|
|
63
|
+
}
|
|
67
64
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
65
|
+
.ds-tag__slot-start {
|
|
66
|
+
display: flex;
|
|
67
|
+
align-items: center;
|
|
68
|
+
flex-shrink: 0;
|
|
69
|
+
}
|
|
71
70
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
.ds-tag__label {
|
|
72
|
+
overflow: hidden;
|
|
73
|
+
text-overflow: ellipsis;
|
|
74
|
+
}
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
.ds-tag__slot-end {
|
|
77
|
+
display: flex;
|
|
78
|
+
align-items: center;
|
|
79
|
+
flex-shrink: 0;
|
|
80
|
+
}
|
|
79
81
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
+
.ds-tag__remove {
|
|
83
|
+
display: flex;
|
|
84
|
+
align-items: center;
|
|
85
|
+
justify-content: center;
|
|
86
|
+
border: none;
|
|
87
|
+
background: transparent;
|
|
88
|
+
padding: 0;
|
|
89
|
+
cursor: pointer;
|
|
90
|
+
color: inherit;
|
|
91
|
+
border-radius: 50%;
|
|
92
|
+
flex-shrink: 0;
|
|
93
|
+
|
|
94
|
+
&:hover {
|
|
95
|
+
background-color: var(--color-grey-200);
|
|
82
96
|
}
|
|
83
97
|
|
|
84
|
-
|
|
85
|
-
|
|
98
|
+
&:disabled {
|
|
99
|
+
cursor: not-allowed;
|
|
100
|
+
opacity: 0.5;
|
|
86
101
|
}
|
|
87
102
|
}
|