@kaizen/components 1.67.22 → 1.68.1

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.
Files changed (54) hide show
  1. package/codemods/README.md +16 -1
  2. package/codemods/upgradeIconV1/getNewIconPropsFromOldIconName.ts +9 -9
  3. package/dist/cjs/__actions__/Button/v3/Button.cjs +43 -8
  4. package/dist/cjs/__actions__/Button/v3/Button.module.css.cjs +21 -0
  5. package/dist/cjs/__actions__/Button/v3/subcomponents/ButtonContent/ButtonContent.cjs +37 -0
  6. package/dist/cjs/__actions__/Button/v3/subcomponents/ButtonContent/ButtonContent.module.css.cjs +9 -0
  7. package/dist/cjs/__actions__/Button/v3/subcomponents/PendingContent/PendingContent.cjs +35 -0
  8. package/dist/cjs/__actions__/Button/v3/subcomponents/PendingContent/PendingContent.module.css.cjs +8 -0
  9. package/dist/cjs/__overlays__/Tooltip/v3/Tooltip.cjs +2 -2
  10. package/dist/esm/__actions__/Button/v3/Button.mjs +44 -9
  11. package/dist/esm/__actions__/Button/v3/Button.module.css.mjs +19 -0
  12. package/dist/esm/__actions__/Button/v3/subcomponents/ButtonContent/ButtonContent.mjs +28 -0
  13. package/dist/esm/__actions__/Button/v3/subcomponents/ButtonContent/ButtonContent.module.css.mjs +7 -0
  14. package/dist/esm/__actions__/Button/v3/subcomponents/PendingContent/PendingContent.mjs +26 -0
  15. package/dist/esm/__actions__/Button/v3/subcomponents/PendingContent/PendingContent.module.css.mjs +6 -0
  16. package/dist/esm/__overlays__/Tooltip/v3/Tooltip.mjs +1 -1
  17. package/dist/styles.css +276 -91
  18. package/dist/types/__actions__/Button/v3/Button.d.ts +17 -4
  19. package/dist/types/__actions__/Button/v3/index.d.ts +1 -0
  20. package/dist/types/__actions__/Button/v3/subcomponents/ButtonContent/ButtonContent.d.ts +11 -0
  21. package/dist/types/__actions__/Button/v3/subcomponents/ButtonContent/index.d.ts +1 -0
  22. package/dist/types/__actions__/Button/v3/subcomponents/PendingContent/PendingContent.d.ts +5 -0
  23. package/dist/types/__actions__/Button/v3/subcomponents/PendingContent/index.d.ts +1 -0
  24. package/dist/types/__actions__/Button/v3/subcomponents/index.d.ts +2 -0
  25. package/dist/types/__actions__/Button/v3/types.d.ts +21 -0
  26. package/package.json +1 -1
  27. package/src/__actions__/Button/v3/Button.module.css +235 -0
  28. package/src/__actions__/Button/v3/Button.tsx +92 -29
  29. package/src/__actions__/Button/v3/_docs/Button--api-specification.mdx +150 -0
  30. package/src/__actions__/Button/v3/_docs/Button--usage-guidelines.mdx +30 -0
  31. package/src/__actions__/Button/v3/_docs/Button.docs.stories.tsx +112 -50
  32. package/src/__actions__/Button/v3/_docs/Button.spec.stories.tsx +80 -120
  33. package/src/__actions__/Button/v3/_docs/Button.stickersheet.stories.tsx +183 -81
  34. package/src/__actions__/Button/v3/index.ts +1 -0
  35. package/src/__actions__/Button/v3/subcomponents/ButtonContent/ButtonContent.module.css +19 -0
  36. package/src/__actions__/Button/v3/subcomponents/ButtonContent/ButtonContent.tsx +40 -0
  37. package/src/__actions__/Button/v3/subcomponents/ButtonContent/index.ts +1 -0
  38. package/src/__actions__/Button/v3/subcomponents/PendingContent/PendingContent.module.css +16 -0
  39. package/src/__actions__/Button/v3/subcomponents/PendingContent/PendingContent.tsx +28 -0
  40. package/src/__actions__/Button/v3/subcomponents/PendingContent/index.ts +1 -0
  41. package/src/__actions__/Button/v3/subcomponents/index.ts +2 -0
  42. package/src/__actions__/Button/v3/types.ts +25 -0
  43. package/src/__actions__/Menu/v3/_docs/Menu.docs.stories.tsx +54 -18
  44. package/src/__actions__/Menu/v3/_docs/Menu.spec.stories.tsx +30 -10
  45. package/src/__actions__/Menu/v3/_docs/Menu.stories.tsx +12 -4
  46. package/src/__future__/Icon/_docs/Icon.docs.stories.tsx +7 -7
  47. package/src/__overlays__/Tooltip/v3/Tooltip.tsx +1 -1
  48. package/src/__overlays__/Tooltip/v3/_docs/Tooltip.spec.stories.tsx +2 -0
  49. package/dist/cjs/__actions__/Button/v3/Button.module.scss.cjs +0 -9
  50. package/dist/esm/__actions__/Button/v3/Button.module.scss.mjs +0 -7
  51. package/src/__actions__/Button/v3/Button.module.scss +0 -104
  52. package/src/__actions__/Button/v3/_docs/ApiSpecification.mdx +0 -173
  53. package/src/__actions__/Button/v3/_docs/Button.mdx +0 -41
  54. package/src/__actions__/Button/v3/_docs/Button.stories.tsx +0 -98
@@ -1,76 +1,138 @@
1
1
  import React from "react"
2
2
  import { action } from "@storybook/addon-actions"
3
3
  import { Meta, StoryObj } from "@storybook/react"
4
- import { ChevronDownIcon, ChevronUpIcon } from "~components/Icon"
4
+ import { Badge } from "~components/Badge"
5
+ import { Icon } from "~components/__future__"
6
+ import { ReversedColors } from "~components/__utilities__/v3"
5
7
  import { Button } from "../index"
6
8
 
7
9
  const meta = {
8
- title: "Actions/Button/Button (v3)/Doc Assets",
10
+ title: "Actions/Button/Button (v3)",
9
11
  component: Button,
10
12
  args: {
11
13
  children: "Label",
12
14
  onPress: action("Button onPress event"),
13
15
  },
16
+ argTypes: {
17
+ icon: {
18
+ options: ["delete", "arrow", "plus"],
19
+ mapping: {
20
+ delete: <Icon isPresentational name="delete" />,
21
+ arrow: <Icon isPresentational name="arrow_forward" />,
22
+ add: <Icon isPresentational name="add" />,
23
+ },
24
+ },
25
+ },
14
26
  } satisfies Meta<typeof Button>
15
27
 
16
28
  export default meta
17
29
 
18
30
  type Story = StoryObj<typeof meta>
19
31
 
20
- export const ButtonClassModifierWithRenderProps: Story = {
21
- render: ({ children, ...otherArgs }) => (
22
- <Button
23
- {...otherArgs}
24
- className={({ isPressed }) => (isPressed ? "!bg-gray-300" : "")}
25
- >
26
- {children}
27
- </Button>
32
+ export const Playground: Story = {}
33
+
34
+ export const ButtonVariants: Story = {
35
+ render: args => (
36
+ <>
37
+ <Button {...args} variant="primary" />
38
+ <Button {...args} variant="secondary" />
39
+ <Button {...args} variant="tertiary" />
40
+ </>
41
+ ),
42
+ decorators: [
43
+ Story => (
44
+ <div className="flex gap-8">
45
+ <Story />
46
+ </div>
47
+ ),
48
+ ],
49
+ }
50
+
51
+ export const ButtonVariantsReversed: Story = {
52
+ render: args => (
53
+ <ReversedColors isReversed={true}>
54
+ <Button {...args} variant="primary" />
55
+ <Button {...args} variant="secondary" />
56
+ <Button {...args} variant="tertiary" />
57
+ </ReversedColors>
28
58
  ),
29
59
  parameters: {
30
- docs: {
31
- source: {
32
- code: `
33
- <Button
34
- {...otherArgs}
35
- className={({ isPressed }) => (isPressed ? "!bg-gray-300" : "")}
36
- >
37
- {children}
38
- </Button>
39
- `,
40
- },
41
- },
60
+ reverseColors: true,
61
+ backgrounds: { default: "Purple 700" },
62
+ },
63
+ decorators: [
64
+ Story => (
65
+ <div className="flex gap-8">
66
+ <Story />
67
+ </div>
68
+ ),
69
+ ],
70
+ }
71
+
72
+ export const ButtonSizes: Story = {
73
+ render: args => (
74
+ <>
75
+ <Button {...args} size="small" />
76
+ <Button {...args} size="medium" />
77
+ <Button {...args} size="large" />
78
+ </>
79
+ ),
80
+ decorators: [
81
+ Story => (
82
+ <div className="flex gap-8 items-center">
83
+ <Story />
84
+ </div>
85
+ ),
86
+ ],
87
+ }
88
+
89
+ export const ButtonWithIconStart: Story = {
90
+ args: {
91
+ icon: <Icon isPresentational name="delete" />,
92
+ },
93
+ }
94
+
95
+ export const ButtonWithIconEnd: Story = {
96
+ args: {
97
+ icon: <Icon isPresentational name="arrow_forward" shouldMirrorInRTL />,
98
+ iconPosition: "end",
42
99
  },
43
100
  }
44
101
 
45
- export const ButtonContentWithRenderProps: Story = {
46
- render: ({ children, ...otherArgs }) => (
47
- <Button {...otherArgs}>
48
- {({ isPressed }) => (
49
- <>
50
- {children}
51
- {isPressed ? (
52
- <ChevronDownIcon role="presentation" />
53
- ) : (
54
- <ChevronUpIcon role="presentation" />
55
- )}
56
- </>
57
- )}
58
- </Button>
102
+ export const IconButton: Story = {
103
+ args: {
104
+ children: "Remove highlights from: May 8, 2024",
105
+ icon: <Icon isPresentational name="delete" />,
106
+ hasHiddenLabel: true,
107
+ },
108
+ }
109
+
110
+ export const ReversedButton: Story = {
111
+ render: args => (
112
+ <ReversedColors isReversed={true}>
113
+ <Button {...args} />
114
+ </ReversedColors>
59
115
  ),
60
116
  parameters: {
61
- docs: {
62
- source: {
63
- code: `
64
- <Button {...otherArgs}>
65
- {({isPressed}) => (
66
- <>
67
- {children}
68
- {isPressed ? <ChevronDownIcon role="presentation" /> : <ChevronUpIcon role="presentation" />}
69
- </>
70
- )}
71
- </Button>
72
- `,
73
- },
74
- },
117
+ backgrounds: { default: "Purple 700" },
118
+ },
119
+ }
120
+
121
+ export const ButtonFullWidth: Story = {
122
+ args: {
123
+ isFullWidth: true,
124
+ },
125
+ }
126
+
127
+ export const ButtonWithBadge: Story = {
128
+ args: {
129
+ children: (
130
+ <>
131
+ Label
132
+ <Badge classNameOverride="ms-8" size="small">
133
+ 3
134
+ </Badge>
135
+ </>
136
+ ),
75
137
  },
76
138
  }
@@ -1,20 +1,14 @@
1
1
  import React from "react"
2
2
  import { Meta, StoryObj } from "@storybook/react"
3
3
  import { userEvent, waitFor, within, expect, fn } from "@storybook/test"
4
- import { VisuallyHidden } from "react-aria"
5
- import {
6
- AddIcon,
7
- TrashIcon,
8
- ThumbsUpOffIcon,
9
- ThumbsUpOnIcon,
10
- } from "~components/Icon"
11
- import { Tooltip, TooltipTrigger } from "~components/__overlays__/v3"
4
+ import { VisuallyHidden } from "~components/VisuallyHidden"
5
+ import { Icon } from "~components/__future__/Icon"
12
6
  import { Button } from "../index"
13
7
 
14
8
  const onPressEvent = fn()
15
9
 
16
10
  const meta = {
17
- title: "Actions/Button/Button (v3)/Tests",
11
+ title: "Actions/Button/Button (v3)/Button (v3) tests",
18
12
  component: Button,
19
13
  args: {
20
14
  children: "Label",
@@ -26,106 +20,104 @@ export default meta
26
20
 
27
21
  type Story = StoryObj<typeof meta>
28
22
 
29
- export const ButtonDefault: Story = {
30
- render: ({ children, ...otherArgs }) => (
31
- <Button {...otherArgs}>
32
- <>
33
- {children}
34
- <AddIcon role="presentation" />
35
- </>
36
- </Button>
37
- ),
38
- }
39
-
40
- export const IsHovered: Story = {
41
- ...ButtonDefault,
42
- play: async ({ canvasElement, step }) => {
43
- const canvas = within(canvasElement.parentElement!)
44
- const button = canvas.getByRole("button")
45
-
46
- await step("Hover shows", async () => {
47
- await userEvent.hover(button)
48
- await expect(button).toHaveAttribute("data-hovered", "true")
49
- })
50
- },
51
- }
52
- export const IsHoveredReversed: Story = {
53
- ...IsHovered,
54
- parameters: {
55
- reverseColors: true,
23
+ // stress testing the accessible name being derived from the nested children
24
+ export const IconButtonWithHiddenLabel: Story = {
25
+ args: {
26
+ hasHiddenLabel: true,
27
+ icon: <Icon name="add" isPresentational />,
28
+ children: (
29
+ <span>
30
+ Hidden label <span>is</span> <span>accessible</span>
31
+ </span>
32
+ ),
56
33
  },
57
- }
58
-
59
- export const IsFocused: Story = {
60
- ...ButtonDefault,
61
- play: async ({ canvasElement, step }) => {
34
+ play: async ({ canvasElement }) => {
62
35
  const canvas = within(canvasElement.parentElement!)
63
36
  const button = canvas.getByRole("button")
64
37
 
65
- await step("Focus shows", async () => {
66
- await userEvent.tab()
67
-
68
- await waitFor(() => expect(document.activeElement).toBe(button))
69
- await expect(button).toHaveAttribute("data-focused", "true")
70
- })
38
+ expect(button).toHaveAccessibleName("Hidden label is accessible")
71
39
  },
72
40
  }
73
41
 
74
- export const IsFocusedReversed: Story = {
75
- ...IsFocused,
76
- parameters: {
77
- reverseColors: true,
42
+ export const PendingButton: Story = {
43
+ render: ({ isPending = false, pendingLabel = "Loading", ...otherProps }) => {
44
+ const [isPendingStatus, setIsPendingStatus] =
45
+ React.useState<boolean>(isPending)
46
+
47
+ return (
48
+ <Button
49
+ {...otherProps}
50
+ isPending={isPendingStatus}
51
+ pendingLabel={pendingLabel}
52
+ onPress={() => {
53
+ setIsPendingStatus(true)
54
+ setTimeout(() => {
55
+ setIsPendingStatus(false)
56
+ }, 900)
57
+ }}
58
+ />
59
+ )
78
60
  },
79
- }
80
-
81
- export const IsPressed: Story = {
82
- ...ButtonDefault,
83
61
  play: async ({ canvasElement, step }) => {
84
62
  const canvas = within(canvasElement.parentElement!)
85
- const button = canvas.getByRole("button")
63
+ const button = canvas.getByRole("button", { name: "Label" })
64
+ // Simulates a delay that may occur when a button must wait for a response
65
+ const timeToWait = 1000
66
+
67
+ await step("Button has accessible label", async () =>
68
+ expect(button).toHaveAccessibleName("Label")
69
+ )
86
70
 
87
- await step("onPress is called", async () => {
71
+ await step("Accessible label updates on press", async () => {
72
+ await button.focus()
88
73
  await userEvent.click(button)
74
+ await waitFor(() => expect(button).toHaveAccessibleName("Loading"))
75
+ })
89
76
 
90
- await expect(onPressEvent).toHaveBeenCalledTimes(1)
77
+ await step("Accessible label reverts once isPending is false", async () => {
78
+ await waitFor(() =>
79
+ setTimeout(() => {
80
+ expect(button).toHaveAccessibleName("Label")
81
+ }, timeToWait)
82
+ )
91
83
  })
92
84
  },
93
85
  }
94
86
 
95
- export const IconButtonWithAccessibleLabel: Story = {
96
- render: ({ children: _, ...otherArgs }) => (
97
- <Button {...otherArgs}>
98
- <>
99
- <TrashIcon role="img" aria-label="Remove" />
100
- <VisuallyHidden> Highlight: 18, June, 2024</VisuallyHidden>
101
- </>
102
- </Button>
103
- ),
104
- play: async ({ canvasElement, step }) => {
105
- const canvas = within(canvasElement.parentElement!)
106
- const button = canvas.getByRole("button")
107
-
108
- await step("has accessible labels", async () => {
109
- await userEvent.tab()
87
+ export const PendingButtonWithHiddenPendingLabel: Story = {
88
+ ...PendingButton,
89
+ args: {
90
+ hasHiddenPendingLabel: true,
91
+ isPending: false,
92
+ pendingLabel: "Loading",
93
+ },
94
+ }
110
95
 
111
- await expect(button).toHaveAccessibleName(
112
- "Remove Highlight: 18, June, 2024"
113
- )
114
- })
96
+ export const PendingIconButton: Story = {
97
+ ...PendingButton,
98
+ args: {
99
+ hasHiddenLabel: true,
100
+ isPending: false,
101
+ pendingLabel: "Loading",
102
+ icon: <Icon name="add" isPresentational />,
115
103
  },
116
104
  }
117
105
 
118
- export const ButtonWithRACRenderPropsAsChildren: Story = {
106
+ export const RACRenderPropsWithChildren: Story = {
119
107
  render: ({ children: _, ...otherArgs }) => (
120
108
  <Button {...otherArgs}>
121
- {({ isFocused }) => (
109
+ {({ isFocusVisible }) => (
122
110
  <>
123
111
  Label
124
- {isFocused ? (
125
- <ThumbsUpOnIcon role="img" aria-label=" is focused" />
126
- ) : (
127
- <ThumbsUpOffIcon role="img" aria-label=" is unfocused" />
128
- )}
112
+ <VisuallyHidden>
113
+ {isFocusVisible ? " is focused" : " is unfocused"}
114
+ </VisuallyHidden>
115
+ <Icon
116
+ name={isFocusVisible ? "thumb_up" : "thumb_down"}
117
+ isPresentational
118
+ isFilled={true}
119
+ className="ms-8 [--icon-size:16]"
120
+ />
129
121
  </>
130
122
  )}
131
123
  </Button>
@@ -149,45 +141,13 @@ export const ButtonWithRACRenderPropsAsChildren: Story = {
149
141
  },
150
142
  }
151
143
 
152
- // While this is a less likely use case, but as it is possible to use render props to apply a class name to the button so we should test that it works with our Button implementation
153
- export const ButtonWithRACRenderPropsAsClassname: Story = {
154
- render: ({ children: _, ...otherArgs }) => (
155
- <Button
156
- className={({ isFocused }) =>
157
- isFocused ? "!bg-blue-500 !text-white !border-transparent" : ""
158
- }
159
- {...otherArgs}
160
- >
161
- Label
162
- </Button>
163
- ),
144
+ export const RACRenderPropsWithClassName: Story = {
145
+ args: {
146
+ className: ({ isFocusVisible }) => (isFocusVisible ? "!bg-gray-300" : ""),
147
+ },
164
148
  play: async ({ canvasElement }) => {
165
149
  const canvas = within(canvasElement.parentElement!)
166
150
  const button = canvas.getByRole("button")
167
151
  await button.focus()
168
152
  },
169
153
  }
170
-
171
- // A compatibility check since when we develop tooltip the v1 button was an issue
172
- export const ButtonWithTooltip: Story = {
173
- render: ({ children: _, ...otherArgs }) => (
174
- <TooltipTrigger>
175
- <Button {...otherArgs}>Label</Button>
176
- <Tooltip>Tooltip content</Tooltip>
177
- </TooltipTrigger>
178
- ),
179
- play: async ({ canvasElement, step }) => {
180
- const canvas = within(canvasElement.parentElement!)
181
- const button = canvas.getByRole("button")
182
-
183
- await step("Focus shows", async () => {
184
- await userEvent.tab()
185
-
186
- await waitFor(() => expect(document.activeElement).toBe(button))
187
- })
188
-
189
- await step("Tooltip content show", async () => {
190
- await waitFor(() => expect(canvas.getByRole("tooltip")).toBeVisible())
191
- })
192
- },
193
- }