@kaizen/components 1.78.1 → 1.78.3
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/dist/cjs/src/Filter/FilterMultiSelect/FilterMultiSelect.cjs +11 -4
- package/dist/cjs/src/Filter/FilterMultiSelect/subcomponents/ListBox/ListBox.cjs +1 -1
- package/dist/cjs/src/Filter/FilterMultiSelect/subcomponents/ListBox/ListBox.module.css.cjs +9 -0
- package/dist/cjs/src/Filter/FilterMultiSelect/subcomponents/MenuPopup/MenuPopup.cjs +1 -1
- package/dist/cjs/src/Filter/FilterMultiSelect/subcomponents/MenuPopup/{MenuPopup.module.scss.cjs → MenuPopup.module.css.cjs} +1 -1
- package/dist/cjs/src/Filter/FilterMultiSelect/subcomponents/MenuPopup/ResponsiveMenuPopup.cjs +91 -0
- package/dist/cjs/src/LikertScaleLegacy/LikertScaleLegacy.cjs +5 -3
- package/dist/cjs/src/Menu/subcomponents/StatelessMenu/StatelessMenu.cjs +0 -1
- package/dist/cjs/src/__next__/Select/Select.cjs +23 -15
- package/dist/esm/src/Filter/FilterMultiSelect/FilterMultiSelect.mjs +12 -5
- package/dist/esm/src/Filter/FilterMultiSelect/subcomponents/ListBox/ListBox.mjs +1 -1
- package/dist/esm/src/Filter/FilterMultiSelect/subcomponents/ListBox/ListBox.module.css.mjs +7 -0
- package/dist/esm/src/Filter/FilterMultiSelect/subcomponents/MenuPopup/MenuPopup.mjs +1 -1
- package/dist/esm/src/Filter/FilterMultiSelect/subcomponents/MenuPopup/MenuPopup.module.css.mjs +4 -0
- package/dist/esm/src/Filter/FilterMultiSelect/subcomponents/MenuPopup/ResponsiveMenuPopup.mjs +85 -0
- package/dist/esm/src/LikertScaleLegacy/LikertScaleLegacy.mjs +5 -3
- package/dist/esm/src/Menu/subcomponents/StatelessMenu/StatelessMenu.mjs +0 -1
- package/dist/esm/src/__next__/Select/Select.mjs +23 -15
- package/dist/styles.css +8717 -8712
- package/dist/types/Filter/FilterMultiSelect/FilterMultiSelect.d.ts +7 -1
- package/dist/types/Filter/FilterMultiSelect/_docs/MockData.d.ts +1 -0
- package/dist/types/Filter/FilterMultiSelect/subcomponents/MenuPopup/ResponsiveMenuPopup.d.ts +22 -0
- package/dist/types/Filter/FilterMultiSelect/subcomponents/MenuPopup/index.d.ts +1 -0
- package/dist/types/LikertScaleLegacy/LikertScaleLegacy.d.ts +5 -1
- package/dist/types/Menu/subcomponents/StatelessMenu/StatelessMenu.d.ts +0 -1
- package/dist/types/__next__/Select/Select.d.ts +1 -1
- package/package.json +1 -1
- package/src/Filter/FilterBar/subcomponents/FilterBarMultiSelect/FilterBarMultiSelect.spec.tsx +1 -0
- package/src/Filter/FilterMultiSelect/FilterMultiSelect.tsx +10 -4
- package/src/Filter/FilterMultiSelect/_docs/FilterMultiSelect.mdx +9 -1
- package/src/Filter/FilterMultiSelect/_docs/FilterMultiSelect.stories.tsx +79 -2
- package/src/Filter/FilterMultiSelect/_docs/MockData.ts +39 -0
- package/src/Filter/FilterMultiSelect/context/MenuTriggerProvider/MenuTriggerProvider.spec.tsx +2 -18
- package/src/Filter/FilterMultiSelect/subcomponents/ListBox/ListBox.module.css +20 -0
- package/src/Filter/FilterMultiSelect/subcomponents/ListBox/ListBox.tsx +1 -1
- package/src/Filter/FilterMultiSelect/subcomponents/ListBoxSection/ListBoxSection.module.scss +1 -0
- package/src/Filter/FilterMultiSelect/subcomponents/MenuPopup/MenuPopup.module.css +20 -0
- package/src/Filter/FilterMultiSelect/subcomponents/MenuPopup/MenuPopup.tsx +1 -1
- package/src/Filter/FilterMultiSelect/subcomponents/MenuPopup/ResponsiveMenuPopup.tsx +115 -0
- package/src/Filter/FilterMultiSelect/subcomponents/MenuPopup/index.ts +1 -0
- package/src/LikertScaleLegacy/LikertScaleLegacy.spec.tsx +1 -0
- package/src/LikertScaleLegacy/LikertScaleLegacy.tsx +7 -1
- package/src/LikertScaleLegacy/_docs/LikertScaleLegacy.mdx +8 -0
- package/src/LikertScaleLegacy/_docs/LikertScaleLegacy.stories.tsx +30 -1
- package/src/Menu/subcomponents/StatelessMenu/StatelessMenu.tsx +0 -2
- package/src/__next__/Select/Select.tsx +5 -0
- package/src/__next__/Select/_docs/Select.mdx +8 -0
- package/src/__next__/Select/_docs/Select.stories.tsx +93 -0
- package/src/__next__/Tooltip/_docs/ApiSpecification.mdx +2 -2
- package/src/__next__/Tooltip/_docs/Tooltip.docs.stories.tsx +15 -30
- package/src/__next__/Tooltip/_docs/Tooltip.mdx +1 -1
- package/src/__next__/Tooltip/_docs/Tooltip.spec.stories.tsx +21 -58
- package/src/__next__/Tooltip/_docs/Tooltip.stories.tsx +2 -2
- package/dist/cjs/src/Filter/FilterMultiSelect/subcomponents/ListBox/ListBox.module.scss.cjs +0 -9
- package/dist/esm/src/Filter/FilterMultiSelect/subcomponents/ListBox/ListBox.module.scss.mjs +0 -7
- package/dist/esm/src/Filter/FilterMultiSelect/subcomponents/MenuPopup/MenuPopup.module.scss.mjs +0 -4
- package/src/Filter/FilterMultiSelect/subcomponents/ListBox/ListBox.module.scss +0 -23
- package/src/Filter/FilterMultiSelect/subcomponents/MenuPopup/MenuPopup.module.scss +0 -22
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import React, { useState } from 'react'
|
|
2
2
|
import { type Meta, type StoryObj } from '@storybook/react'
|
|
3
|
+
import { expect, within } from '@storybook/test'
|
|
4
|
+
import { VisuallyHidden } from '~components/VisuallyHidden'
|
|
3
5
|
import { LikertScaleLegacy } from '../index'
|
|
4
6
|
import { type Scale, type ScaleItem } from '../types'
|
|
5
7
|
|
|
@@ -57,7 +59,7 @@ export const Playground: Story = {
|
|
|
57
59
|
code: `
|
|
58
60
|
const SatisfactionExample = () => {
|
|
59
61
|
const [selectedItem, setSelectedItem] = useState<ScaleItem | null>(null)
|
|
60
|
-
|
|
62
|
+
|
|
61
63
|
return (
|
|
62
64
|
<LikertScaleLegacy
|
|
63
65
|
scale={[
|
|
@@ -82,3 +84,30 @@ export const Playground: Story = {
|
|
|
82
84
|
},
|
|
83
85
|
},
|
|
84
86
|
}
|
|
87
|
+
|
|
88
|
+
export const IsRequired: Story = {
|
|
89
|
+
render: (args) => {
|
|
90
|
+
const [selectedItem, setSelectedItem] = useState<ScaleItem | null>(null)
|
|
91
|
+
const labelId = React.useId()
|
|
92
|
+
return (
|
|
93
|
+
<div>
|
|
94
|
+
<VisuallyHidden id={labelId}>Likert scale label</VisuallyHidden>
|
|
95
|
+
<LikertScaleLegacy
|
|
96
|
+
{...args}
|
|
97
|
+
labelId={labelId}
|
|
98
|
+
selectedItem={selectedItem}
|
|
99
|
+
onSelect={setSelectedItem}
|
|
100
|
+
/>
|
|
101
|
+
</div>
|
|
102
|
+
)
|
|
103
|
+
},
|
|
104
|
+
args: {
|
|
105
|
+
isRequired: true,
|
|
106
|
+
},
|
|
107
|
+
play: async ({ canvasElement }) => {
|
|
108
|
+
const canvas = within(canvasElement.parentElement!)
|
|
109
|
+
const likertScale = canvas.getByRole('radiogroup', { name: 'Likert scale label' })
|
|
110
|
+
|
|
111
|
+
expect(likertScale).toHaveAttribute('aria-required', 'true')
|
|
112
|
+
},
|
|
113
|
+
}
|
|
@@ -46,7 +46,6 @@ export type StatelessMenuProps = {
|
|
|
46
46
|
'renderButton': (args: {
|
|
47
47
|
'onClick': (e: any) => void
|
|
48
48
|
'onMouseDown': (e: any) => void
|
|
49
|
-
'aria-haspopup': boolean
|
|
50
49
|
'aria-expanded': boolean
|
|
51
50
|
}) => React.ReactElement
|
|
52
51
|
'onClick'?: (event: SyntheticEvent) => void
|
|
@@ -76,7 +75,6 @@ export const StatelessMenu = ({
|
|
|
76
75
|
toggleMenuDropdown()
|
|
77
76
|
},
|
|
78
77
|
'onMouseDown': (e: React.MouseEvent<Element, MouseEvent>) => e.preventDefault(),
|
|
79
|
-
'aria-haspopup': true,
|
|
80
78
|
'aria-expanded': isMenuVisible,
|
|
81
79
|
})
|
|
82
80
|
|
|
@@ -85,6 +85,7 @@ export const Select = <Option extends SelectOption = SelectOption>({
|
|
|
85
85
|
status,
|
|
86
86
|
validationMessage,
|
|
87
87
|
isReversed,
|
|
88
|
+
isRequired = false,
|
|
88
89
|
isFullWidth,
|
|
89
90
|
disabledValues,
|
|
90
91
|
classNameOverride,
|
|
@@ -93,6 +94,7 @@ export const Select = <Option extends SelectOption = SelectOption>({
|
|
|
93
94
|
placeholder = '',
|
|
94
95
|
isDisabled,
|
|
95
96
|
portalContainerId,
|
|
97
|
+
onSelectionChange,
|
|
96
98
|
...restProps
|
|
97
99
|
}: SelectProps<Option>): JSX.Element => {
|
|
98
100
|
const { refs } = useFloating<HTMLButtonElement>()
|
|
@@ -114,6 +116,8 @@ export const Select = <Option extends SelectOption = SelectOption>({
|
|
|
114
116
|
description,
|
|
115
117
|
placeholder,
|
|
116
118
|
isDisabled,
|
|
119
|
+
isRequired,
|
|
120
|
+
onSelectionChange: onSelectionChange ? (key) => onSelectionChange(key!) : undefined,
|
|
117
121
|
...restProps,
|
|
118
122
|
}
|
|
119
123
|
|
|
@@ -153,6 +157,7 @@ export const Select = <Option extends SelectOption = SelectOption>({
|
|
|
153
157
|
isReversed,
|
|
154
158
|
'ref': refs.setReference,
|
|
155
159
|
'aria-describedby': classnames(validationMessage && validationId, description && descriptionId),
|
|
160
|
+
'aria-required': isRequired,
|
|
156
161
|
}
|
|
157
162
|
|
|
158
163
|
const [portalContainer, setPortalContainer] = useState<HTMLElement>()
|
|
@@ -92,6 +92,14 @@ Add validation messages using `status` and `validationMessage`.
|
|
|
92
92
|
|
|
93
93
|
<Canvas of={SelectStories.Validation} />
|
|
94
94
|
|
|
95
|
+
#### isRequired and validationBehavior
|
|
96
|
+
|
|
97
|
+
When using the `isRequired` property you can also specify the `validationBehavior` to change from `aria` to `native` form validation.
|
|
98
|
+
|
|
99
|
+
<Canvas of={SelectStories.SelectNativeValidationBehavior} />
|
|
100
|
+
|
|
101
|
+
While both use `aria-required` to announce whether the field has to have a value to assistive technologies, the `native` will option will prevent form submissions if the `selectedKey` is `undefined`.
|
|
102
|
+
|
|
95
103
|
### Full width
|
|
96
104
|
|
|
97
105
|
Set `isFullWidth` to `true` to have the Select span the full width of its container.
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { type Meta, type StoryObj } from '@storybook/react'
|
|
3
|
+
import { expect, userEvent, waitFor, within } from '@storybook/test'
|
|
4
|
+
import { FieldMessage } from '~components/FieldMessage'
|
|
3
5
|
import { ContextModal } from '~components/Modal'
|
|
4
6
|
import { RadioField, RadioGroup } from '~components/Radio'
|
|
7
|
+
import { Button } from '~components/__next__'
|
|
5
8
|
import { Select } from '../Select'
|
|
6
9
|
import { type SelectOption } from '../types'
|
|
7
10
|
import { groupedMockItems, mixedMockItemsDisabled, singleMockItems } from './mockData'
|
|
@@ -229,3 +232,93 @@ export const TouchDeviceTest: Story = {
|
|
|
229
232
|
)
|
|
230
233
|
},
|
|
231
234
|
}
|
|
235
|
+
|
|
236
|
+
export const RequiredSelect: Story = {
|
|
237
|
+
args: {
|
|
238
|
+
label: 'Required Select',
|
|
239
|
+
isRequired: true,
|
|
240
|
+
validationBehavior: 'native',
|
|
241
|
+
},
|
|
242
|
+
render: (args) => <Select {...args} />,
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export const SelectNativeValidationBehavior: Story = {
|
|
246
|
+
parameters: {
|
|
247
|
+
name: 'Required Select with native form validation',
|
|
248
|
+
},
|
|
249
|
+
args: {
|
|
250
|
+
label: 'Required Select',
|
|
251
|
+
isRequired: true,
|
|
252
|
+
validationBehavior: 'native',
|
|
253
|
+
},
|
|
254
|
+
render: (args) => {
|
|
255
|
+
const [hasSubmitted, setHasSubmitted] = React.useState(false)
|
|
256
|
+
return (
|
|
257
|
+
<div>
|
|
258
|
+
<form
|
|
259
|
+
className="flex flex-col gap-16"
|
|
260
|
+
name="form-with-required-select"
|
|
261
|
+
aria-describedby={hasSubmitted ? 'id--field-message-form' : undefined}
|
|
262
|
+
onSubmit={(e) => {
|
|
263
|
+
e.preventDefault()
|
|
264
|
+
setHasSubmitted(true)
|
|
265
|
+
}}
|
|
266
|
+
>
|
|
267
|
+
<Select {...args} isRequired />
|
|
268
|
+
<div>
|
|
269
|
+
<Button type="submit">Submit</Button>
|
|
270
|
+
</div>
|
|
271
|
+
</form>
|
|
272
|
+
{hasSubmitted && (
|
|
273
|
+
<FieldMessage
|
|
274
|
+
id="id--field-message-form"
|
|
275
|
+
classNameOverride="mt-8"
|
|
276
|
+
status="success"
|
|
277
|
+
message={'Form submitted!'}
|
|
278
|
+
/>
|
|
279
|
+
)}
|
|
280
|
+
</div>
|
|
281
|
+
)
|
|
282
|
+
},
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export const NativeFormValidationWithoutSelectedVal: Story = {
|
|
286
|
+
...SelectNativeValidationBehavior,
|
|
287
|
+
play: async ({ canvasElement, step }) => {
|
|
288
|
+
const canvas = within(canvasElement.parentElement!)
|
|
289
|
+
const submitButton = canvas.getByRole('button', { name: 'Submit' })
|
|
290
|
+
const requiredSelect = canvas.getByRole('combobox', { name: 'Required Select' })
|
|
291
|
+
const form = await canvas.findByRole('form')
|
|
292
|
+
|
|
293
|
+
await step('Select has aria-required attribute', async () => {
|
|
294
|
+
expect(requiredSelect).toHaveAttribute('aria-required', 'true')
|
|
295
|
+
})
|
|
296
|
+
|
|
297
|
+
await step('Submit will not call onSubmit without a selected value', async () => {
|
|
298
|
+
await userEvent.click(submitButton)
|
|
299
|
+
await waitFor(() => {
|
|
300
|
+
expect(form).toHaveAccessibleDescription('')
|
|
301
|
+
})
|
|
302
|
+
})
|
|
303
|
+
},
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
export const NativeFormValidationWithSelectedVal: Story = {
|
|
307
|
+
...SelectNativeValidationBehavior,
|
|
308
|
+
args: {
|
|
309
|
+
selectedKey: 'short-black',
|
|
310
|
+
},
|
|
311
|
+
play: async ({ canvasElement, step }) => {
|
|
312
|
+
const canvas = within(canvasElement.parentElement!)
|
|
313
|
+
const submitButton = canvas.getByRole('button', { name: 'Submit' })
|
|
314
|
+
const form = await canvas.findByRole('form')
|
|
315
|
+
|
|
316
|
+
await step('Submit will call onSubmit with a selected value', async () => {
|
|
317
|
+
await userEvent.click(submitButton)
|
|
318
|
+
|
|
319
|
+
await waitFor(() => {
|
|
320
|
+
expect(form).toHaveAccessibleDescription('Form submitted!')
|
|
321
|
+
})
|
|
322
|
+
})
|
|
323
|
+
},
|
|
324
|
+
}
|
|
@@ -28,7 +28,7 @@ Tooltips are brief floating labels used to add additional contextual information
|
|
|
28
28
|
source={{
|
|
29
29
|
code: `
|
|
30
30
|
<TooltipTrigger>
|
|
31
|
-
<Button
|
|
31
|
+
<Button>Button</Button>
|
|
32
32
|
<Tooltip>Tooltip content</Tooltip>
|
|
33
33
|
</TooltipTrigger>
|
|
34
34
|
`,
|
|
@@ -75,7 +75,7 @@ The `TooltipTrigger` wraps both the `Tooltip` and its trigger element, controlli
|
|
|
75
75
|
```jsx
|
|
76
76
|
<TooltipTrigger>
|
|
77
77
|
/* In this case the trigger element is the Button */
|
|
78
|
-
<Button
|
|
78
|
+
<Button>Button</Button>
|
|
79
79
|
/* The Tooltip and its content is a child of the trigger */
|
|
80
80
|
<Tooltip>Tooltip content</Tooltip>
|
|
81
81
|
</TooltipTrigger>
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { type Meta, type StoryObj } from '@storybook/react'
|
|
3
3
|
import isChromatic from 'chromatic'
|
|
4
|
-
import { Button, IconButton } from '~components/Button'
|
|
5
4
|
import { FieldMessage } from '~components/FieldMessage'
|
|
6
5
|
import { Focusable } from '~components/Focusable'
|
|
7
6
|
import { Input } from '~components/Input'
|
|
8
7
|
import { Label } from '~components/Label'
|
|
9
8
|
import { Text } from '~components/Text'
|
|
9
|
+
import { Button } from '~components/__next__/Button'
|
|
10
10
|
import { Icon } from '~components/__next__/Icon'
|
|
11
11
|
import { Tooltip, TooltipTrigger } from '../index'
|
|
12
12
|
import * as TestStories from './Tooltip.spec.stories'
|
|
@@ -37,7 +37,7 @@ type Story = StoryObj<typeof meta>
|
|
|
37
37
|
export const Playground: Story = {
|
|
38
38
|
render: ({ defaultOpen: _, isOpen, ...args }) => (
|
|
39
39
|
<TooltipTrigger defaultOpen={true} isOpen={isOpen}>
|
|
40
|
-
<Button
|
|
40
|
+
<Button>Button</Button>
|
|
41
41
|
<Tooltip {...args}>Tooltip content</Tooltip>
|
|
42
42
|
</TooltipTrigger>
|
|
43
43
|
),
|
|
@@ -46,14 +46,9 @@ export const Playground: Story = {
|
|
|
46
46
|
export const Primary: Story = {
|
|
47
47
|
render: () => (
|
|
48
48
|
<TooltipTrigger>
|
|
49
|
-
<
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
primary
|
|
53
|
-
// Negate the aria description (added by RAC) as it should be the
|
|
54
|
-
// same as the accessible name, therefore no need to duplicate it
|
|
55
|
-
aria-describedby={null}
|
|
56
|
-
/>
|
|
49
|
+
<Button icon={<Icon name="add" isPresentational />} hasHiddenLabel>
|
|
50
|
+
Add something
|
|
51
|
+
</Button>
|
|
57
52
|
<Tooltip>Add something</Tooltip>
|
|
58
53
|
</TooltipTrigger>
|
|
59
54
|
),
|
|
@@ -105,14 +100,9 @@ export const DoConcise: Story = {
|
|
|
105
100
|
render: () => (
|
|
106
101
|
<div>
|
|
107
102
|
<TooltipTrigger>
|
|
108
|
-
<
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
primary
|
|
112
|
-
// Negate the aria description (added by RAC) as it should be the
|
|
113
|
-
// same as the accessible name, therefore no need to duplicate it
|
|
114
|
-
aria-describedby={null}
|
|
115
|
-
/>
|
|
103
|
+
<Button icon={<Icon name="add" isPresentational />} hasHiddenLabel>
|
|
104
|
+
Add topic
|
|
105
|
+
</Button>
|
|
116
106
|
<Tooltip>Add topic to agenda</Tooltip>
|
|
117
107
|
</TooltipTrigger>
|
|
118
108
|
</div>
|
|
@@ -128,17 +118,12 @@ export const DontConcise: Story = {
|
|
|
128
118
|
render: () => (
|
|
129
119
|
<div>
|
|
130
120
|
<TooltipTrigger>
|
|
131
|
-
<
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
primary
|
|
135
|
-
// Negate the aria description (added by RAC) as it should be the
|
|
136
|
-
// same as the accessible name, therefore no need to duplicate it
|
|
137
|
-
aria-describedby={null}
|
|
138
|
-
/>
|
|
121
|
+
<Button icon={<Icon name="add" isPresentational />} hasHiddenLabel>
|
|
122
|
+
Add something
|
|
123
|
+
</Button>
|
|
139
124
|
<Tooltip>
|
|
140
125
|
Add Topic to agenda. This will create a new topic where you can discuss recent work with
|
|
141
|
-
your manager.
|
|
126
|
+
your manager.
|
|
142
127
|
</Tooltip>
|
|
143
128
|
</TooltipTrigger>
|
|
144
129
|
</div>
|
|
@@ -150,11 +135,11 @@ export const ShouldFlip: Story = {
|
|
|
150
135
|
render: () => (
|
|
151
136
|
<div className="flex flex-col gap-8 pl-96 overflow-hidden max-w-[250px]">
|
|
152
137
|
<TooltipTrigger>
|
|
153
|
-
<Button
|
|
138
|
+
<Button>Should flip</Button>
|
|
154
139
|
<Tooltip placement="end">Tooltip content</Tooltip>
|
|
155
140
|
</TooltipTrigger>
|
|
156
141
|
<TooltipTrigger>
|
|
157
|
-
<Button
|
|
142
|
+
<Button>Won't flip</Button>
|
|
158
143
|
<Tooltip placement="end" shouldFlip={false}>
|
|
159
144
|
Tooltip content
|
|
160
145
|
</Tooltip>
|
|
@@ -188,7 +173,7 @@ export const UncontrolledState: Story = {
|
|
|
188
173
|
Toggle open
|
|
189
174
|
</button>
|
|
190
175
|
<TooltipTrigger isOpen={isOpen}>
|
|
191
|
-
<Button
|
|
176
|
+
<Button>Button</Button>
|
|
192
177
|
<Tooltip>Tooltip content</Tooltip>
|
|
193
178
|
</TooltipTrigger>
|
|
194
179
|
</div>
|
|
@@ -2,11 +2,12 @@ import React from 'react'
|
|
|
2
2
|
import { type Meta, type StoryObj } from '@storybook/react'
|
|
3
3
|
import { expect, userEvent, waitFor, within } from '@storybook/test'
|
|
4
4
|
import isChromatic from 'chromatic'
|
|
5
|
-
import { Button, IconButton } from '~components/Button'
|
|
6
5
|
import { Focusable } from '~components/Focusable'
|
|
7
|
-
import {
|
|
6
|
+
import { LinkButton } from '~components/LinkButton'
|
|
8
7
|
import { Text } from '~components/Text'
|
|
8
|
+
import { Button } from '~components/__next__/Button'
|
|
9
9
|
import { Icon } from '~components/__next__/Icon'
|
|
10
|
+
import { Tab, TabList, TabPanel, Tabs } from '~components/__next__/Tabs'
|
|
10
11
|
import { Tag } from '~components/__next__/Tag'
|
|
11
12
|
import { Tooltip, TooltipTrigger } from '../index'
|
|
12
13
|
|
|
@@ -32,12 +33,10 @@ export default meta
|
|
|
32
33
|
|
|
33
34
|
type Story = StoryObj<typeof meta>
|
|
34
35
|
|
|
35
|
-
// TODO: update this to use the new `next` button component
|
|
36
|
-
|
|
37
36
|
export const OnButton: Story = {
|
|
38
37
|
render: ({ defaultOpen, isOpen, ...args }) => (
|
|
39
38
|
<TooltipTrigger defaultOpen={defaultOpen} isOpen={isOpen}>
|
|
40
|
-
<Button
|
|
39
|
+
<Button>Button</Button>
|
|
41
40
|
<Tooltip {...args}>Tooltip content</Tooltip>
|
|
42
41
|
</TooltipTrigger>
|
|
43
42
|
),
|
|
@@ -46,10 +45,12 @@ export const OnButton: Story = {
|
|
|
46
45
|
const button = canvas.queryByRole('button') ?? canvas.getByRole('link')
|
|
47
46
|
|
|
48
47
|
await step('Hover shows', async () => {
|
|
49
|
-
await userEvent.unhover(button)
|
|
48
|
+
await waitFor(() => userEvent.unhover(button))
|
|
50
49
|
await userEvent.hover(button)
|
|
51
|
-
|
|
52
|
-
expect(
|
|
50
|
+
const tooltip = canvas.findByRole('tooltip')
|
|
51
|
+
await expect(await tooltip).toBeInTheDocument()
|
|
52
|
+
await expect((await tooltip).checkVisibility()).toBe(true)
|
|
53
|
+
await expect(button).toHaveAttribute('aria-describedby', canvas.getByRole('tooltip').id)
|
|
53
54
|
await userEvent.unhover(button)
|
|
54
55
|
})
|
|
55
56
|
|
|
@@ -76,7 +77,7 @@ export const OnLink: Story = {
|
|
|
76
77
|
...OnButton,
|
|
77
78
|
render: ({ defaultOpen, isOpen, ...args }) => (
|
|
78
79
|
<TooltipTrigger defaultOpen={defaultOpen} isOpen={isOpen}>
|
|
79
|
-
<
|
|
80
|
+
<LinkButton href="#">Button</LinkButton>
|
|
80
81
|
<Tooltip {...args}>Tooltip content</Tooltip>
|
|
81
82
|
</TooltipTrigger>
|
|
82
83
|
),
|
|
@@ -86,12 +87,9 @@ export const OnButtonWithDesc: Story = {
|
|
|
86
87
|
render: ({ defaultOpen, isOpen, ...args }) => (
|
|
87
88
|
<>
|
|
88
89
|
<TooltipTrigger defaultOpen={defaultOpen} isOpen={isOpen}>
|
|
89
|
-
<
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
primary
|
|
93
|
-
aria-describedby="blah"
|
|
94
|
-
/>
|
|
90
|
+
<Button icon={<Icon name="add" isPresentational />} aria-describedby="blah" hasHiddenLabel>
|
|
91
|
+
(TESTING) Add label
|
|
92
|
+
</Button>
|
|
95
93
|
<Tooltip {...args}>Tooltip content</Tooltip>
|
|
96
94
|
</TooltipTrigger>
|
|
97
95
|
<Text variant="body" id="blah" classNameOverride="p-4">
|
|
@@ -104,14 +102,9 @@ export const OnButtonWithDesc: Story = {
|
|
|
104
102
|
export const OnIconButton: Story = {
|
|
105
103
|
render: ({ defaultOpen, isOpen, ...args }) => (
|
|
106
104
|
<TooltipTrigger defaultOpen={defaultOpen} isOpen={isOpen}>
|
|
107
|
-
<
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
primary
|
|
111
|
-
// Negate the aria description (added by RAC) as it should be the
|
|
112
|
-
// same as the accessible name, therefore no need to duplicate it
|
|
113
|
-
aria-describedby={null}
|
|
114
|
-
/>
|
|
105
|
+
<Button icon={<Icon name="add" isPresentational />} hasHiddenLabel>
|
|
106
|
+
Add something
|
|
107
|
+
</Button>
|
|
115
108
|
<Tooltip {...args}>Add something</Tooltip>
|
|
116
109
|
</TooltipTrigger>
|
|
117
110
|
),
|
|
@@ -120,36 +113,7 @@ export const OnIconButton: Story = {
|
|
|
120
113
|
export const OnDisabledButton: Story = {
|
|
121
114
|
render: ({ defaultOpen, isOpen, ...args }) => (
|
|
122
115
|
<TooltipTrigger defaultOpen={defaultOpen} isOpen={isOpen}>
|
|
123
|
-
<Button
|
|
124
|
-
<Tooltip {...args}>Tooltip content</Tooltip>
|
|
125
|
-
</TooltipTrigger>
|
|
126
|
-
),
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export const OnCustomButtonAnchor: Story = {
|
|
130
|
-
name: 'On Button with custom <a>',
|
|
131
|
-
render: ({ defaultOpen, isOpen, ...args }) => (
|
|
132
|
-
<TooltipTrigger defaultOpen={defaultOpen} isOpen={isOpen}>
|
|
133
|
-
<Button
|
|
134
|
-
label="Button"
|
|
135
|
-
component={(props) => (
|
|
136
|
-
// eslint-disable-next-line jsx-a11y/anchor-is-valid
|
|
137
|
-
<a {...props} href="#" style={{ padding: '0 1rem' }}>
|
|
138
|
-
Custom Link
|
|
139
|
-
</a>
|
|
140
|
-
)}
|
|
141
|
-
/>
|
|
142
|
-
<Tooltip {...args}>Tooltip content</Tooltip>
|
|
143
|
-
</TooltipTrigger>
|
|
144
|
-
),
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
export const OnCustomButton: Story = {
|
|
148
|
-
...OnButton,
|
|
149
|
-
name: 'On Button with custom <button>',
|
|
150
|
-
render: ({ defaultOpen, isOpen, ...args }) => (
|
|
151
|
-
<TooltipTrigger defaultOpen={defaultOpen} isOpen={isOpen}>
|
|
152
|
-
<Button label="Button" component={(props) => <button type="button" {...props} />} />
|
|
116
|
+
<Button isDisabled>Button</Button>
|
|
153
117
|
<Tooltip {...args}>Tooltip content</Tooltip>
|
|
154
118
|
</TooltipTrigger>
|
|
155
119
|
),
|
|
@@ -175,9 +139,8 @@ export const OnTabs: Story = {
|
|
|
175
139
|
<Tooltip {...args}>Tooltip content</Tooltip>
|
|
176
140
|
</TooltipTrigger>
|
|
177
141
|
</TabList>
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
</TabPanels>
|
|
142
|
+
|
|
143
|
+
<TabPanel className="p-24 font-family-paragraph">Tab content</TabPanel>
|
|
181
144
|
</Tabs>
|
|
182
145
|
),
|
|
183
146
|
}
|
|
@@ -185,7 +148,7 @@ export const OnTabs: Story = {
|
|
|
185
148
|
export const Placement: Story = {
|
|
186
149
|
render: ({ defaultOpen, isOpen, ...args }) => (
|
|
187
150
|
<TooltipTrigger defaultOpen={defaultOpen} isOpen={isOpen}>
|
|
188
|
-
<Button
|
|
151
|
+
<Button>Button</Button>
|
|
189
152
|
<Tooltip {...args} placement="top" shouldFlip={false}>
|
|
190
153
|
Placement top
|
|
191
154
|
</Tooltip>
|
|
@@ -205,7 +168,7 @@ export const Placement: Story = {
|
|
|
205
168
|
export const ReversedColors: Story = {
|
|
206
169
|
render: ({ defaultOpen, isOpen, ...args }) => (
|
|
207
170
|
<TooltipTrigger defaultOpen={defaultOpen} isOpen={isOpen}>
|
|
208
|
-
<Button
|
|
171
|
+
<Button>Button</Button>
|
|
209
172
|
<Tooltip {...args}>Tooltip content</Tooltip>
|
|
210
173
|
</TooltipTrigger>
|
|
211
174
|
),
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React, { type FunctionComponent } from 'react'
|
|
2
2
|
import { type Meta, type StoryObj } from '@storybook/react'
|
|
3
3
|
import isChromatic from 'chromatic'
|
|
4
|
-
import { Button } from '~components/Button'
|
|
5
4
|
import { Focusable } from '~components/Focusable'
|
|
6
5
|
import { Tag } from '~components/__next__'
|
|
6
|
+
import { Button } from '~components/__next__/Button'
|
|
7
7
|
import { Tooltip, TooltipTrigger } from '../index'
|
|
8
8
|
import * as testStories from './Tooltip.spec.stories'
|
|
9
9
|
|
|
@@ -33,7 +33,7 @@ type Story = StoryObj<typeof meta>
|
|
|
33
33
|
export const Playground: Story = {
|
|
34
34
|
render: ({ defaultOpen: _, isOpen, ...args }) => (
|
|
35
35
|
<TooltipTrigger defaultOpen={true} isOpen={isOpen}>
|
|
36
|
-
<Button
|
|
36
|
+
<Button>Button</Button>
|
|
37
37
|
<Tooltip {...args}>Tooltip content</Tooltip>
|
|
38
38
|
</TooltipTrigger>
|
|
39
39
|
),
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var styles = {
|
|
4
|
-
"listBox": "ListBox-module_listBox__q95MO",
|
|
5
|
-
"overflown": "ListBox-module_overflown__wChQA",
|
|
6
|
-
"hidden": "ListBox-module_hidden__eYdXv",
|
|
7
|
-
"noResultsWrapper": "ListBox-module_noResultsWrapper__WcLRm"
|
|
8
|
-
};
|
|
9
|
-
module.exports = styles;
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
@import '~@kaizen/design-tokens/sass/spacing';
|
|
2
|
-
|
|
3
|
-
.listBox {
|
|
4
|
-
list-style: none;
|
|
5
|
-
padding: $spacing-sm;
|
|
6
|
-
margin: 0 $spacing-sm 0 0;
|
|
7
|
-
display: grid;
|
|
8
|
-
max-height: 22rem;
|
|
9
|
-
overflow-y: auto;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
.overflown {
|
|
13
|
-
padding-right: $spacing-sm;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
.hidden {
|
|
17
|
-
display: none;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// this is a div but remove styles briefly flickering to a bullet list as the sections are removed
|
|
21
|
-
.noResultsWrapper {
|
|
22
|
-
list-style: none;
|
|
23
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
@import '~@kaizen/design-tokens/sass/spacing';
|
|
2
|
-
@import '~@kaizen/design-tokens/sass/shadow';
|
|
3
|
-
@import '~@kaizen/design-tokens/sass/border';
|
|
4
|
-
@import '~@kaizen/design-tokens/sass/color';
|
|
5
|
-
|
|
6
|
-
// figma hard coded: https://www.figma.com/file/eZKEE5kXbEMY3lx84oz8iN/%E2%9D%A4%EF%B8%8F-UI-Kit%3A-Heart?node-id=22814%3A96966
|
|
7
|
-
$menu-container-width: 294px;
|
|
8
|
-
$menu-container-max-height: 312px;
|
|
9
|
-
|
|
10
|
-
.menuPopup {
|
|
11
|
-
position: absolute;
|
|
12
|
-
z-index: 1000; // from $ca-z-index-dropdown
|
|
13
|
-
box-sizing: border-box;
|
|
14
|
-
background: $color-white;
|
|
15
|
-
color: $color-purple-800;
|
|
16
|
-
border-radius: $border-solid-border-radius;
|
|
17
|
-
box-shadow: $shadow-large-box-shadow;
|
|
18
|
-
padding: $spacing-sm 0;
|
|
19
|
-
margin-top: $spacing-xs;
|
|
20
|
-
text-align: start;
|
|
21
|
-
width: $menu-container-width;
|
|
22
|
-
}
|