@kaizen/components 1.67.21 → 1.68.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.
Files changed (65) hide show
  1. package/dist/cjs/EmptyState/EmptyState.cjs +15 -17
  2. package/dist/cjs/EmptyState/EmptyState.module.css.cjs +20 -0
  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/EmptyState/EmptyState.mjs +15 -17
  11. package/dist/esm/EmptyState/EmptyState.module.css.mjs +18 -0
  12. package/dist/esm/__actions__/Button/v3/Button.mjs +44 -9
  13. package/dist/esm/__actions__/Button/v3/Button.module.css.mjs +19 -0
  14. package/dist/esm/__actions__/Button/v3/subcomponents/ButtonContent/ButtonContent.mjs +28 -0
  15. package/dist/esm/__actions__/Button/v3/subcomponents/ButtonContent/ButtonContent.module.css.mjs +7 -0
  16. package/dist/esm/__actions__/Button/v3/subcomponents/PendingContent/PendingContent.mjs +26 -0
  17. package/dist/esm/__actions__/Button/v3/subcomponents/PendingContent/PendingContent.module.css.mjs +6 -0
  18. package/dist/esm/__overlays__/Tooltip/v3/Tooltip.mjs +1 -1
  19. package/dist/styles.css +360 -246
  20. package/dist/types/EmptyState/EmptyState.d.ts +2 -1
  21. package/dist/types/__actions__/Button/v3/Button.d.ts +17 -4
  22. package/dist/types/__actions__/Button/v3/index.d.ts +1 -0
  23. package/dist/types/__actions__/Button/v3/subcomponents/ButtonContent/ButtonContent.d.ts +11 -0
  24. package/dist/types/__actions__/Button/v3/subcomponents/ButtonContent/index.d.ts +1 -0
  25. package/dist/types/__actions__/Button/v3/subcomponents/PendingContent/PendingContent.d.ts +5 -0
  26. package/dist/types/__actions__/Button/v3/subcomponents/PendingContent/index.d.ts +1 -0
  27. package/dist/types/__actions__/Button/v3/subcomponents/index.d.ts +2 -0
  28. package/dist/types/__actions__/Button/v3/types.d.ts +21 -0
  29. package/package.json +1 -1
  30. package/src/EmptyState/EmptyState.module.css +114 -0
  31. package/src/EmptyState/EmptyState.tsx +18 -20
  32. package/src/EmptyState/_docs/EmptyState.stickersheet.stories.tsx +55 -39
  33. package/src/__actions__/Button/v3/Button.module.css +235 -0
  34. package/src/__actions__/Button/v3/Button.tsx +92 -29
  35. package/src/__actions__/Button/v3/_docs/Button--api-specification.mdx +150 -0
  36. package/src/__actions__/Button/v3/_docs/Button--usage-guidelines.mdx +30 -0
  37. package/src/__actions__/Button/v3/_docs/Button.docs.stories.tsx +112 -50
  38. package/src/__actions__/Button/v3/_docs/Button.spec.stories.tsx +80 -120
  39. package/src/__actions__/Button/v3/_docs/Button.stickersheet.stories.tsx +183 -81
  40. package/src/__actions__/Button/v3/index.ts +1 -0
  41. package/src/__actions__/Button/v3/subcomponents/ButtonContent/ButtonContent.module.css +19 -0
  42. package/src/__actions__/Button/v3/subcomponents/ButtonContent/ButtonContent.tsx +40 -0
  43. package/src/__actions__/Button/v3/subcomponents/ButtonContent/index.ts +1 -0
  44. package/src/__actions__/Button/v3/subcomponents/PendingContent/PendingContent.module.css +16 -0
  45. package/src/__actions__/Button/v3/subcomponents/PendingContent/PendingContent.tsx +28 -0
  46. package/src/__actions__/Button/v3/subcomponents/PendingContent/index.ts +1 -0
  47. package/src/__actions__/Button/v3/subcomponents/index.ts +2 -0
  48. package/src/__actions__/Button/v3/types.ts +25 -0
  49. package/src/__actions__/Menu/v3/_docs/Menu.docs.stories.tsx +54 -18
  50. package/src/__actions__/Menu/v3/_docs/Menu.spec.stories.tsx +30 -10
  51. package/src/__actions__/Menu/v3/_docs/Menu.stories.tsx +12 -4
  52. package/src/__future__/Icon/_docs/Icon.docs.stories.tsx +7 -7
  53. package/src/__overlays__/Tooltip/v3/Tooltip.tsx +1 -1
  54. package/src/__overlays__/Tooltip/v3/_docs/Tooltip.spec.stories.tsx +2 -0
  55. package/dist/cjs/EmptyState/EmptyState.module.scss.cjs +0 -23
  56. package/dist/cjs/__actions__/Button/v3/Button.module.scss.cjs +0 -9
  57. package/dist/esm/EmptyState/EmptyState.module.scss.mjs +0 -21
  58. package/dist/esm/__actions__/Button/v3/Button.module.scss.mjs +0 -7
  59. package/src/EmptyState/EmptyState.module.scss +0 -186
  60. package/src/EmptyState/EmptyState.spec.tsx +0 -48
  61. package/src/EmptyState/_mixins.scss +0 -44
  62. package/src/__actions__/Button/v3/Button.module.scss +0 -104
  63. package/src/__actions__/Button/v3/_docs/ApiSpecification.mdx +0 -173
  64. package/src/__actions__/Button/v3/_docs/Button.mdx +0 -41
  65. package/src/__actions__/Button/v3/_docs/Button.stories.tsx +0 -98
@@ -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
- }
@@ -1,112 +1,214 @@
1
1
  import React from "react"
2
2
  import { Meta } from "@storybook/react"
3
- import { ArrowForwardIcon, AddIcon, TrashIcon } from "~components/Icon"
4
- import { LoadingSpinner } from "~components/Loading"
3
+ import { within } from "@storybook/test"
4
+ import { Icon } from "~components/__future__/Icon"
5
5
  import {
6
6
  StickerSheet,
7
7
  StickerSheetStory,
8
8
  } from "~storybook/components/StickerSheet"
9
- import { Button } from "../index"
9
+ import { Button, ButtonSizes, ButtonVariants } from "../index"
10
10
 
11
11
  export default {
12
- title: "Actions/Button/Button (v3)/Tests",
12
+ title: "Actions/Button/Button (v3)",
13
13
  parameters: {
14
14
  chromatic: { disable: false },
15
15
  controls: { disable: true },
16
16
  },
17
17
  } satisfies Meta
18
18
 
19
+ const variants = ["primary", "secondary", "tertiary"] satisfies ButtonVariants[]
20
+ const sizes = ["small", "medium", "large"] satisfies ButtonSizes[]
21
+
22
+ const RowTemplate = ({
23
+ isReversed = false,
24
+ }: {
25
+ isReversed?: boolean
26
+ }): JSX.Element => (
27
+ <>
28
+ {variants.map(variant =>
29
+ sizes.map(size => (
30
+ <StickerSheet.Row
31
+ key={size + variant}
32
+ isReversed={isReversed}
33
+ rowTitle={`${variant} (${size})`}
34
+ >
35
+ <Button variant={variant} size={size}>
36
+ Label
37
+ </Button>
38
+ <Button
39
+ icon={<Icon name="add" isPresentational />}
40
+ variant={variant}
41
+ size={size}
42
+ >
43
+ Label
44
+ </Button>
45
+ <Button
46
+ icon={
47
+ <Icon name="arrow_forward" shouldMirrorInRTL isPresentational />
48
+ }
49
+ iconPosition="end"
50
+ variant={variant}
51
+ size={size}
52
+ >
53
+ Label
54
+ </Button>
55
+ <Button
56
+ icon={
57
+ <Icon name="arrow_forward" shouldMirrorInRTL isPresentational />
58
+ }
59
+ iconPosition="end"
60
+ variant={variant}
61
+ isPending
62
+ pendingLabel="Submitting"
63
+ size={size}
64
+ >
65
+ Label
66
+ </Button>
67
+ <Button
68
+ icon={
69
+ <Icon name="arrow_forward" shouldMirrorInRTL isPresentational />
70
+ }
71
+ iconPosition="end"
72
+ variant={variant}
73
+ isPending
74
+ pendingLabel="Submitting"
75
+ hasHiddenPendingLabel
76
+ size={size}
77
+ >
78
+ Label
79
+ </Button>
80
+ <Button
81
+ icon={
82
+ <Icon name="arrow_forward" shouldMirrorInRTL isPresentational />
83
+ }
84
+ iconPosition="end"
85
+ variant={variant}
86
+ size={size}
87
+ isDisabled
88
+ >
89
+ Label
90
+ </Button>
91
+ </StickerSheet.Row>
92
+ ))
93
+ )}
94
+ </>
95
+ )
96
+
97
+ const IconButtonRowTemplate = ({
98
+ isReversed = false,
99
+ }: {
100
+ isReversed?: boolean
101
+ }): JSX.Element => (
102
+ <>
103
+ {sizes.map(size => (
104
+ <StickerSheet.Row
105
+ isReversed={isReversed}
106
+ rowTitle={size}
107
+ key={size + variants}
108
+ >
109
+ {variants.map(variant => (
110
+ <span className="flex gap-8" key={variant}>
111
+ <Button
112
+ icon={<Icon name="delete" isPresentational />}
113
+ hasHiddenLabel
114
+ size={size}
115
+ variant={variant}
116
+ >
117
+ Label
118
+ </Button>
119
+ <Button
120
+ icon={<Icon name="delete" isPresentational />}
121
+ size={size}
122
+ isPending
123
+ hasHiddenLabel
124
+ pendingLabel="Submitting"
125
+ variant={variant}
126
+ >
127
+ Label
128
+ </Button>
129
+ </span>
130
+ ))}
131
+ </StickerSheet.Row>
132
+ ))}
133
+ </>
134
+ )
135
+
19
136
  const StickerSheetTemplate: StickerSheetStory = {
20
137
  render: ({ isReversed }) => (
21
138
  <>
22
139
  <StickerSheet heading="Button" isReversed={isReversed}>
23
140
  <StickerSheet.Header
24
- headings={["Base", "Disabled", "working"]}
141
+ headings={[
142
+ "Base",
143
+ "Icon start",
144
+ "Icon end",
145
+ "isPending",
146
+ "hasHiddenPendingLabel",
147
+ "isDisabled",
148
+ ]}
25
149
  headingsWidth="10rem"
26
150
  hasVerticalHeadings
27
151
  verticalHeadingsWidth="12rem"
28
152
  />
29
153
  <StickerSheet.Body>
30
- <StickerSheet.Row rowTitle="Default">
31
- <Button>Label</Button>
32
-
33
- <Button isDisabled>Label</Button>
34
- <Button isDisabled>
35
- <LoadingSpinner size="sm" accessibilityLabel="submitting label" />
36
- </Button>
37
- </StickerSheet.Row>
38
- <StickerSheet.Row rowTitle="Icon start">
39
- <Button>
40
- <AddIcon role="presentation" />
41
- Label
42
- </Button>
43
- <Button isDisabled>
44
- <AddIcon role="presentation" />
45
- Label
46
- </Button>
47
- <Button isDisabled>
48
- <LoadingSpinner size="sm" accessibilityLabel="submitting label" />
49
- </Button>
50
- </StickerSheet.Row>
51
- <StickerSheet.Row rowTitle="Icon end">
52
- <Button>
53
- Label
54
- <ArrowForwardIcon role="presentation" />
55
- </Button>
56
- <Button isDisabled>
57
- Label
58
- <ArrowForwardIcon role="presentation" />
59
- </Button>
60
- <Button isDisabled>
61
- <LoadingSpinner size="sm" accessibilityLabel="submitting label" />
62
- </Button>
63
- </StickerSheet.Row>
64
- <StickerSheet.Row rowTitle="Icon only">
65
- <Button aria-label="Label">
66
- <TrashIcon role="presentation" />
67
- </Button>
68
- <Button aria-label="Label" isDisabled>
69
- <TrashIcon role="presentation" />
70
- </Button>
71
- <Button aria-label="Label" isDisabled>
72
- <LoadingSpinner size="sm" accessibilityLabel="submitting label" />
73
- </Button>
74
- </StickerSheet.Row>
75
- <StickerSheet.Row rowTitle="Small">
76
- <Button size="small">
77
- Label
78
- <ArrowForwardIcon role="presentation" />
79
- </Button>
80
- <Button size="small" isDisabled>
81
- Label
82
- <ArrowForwardIcon role="presentation" />
83
- </Button>
84
- <Button size="small" isDisabled>
85
- <LoadingSpinner size="xs" accessibilityLabel="submitting label" />
86
- </Button>
87
- </StickerSheet.Row>
88
- <StickerSheet.Row rowTitle="Icon only small">
89
- <Button size="small">
90
- <TrashIcon role="img" aria-label="Remove label" />
91
- </Button>
92
- <Button size="small" isDisabled>
93
- <TrashIcon role="img" aria-label="Remove label" />
94
- </Button>
95
- <Button size="small" isDisabled>
96
- <LoadingSpinner size="xs" accessibilityLabel="Removing label" />
97
- </Button>
98
- </StickerSheet.Row>
154
+ <RowTemplate isReversed={isReversed} />
155
+ </StickerSheet.Body>
156
+ </StickerSheet>
157
+ <StickerSheet heading="Icon only button" isReversed={isReversed}>
158
+ <StickerSheet.Header
159
+ headings={["primary", "secondary", "tertiary"]}
160
+ headingsWidth="10rem"
161
+ hasVerticalHeadings
162
+ verticalHeadingsWidth="12rem"
163
+ />
164
+ <StickerSheet.Body>
165
+ <IconButtonRowTemplate isReversed={isReversed} />
166
+ </StickerSheet.Body>
167
+ </StickerSheet>
168
+ <StickerSheet heading="Pseudo states" isReversed={isReversed}>
169
+ <StickerSheet.Header
170
+ headings={["isHovered", "isFocusVisible", "isPressed"]}
171
+ headingsWidth="10rem"
172
+ hasVerticalHeadings
173
+ verticalHeadingsWidth="12rem"
174
+ />
175
+ <StickerSheet.Body>
176
+ {variants.map(variant => (
177
+ <StickerSheet.Row
178
+ key={variant}
179
+ isReversed={isReversed}
180
+ rowTitle={variant}
181
+ >
182
+ <Button data-testid="testid__button-hover" variant={variant}>
183
+ Label
184
+ </Button>
185
+ <Button data-testid="testid__button-focus" variant={variant}>
186
+ Label
187
+ </Button>
188
+ <Button data-testid="testid__button-pressed" variant={variant}>
189
+ Label
190
+ </Button>
191
+ </StickerSheet.Row>
192
+ ))}
99
193
  </StickerSheet.Body>
100
194
  </StickerSheet>
101
195
  </>
102
196
  ),
103
- parameters: {
104
- pseudo: {
105
- hover: '[data-hovered="true"]',
106
- active: '[data-pressed="true"]',
107
- focus: '[data-focused="true"]',
108
- focusVisible: '[data-focus-visible="true"]',
109
- },
197
+ play: ({ canvasElement }) => {
198
+ const canvas = within(canvasElement)
199
+ const focusButtons = canvas.getAllByTestId("testid__button-focus")
200
+ const hoverButtons = canvas.getAllByTestId("testid__button-hover")
201
+ const pressedButton = canvas.getAllByTestId("testid__button-pressed")
202
+
203
+ focusButtons.forEach(button => {
204
+ button.setAttribute("data-focus-visible", "true")
205
+ })
206
+ hoverButtons.forEach(button => {
207
+ button.setAttribute("data-hovered", "true")
208
+ })
209
+ pressedButton.forEach(button => {
210
+ button.setAttribute("data-pressed", "true")
211
+ })
110
212
  },
111
213
  }
112
214
 
@@ -1 +1,2 @@
1
1
  export * from "./Button"
2
+ export * from "./types"
@@ -0,0 +1,19 @@
1
+ .buttonContent {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ gap: var(--button-icon-gap, var(--spacing-6));
5
+ }
6
+
7
+ .large {
8
+ --button-icon-gap: var(--spacing-8);
9
+ }
10
+
11
+ .buttonLabel {
12
+ display: inline-flex;
13
+ align-items: center;
14
+ }
15
+
16
+ .buttonIcon {
17
+ display: inline-flex;
18
+ align-items: center;
19
+ }
@@ -0,0 +1,40 @@
1
+ import React, { HTMLAttributes } from "react"
2
+ import classNames from "classnames"
3
+ import { VisuallyHidden } from "~components/VisuallyHidden"
4
+ import { ButtonProps } from "../../Button"
5
+ import styles from "./ButtonContent.module.css"
6
+
7
+ type ButtonContentProps = {
8
+ size?: ButtonProps["size"]
9
+ icon?: ButtonProps["icon"]
10
+ iconPosition?: ButtonProps["iconPosition"]
11
+ hasHiddenLabel?: ButtonProps["hasHiddenLabel"]
12
+ } & HTMLAttributes<HTMLSpanElement>
13
+
14
+ /** Renders the inner content of the button, handling icon and label visibility */
15
+ export const ButtonContent = ({
16
+ children,
17
+ hasHiddenLabel,
18
+ size = "medium",
19
+ icon,
20
+ iconPosition = "start",
21
+ className,
22
+ ...restProps
23
+ }: ButtonContentProps): JSX.Element => (
24
+ <span
25
+ className={classNames(className, styles.buttonContent, styles[size])}
26
+ {...restProps}
27
+ >
28
+ {icon && iconPosition === "start" && (
29
+ <span className={styles.buttonIcon}>{icon}</span>
30
+ )}
31
+ {hasHiddenLabel ? (
32
+ <VisuallyHidden>{children}</VisuallyHidden>
33
+ ) : (
34
+ <span className={styles.buttonLabel}>{children}</span>
35
+ )}
36
+ {icon && iconPosition === "end" && (
37
+ <span className={styles.buttonIcon}>{icon}</span>
38
+ )}
39
+ </span>
40
+ )
@@ -0,0 +1 @@
1
+ export * from "./ButtonContent"
@@ -0,0 +1,16 @@
1
+ .pendingContent {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ gap: var(--button-pending-content-gap, var(--spacing-6));
5
+ }
6
+
7
+ .large {
8
+ --button-pending-content-gap: var(--spacing-8);
9
+ }
10
+
11
+ .centerSpinner {
12
+ position: absolute;
13
+ left: 50%;
14
+ top: 50%;
15
+ transform: translate(-50%, -50%);
16
+ }
@@ -0,0 +1,28 @@
1
+ import React from "react"
2
+ import classNames from "classnames"
3
+ import { LoadingSpinner } from "~components/Loading"
4
+ import { VisuallyHidden } from "~components/VisuallyHidden"
5
+ import { ButtonSizes, PendingProps } from "../../types"
6
+ import styles from "./PendingContent.module.css"
7
+
8
+ /** Renders the pending content of the button, handling pending label visibility and spinner positioning */
9
+ export const PendingContent = ({
10
+ pendingLabel,
11
+ hasHiddenPendingLabel = false,
12
+ size = "medium",
13
+ }: PendingProps & { size?: ButtonSizes }): JSX.Element => (
14
+ <span className={classNames(styles.pendingContent, styles[size])}>
15
+ {hasHiddenPendingLabel ? (
16
+ <VisuallyHidden>{pendingLabel}</VisuallyHidden>
17
+ ) : (
18
+ <span>{pendingLabel}</span>
19
+ )}
20
+ <LoadingSpinner
21
+ size={size === "small" ? "xs" : "sm"}
22
+ accessibilityLabel=""
23
+ classNameOverride={
24
+ hasHiddenPendingLabel ? styles.centerSpinner : undefined
25
+ }
26
+ />
27
+ </span>
28
+ )
@@ -0,0 +1 @@
1
+ export * from "./PendingContent"
@@ -0,0 +1,2 @@
1
+ export * from "./PendingContent"
2
+ export * from "./ButtonContent"