@windstream/react-shared-components 0.0.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 (112) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +360 -0
  3. package/dist/core.d.ts +389 -0
  4. package/dist/index.d.ts +389 -0
  5. package/dist/index.esm.js +35 -0
  6. package/dist/index.esm.js.map +1 -0
  7. package/dist/index.js +35 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/styles.css +3 -0
  10. package/dist/utils/index.d.ts +11 -0
  11. package/dist/utils/index.esm.js +2 -0
  12. package/dist/utils/index.esm.js.map +1 -0
  13. package/dist/utils/index.js +2 -0
  14. package/dist/utils/index.js.map +1 -0
  15. package/package.json +151 -0
  16. package/src/components/accordion/Accordion.stories.tsx +225 -0
  17. package/src/components/accordion/index.tsx +36 -0
  18. package/src/components/accordion/types.ts +10 -0
  19. package/src/components/alert-card/AlertCard.stories.tsx +172 -0
  20. package/src/components/alert-card/index.tsx +35 -0
  21. package/src/components/alert-card/types.ts +9 -0
  22. package/src/components/brand-button/BrandButton.stories.tsx +221 -0
  23. package/src/components/brand-button/helpers.ts +35 -0
  24. package/src/components/brand-button/index.tsx +90 -0
  25. package/src/components/brand-button/types.ts +27 -0
  26. package/src/components/button/Button.stories.tsx +108 -0
  27. package/src/components/button/index.tsx +23 -0
  28. package/src/components/button/types.ts +14 -0
  29. package/src/components/call-button/CallButton.stories.tsx +324 -0
  30. package/src/components/call-button/index.tsx +80 -0
  31. package/src/components/call-button/types.ts +9 -0
  32. package/src/components/checkbox/Checkbox.stories.tsx +248 -0
  33. package/src/components/checkbox/index.tsx +185 -0
  34. package/src/components/checkbox/types.ts +24 -0
  35. package/src/components/checklist/Checklist.stories.tsx +151 -0
  36. package/src/components/checklist/index.tsx +33 -0
  37. package/src/components/checklist/types.ts +6 -0
  38. package/src/components/collapse/Collapse.stories.tsx +256 -0
  39. package/src/components/collapse/index.tsx +44 -0
  40. package/src/components/collapse/types.ts +6 -0
  41. package/src/components/divider/Divider.stories.tsx +206 -0
  42. package/src/components/divider/index.tsx +23 -0
  43. package/src/components/divider/type.ts +3 -0
  44. package/src/components/input/Input.stories.tsx +358 -0
  45. package/src/components/input/index.tsx +174 -0
  46. package/src/components/input/types.ts +37 -0
  47. package/src/components/link/Link.stories.tsx +163 -0
  48. package/src/components/link/index.tsx +96 -0
  49. package/src/components/link/types.ts +25 -0
  50. package/src/components/list/List.stories.tsx +272 -0
  51. package/src/components/list/index.tsx +86 -0
  52. package/src/components/list/list-item/index.tsx +36 -0
  53. package/src/components/list/list-item/types.ts +13 -0
  54. package/src/components/list/types.ts +29 -0
  55. package/src/components/material-icon/MaterialIcon.stories.tsx +330 -0
  56. package/src/components/material-icon/constants.ts +95 -0
  57. package/src/components/material-icon/index.tsx +44 -0
  58. package/src/components/material-icon/types.ts +31 -0
  59. package/src/components/modal/Modal.stories.tsx +171 -0
  60. package/src/components/modal/index.tsx +168 -0
  61. package/src/components/modal/types.ts +24 -0
  62. package/src/components/radio-button/RadioButton.stories.tsx +307 -0
  63. package/src/components/radio-button/index.tsx +73 -0
  64. package/src/components/radio-button/types.ts +22 -0
  65. package/src/components/see-more/SeeMore.stories.tsx +182 -0
  66. package/src/components/see-more/index.tsx +38 -0
  67. package/src/components/see-more/types.ts +4 -0
  68. package/src/components/select/Select.stories.tsx +410 -0
  69. package/src/components/select/index.tsx +150 -0
  70. package/src/components/select/types.ts +34 -0
  71. package/src/components/select-plan-button/SelectPlanButton.stories.tsx +160 -0
  72. package/src/components/select-plan-button/index.tsx +21 -0
  73. package/src/components/select-plan-button/types.ts +4 -0
  74. package/src/components/skeleton/Skeleton.stories.tsx +180 -0
  75. package/src/components/skeleton/index.tsx +61 -0
  76. package/src/components/skeleton/types.ts +4 -0
  77. package/src/components/spinner/Spinner.stories.tsx +335 -0
  78. package/src/components/spinner/index.tsx +44 -0
  79. package/src/components/spinner/types.ts +5 -0
  80. package/src/components/text/Text.stories.tsx +302 -0
  81. package/src/components/text/index.tsx +26 -0
  82. package/src/components/text/types.ts +45 -0
  83. package/src/components/tooltip/Tooltip.stories.tsx +220 -0
  84. package/src/components/tooltip/index.tsx +78 -0
  85. package/src/components/tooltip/types.ts +7 -0
  86. package/src/components/view-cart-button/ViewCartButton.stories.tsx +241 -0
  87. package/src/components/view-cart-button/index.tsx +39 -0
  88. package/src/components/view-cart-button/types.ts +5 -0
  89. package/src/hooks/use-body-scroll-lock.ts +31 -0
  90. package/src/index.ts +81 -0
  91. package/src/setupTests.ts +46 -0
  92. package/src/stories/DocsTemplate.tsx +26 -0
  93. package/src/stories/assets/accessibility.png +0 -0
  94. package/src/stories/assets/accessibility.svg +1 -0
  95. package/src/stories/assets/addon-library.png +0 -0
  96. package/src/stories/assets/assets.png +0 -0
  97. package/src/stories/assets/avif-test-image.avif +0 -0
  98. package/src/stories/assets/context.png +0 -0
  99. package/src/stories/assets/discord.svg +1 -0
  100. package/src/stories/assets/docs.png +0 -0
  101. package/src/stories/assets/figma-plugin.png +0 -0
  102. package/src/stories/assets/github.svg +1 -0
  103. package/src/stories/assets/share.png +0 -0
  104. package/src/stories/assets/styling.png +0 -0
  105. package/src/stories/assets/testing.png +0 -0
  106. package/src/stories/assets/theming.png +0 -0
  107. package/src/stories/assets/tutorials.svg +1 -0
  108. package/src/stories/assets/youtube.svg +1 -0
  109. package/src/styles/globals.css +50 -0
  110. package/src/types/global.d.ts +9 -0
  111. package/src/utils/index.ts +49 -0
  112. package/tailwind.config.cjs +524 -0
@@ -0,0 +1,23 @@
1
+ import { forwardRef } from "react";
2
+ import { cx } from "@shared/utils";
3
+ import { ButtonProps } from "@shared/components/button/types";
4
+ // Minimal button: styling is entirely up to the consumer via className
5
+ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
6
+ ({ children, className = "", style, disabled, ...props }, ref) => {
7
+ return (
8
+ <button
9
+ ref={ref}
10
+ className={cx(className)}
11
+ style={style}
12
+ disabled={disabled}
13
+ {...props}
14
+ >
15
+ {children}
16
+ </button>
17
+ );
18
+ }
19
+ );
20
+
21
+ Button.displayName = "Button";
22
+
23
+ export type { ButtonProps };
@@ -0,0 +1,14 @@
1
+ import {
2
+ type ButtonHTMLAttributes,
3
+ type CSSProperties,
4
+ type ReactNode,
5
+ } from "react";
6
+
7
+ export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
8
+ /** Content to render inside the button */
9
+ children?: ReactNode;
10
+ /** Custom className for the button */
11
+ className?: string;
12
+ /** Custom styles */
13
+ style?: CSSProperties;
14
+ }
@@ -0,0 +1,324 @@
1
+ import { CallButton } from "./index";
2
+ import { DocsPage } from "@shared/stories/DocsTemplate";
3
+
4
+ import type { Meta, StoryObj } from "@storybook/react";
5
+
6
+ const meta: Meta<typeof CallButton> = {
7
+ title: "Components/CallButton",
8
+ component: CallButton,
9
+ tags: ["autodocs"],
10
+ parameters: {
11
+ layout: "centered",
12
+ docs: {
13
+ page: DocsPage,
14
+ description: {
15
+ component:
16
+ "A call button component that extends the Link component with a call icon and optional blinking dot.",
17
+ },
18
+ },
19
+ },
20
+ argTypes: {
21
+ showBlinkDot: {
22
+ control: { type: "boolean" },
23
+ description: "Show a blinking dot indicator",
24
+ },
25
+ buttonStyle: {
26
+ control: { type: "select" },
27
+ options: ["primary"],
28
+ description: "Visual style variant",
29
+ },
30
+ size: {
31
+ control: { type: "select" },
32
+ options: ["sm", "md", "lg"],
33
+ description: "Button size",
34
+ },
35
+ href: {
36
+ control: { type: "text" },
37
+ description: "Link destination",
38
+ },
39
+ children: {
40
+ control: { type: "text" },
41
+ description: "Button text content",
42
+ },
43
+ className: {
44
+ control: { type: "text" },
45
+ description: "Additional CSS classes",
46
+ },
47
+ },
48
+ args: {
49
+ href: "tel:+1234567890",
50
+ children: "Call Now",
51
+ showBlinkDot: false,
52
+ buttonStyle: "primary",
53
+ size: "md",
54
+ },
55
+ };
56
+
57
+ export default meta;
58
+ type Story = StoryObj<typeof meta>;
59
+
60
+ // All variants showcase - Real visual variants
61
+ export const AllVariants: Story = {
62
+ render: () => (
63
+ <div className="space-y-8">
64
+ <div>
65
+ <h3 className="mb-4 text-lg font-semibold">Style Variants</h3>
66
+ <div className="grid grid-cols-2 gap-4">
67
+ <div className="space-y-3">
68
+ <h4 className="text-sm font-medium text-gray-600">
69
+ Primary (Default)
70
+ </h4>
71
+ <CallButton href="tel:+1234567890" buttonStyle="primary">
72
+ Call Now
73
+ </CallButton>
74
+ </div>
75
+ </div>
76
+ </div>
77
+
78
+ <div>
79
+ <h3 className="mb-4 text-lg font-semibold">Size Variants</h3>
80
+ <div className="grid grid-cols-3 gap-4">
81
+ <div className="space-y-3">
82
+ <h4 className="text-sm font-medium text-gray-600">Small</h4>
83
+ <CallButton href="tel:+1234567890" size="sm">
84
+ Call
85
+ </CallButton>
86
+ </div>
87
+ <div className="space-y-3">
88
+ <h4 className="text-sm font-medium text-gray-600">
89
+ Medium (Default)
90
+ </h4>
91
+ <CallButton href="tel:+1234567890" size="md">
92
+ Call Now
93
+ </CallButton>
94
+ </div>
95
+ <div className="space-y-3">
96
+ <h4 className="text-sm font-medium text-gray-600">Large</h4>
97
+ <CallButton href="tel:+1234567890" size="lg">
98
+ Call Now
99
+ </CallButton>
100
+ </div>
101
+ </div>
102
+ </div>
103
+
104
+ <div>
105
+ <h3 className="mb-4 text-lg font-semibold">Blinking Dot Variant</h3>
106
+ <div className="space-y-3">
107
+ <CallButton
108
+ href="tel:+1234567890"
109
+ showBlinkDot={true}
110
+ buttonStyle="primary"
111
+ >
112
+ Emergency Hotline
113
+ </CallButton>
114
+ </div>
115
+ </div>
116
+ </div>
117
+ ),
118
+ parameters: {
119
+ docs: {
120
+ description: {
121
+ story:
122
+ "Complete showcase of all CallButton visual variants: styles, sizes, and blinking dot.",
123
+ },
124
+ },
125
+ },
126
+ };
127
+
128
+ // Default call button
129
+ export const Default: Story = {
130
+ args: {
131
+ buttonStyle: "primary",
132
+ size: "md",
133
+ showBlinkDot: false,
134
+ },
135
+ parameters: {
136
+ docs: {
137
+ description: {
138
+ story: "Default CallButton with primary style and medium size.",
139
+ },
140
+ },
141
+ },
142
+ };
143
+
144
+ // Call button with blinking dot
145
+ export const WithBlinkDot: Story = {
146
+ args: {
147
+ showBlinkDot: true,
148
+ children: "Call Now",
149
+ buttonStyle: "primary",
150
+ size: "md",
151
+ },
152
+ parameters: {
153
+ docs: {
154
+ description: {
155
+ story:
156
+ "CallButton with blinking dot indicator for emergency or priority calls.",
157
+ },
158
+ },
159
+ },
160
+ };
161
+
162
+ // Style variations
163
+ export const StyleVariations: Story = {
164
+ render: () => (
165
+ <div className="space-y-4">
166
+ <div className="space-y-2">
167
+ <h4 className="text-sm font-medium text-gray-600">Primary Style</h4>
168
+ <CallButton href="tel:+1234567890" buttonStyle="primary">
169
+ Call Support
170
+ </CallButton>
171
+ </div>
172
+ </div>
173
+ ),
174
+ parameters: {
175
+ docs: {
176
+ description: {
177
+ story:
178
+ "All four CallButton style variants: primary, secondary, outline, and ghost.",
179
+ },
180
+ },
181
+ },
182
+ };
183
+
184
+ // Size variations
185
+ export const SizeVariations: Story = {
186
+ render: () => (
187
+ <div className="space-y-4">
188
+ <div className="space-y-2">
189
+ <h4 className="text-sm font-medium text-gray-600">Small Size</h4>
190
+ <CallButton href="tel:+1234567890" size="sm">
191
+ Call
192
+ </CallButton>
193
+ </div>
194
+ <div className="space-y-2">
195
+ <h4 className="text-sm font-medium text-gray-600">
196
+ Medium Size (Default)
197
+ </h4>
198
+ <CallButton href="tel:+1234567890" size="md">
199
+ Call Now
200
+ </CallButton>
201
+ </div>
202
+ <div className="space-y-2">
203
+ <h4 className="text-sm font-medium text-gray-600">Large Size</h4>
204
+ <CallButton href="tel:+1234567890" size="lg">
205
+ Call Now
206
+ </CallButton>
207
+ </div>
208
+ </div>
209
+ ),
210
+ parameters: {
211
+ docs: {
212
+ description: {
213
+ story: "All three CallButton size variants: small, medium, and large.",
214
+ },
215
+ },
216
+ },
217
+ };
218
+
219
+ // Interactive combinations
220
+ export const Interactive: Story = {
221
+ render: () => (
222
+ <div className="space-y-6">
223
+ <div>
224
+ <h3 className="mb-3 text-lg font-semibold">Emergency Contacts</h3>
225
+ <div className="space-y-3">
226
+ <CallButton
227
+ href="tel:+1234567890"
228
+ showBlinkDot={true}
229
+ buttonStyle="primary"
230
+ size="lg"
231
+ >
232
+ Emergency Hotline
233
+ </CallButton>
234
+ </div>
235
+ </div>
236
+ </div>
237
+ ),
238
+ parameters: {
239
+ docs: {
240
+ description: {
241
+ story:
242
+ "Interactive examples showing combinations of CallButton variants for different use cases.",
243
+ },
244
+ },
245
+ },
246
+ };
247
+
248
+ // States and interactions
249
+ export const StatesAndInteractions: Story = {
250
+ render: () => (
251
+ <div className="space-y-6">
252
+ <div>
253
+ <h3 className="mb-3 text-lg font-semibold">Hover States</h3>
254
+ <p className="mb-2 text-sm text-gray-600">
255
+ Hover over the buttons to see interactive states
256
+ </p>
257
+ <div className="space-y-3">
258
+ <CallButton href="tel:+1234567890" showBlinkDot={true}>
259
+ Hover Me
260
+ </CallButton>
261
+ <CallButton href="tel:+1234567890">Hover Me Too</CallButton>
262
+ </div>
263
+ </div>
264
+
265
+ <div>
266
+ <h3 className="mb-3 text-lg font-semibold">Focus States</h3>
267
+ <p className="mb-2 text-sm text-gray-600">
268
+ Tab to focus and see keyboard navigation states
269
+ </p>
270
+ <div className="space-y-3">
271
+ <CallButton href="tel:+1234567890">Focus Me</CallButton>
272
+ <CallButton href="tel:+1234567890">Focus Me Too</CallButton>
273
+ </div>
274
+ </div>
275
+ </div>
276
+ ),
277
+ parameters: {
278
+ docs: {
279
+ description: {
280
+ story:
281
+ "Demonstrates hover, focus, and interaction states of the CallButton component.",
282
+ },
283
+ },
284
+ },
285
+ };
286
+
287
+ // Accessibility showcase
288
+ export const Accessibility: Story = {
289
+ render: () => (
290
+ <div className="space-y-4">
291
+ <div>
292
+ <h3 className="mb-3 text-lg font-semibold">Screen Reader Friendly</h3>
293
+ <p className="mb-2 text-sm text-gray-600">
294
+ These buttons include proper ARIA labels and descriptions
295
+ </p>
296
+ <div className="space-y-3">
297
+ <CallButton
298
+ href="tel:+1234567890"
299
+ showBlinkDot={true}
300
+ aria-label="Call emergency support line"
301
+ aria-description="24/7 emergency hotline with priority response"
302
+ >
303
+ Emergency Support
304
+ </CallButton>
305
+ <CallButton
306
+ href="tel:+1234567890"
307
+ aria-label="Call customer service"
308
+ aria-description="General customer support and inquiries"
309
+ >
310
+ Customer Service
311
+ </CallButton>
312
+ </div>
313
+ </div>
314
+ </div>
315
+ ),
316
+ parameters: {
317
+ docs: {
318
+ description: {
319
+ story:
320
+ "Accessibility features including ARIA labels and screen reader support.",
321
+ },
322
+ },
323
+ },
324
+ };
@@ -0,0 +1,80 @@
1
+ import { Link } from "@shared/components/link";
2
+ import { MaterialIcon } from "@shared/components/material-icon";
3
+ import type { IconProps } from "@shared/components/material-icon/types";
4
+ import type { CallButtonProps } from "@shared/components/call-button/types";
5
+
6
+ export const CallButton = (props: CallButtonProps) => {
7
+ const {
8
+ showBlinkDot = false,
9
+ buttonStyle = "primary",
10
+ size = "md",
11
+ children,
12
+ ...rest
13
+ } = props;
14
+
15
+ const baseClasses =
16
+ "relative flex items-center gap-2 font-medium tracking-wide outline-offset-4 rounded-full";
17
+
18
+ const sizeClasses = {
19
+ sm: "h-6 text-xs pl-1 pr-2",
20
+ md: "h-8 text-sm pl-1 pr-2",
21
+ lg: "h-10 text-base pl-2 pr-3",
22
+ };
23
+
24
+ const styleClasses = {
25
+ primary:
26
+ "border-[0.727px] border-border text-text"
27
+ };
28
+
29
+ const iconSize: Record<string, IconProps["size"]> = {
30
+ sm: 20,
31
+ md: 20,
32
+ lg: 32,
33
+ };
34
+
35
+ const iconContainerSize = {
36
+ sm: "h-5 w-5",
37
+ md: "h-6 w-6",
38
+ lg: "h-8 w-8",
39
+ };
40
+
41
+ const dotSize = {
42
+ sm: "h-2 w-2",
43
+ md: "h-3 w-3",
44
+ lg: "h-4 w-4",
45
+ };
46
+
47
+ const dotPosition = {
48
+ sm: "-left-4",
49
+ md: "-left-6",
50
+ lg: "-left-8",
51
+ };
52
+
53
+ return (
54
+ <Link
55
+ {...rest}
56
+ className={`${baseClasses} ${sizeClasses[size]} ${styleClasses[buttonStyle]}`}
57
+ >
58
+ {showBlinkDot ? (
59
+ <span
60
+ className={`animate-blink pointer-events-none absolute ${dotPosition[size]} top-1/2 ${dotSize[size]} -translate-y-1/2 rounded-full bg-icon-brand`}
61
+ />
62
+ ) : null}
63
+ <span
64
+ className={`relative inline-flex ${iconContainerSize[size]} items-center justify-center rounded-full bg-icon-brand`}
65
+ >
66
+ <MaterialIcon
67
+ name="call"
68
+ fill={1}
69
+ size={iconSize[size]}
70
+ className="text-white"
71
+ />
72
+ </span>
73
+ <span className="font-normal tracking-wide">{children}</span>
74
+ </Link>
75
+ );
76
+ };
77
+
78
+ CallButton.displayName = "CallButton";
79
+
80
+ export type { CallButtonProps };
@@ -0,0 +1,9 @@
1
+ import { ReactNode } from "react";
2
+ import { LinkProps } from "@shared/components/link/types";
3
+
4
+ export interface CallButtonProps extends Omit<LinkProps, "children"> {
5
+ showBlinkDot?: boolean;
6
+ buttonStyle?: "primary";
7
+ size?: "sm" | "md" | "lg";
8
+ children: ReactNode;
9
+ }
@@ -0,0 +1,248 @@
1
+ import { Checkbox } from "./index";
2
+ import { DocsPage } from "@shared/stories/DocsTemplate";
3
+
4
+ import type { Meta, StoryObj } from "@storybook/react";
5
+ import { useState } from "react";
6
+
7
+ const meta: Meta<typeof Checkbox> = {
8
+ title: "Components/Checkbox",
9
+ component: Checkbox,
10
+ tags: ["autodocs"],
11
+ parameters: {
12
+ layout: "centered",
13
+ docs: {
14
+ page: DocsPage,
15
+ description: {
16
+ component:
17
+ "A checkbox component with support for checked/unchecked states, labels, error states, and info icons.",
18
+ },
19
+ },
20
+ },
21
+ argTypes: {
22
+ checked: {
23
+ control: { type: "boolean" },
24
+ description: "Whether the checkbox is checked",
25
+ },
26
+ disabled: {
27
+ control: { type: "boolean" },
28
+ description: "Disable the checkbox",
29
+ },
30
+ label: {
31
+ control: { type: "text" },
32
+ description: "Label text for the checkbox",
33
+ },
34
+ error: {
35
+ control: { type: "boolean" },
36
+ description: "Show error state",
37
+ },
38
+ required: {
39
+ control: { type: "boolean" },
40
+ description: "Mark checkbox as required",
41
+ },
42
+ state: {
43
+ control: { type: "select" },
44
+ options: ["default", "focus", "disabled"],
45
+ description: "Visual state of the checkbox",
46
+ },
47
+ },
48
+ args: {
49
+ checked: false,
50
+ disabled: false,
51
+ label: "Checkbox Label",
52
+ error: false,
53
+ required: false,
54
+ },
55
+ };
56
+
57
+ export default meta;
58
+ type Story = StoryObj<typeof meta>;
59
+
60
+ // Default checkbox
61
+ export const Default: Story = {
62
+ args: {},
63
+ };
64
+
65
+ // Checked checkbox
66
+ export const Checked: Story = {
67
+ args: {
68
+ checked: true,
69
+ label: "Checked Checkbox",
70
+ },
71
+ };
72
+
73
+ // Unchecked checkbox
74
+ export const Unchecked: Story = {
75
+ args: {
76
+ checked: false,
77
+ label: "Unchecked Checkbox",
78
+ },
79
+ };
80
+
81
+ // With label
82
+ export const WithLabel: Story = {
83
+ args: {
84
+ checked: false,
85
+ label: "I agree to the terms and conditions",
86
+ },
87
+ };
88
+
89
+ // Disabled checkbox
90
+ export const Disabled: Story = {
91
+ args: {
92
+ checked: false,
93
+ label: "Disabled Checkbox",
94
+ disabled: true,
95
+ },
96
+ };
97
+
98
+ // Disabled checked
99
+ export const DisabledChecked: Story = {
100
+ args: {
101
+ checked: true,
102
+ label: "Disabled Checked Checkbox",
103
+ disabled: true,
104
+ },
105
+ };
106
+
107
+ // Error state
108
+ export const Error: Story = {
109
+ args: {
110
+ checked: false,
111
+ label: "Checkbox with Error",
112
+ error: true,
113
+ },
114
+ };
115
+
116
+ // Required checkbox
117
+ export const Required: Story = {
118
+ args: {
119
+ checked: false,
120
+ label: "Required Field",
121
+ required: true,
122
+ },
123
+ };
124
+
125
+ // Focus state
126
+ export const Focus: Story = {
127
+ args: {
128
+ checked: false,
129
+ label: "Focused Checkbox",
130
+ state: "focus",
131
+ },
132
+ };
133
+
134
+ // With info icon
135
+ export const WithInfoIcon: Story = {
136
+ args: {
137
+ checked: false,
138
+ label: "Checkbox with Info",
139
+ renderInfoIcon: {
140
+ onClick: () => alert("Info clicked"),
141
+ dataTestId: "info-icon",
142
+ },
143
+ },
144
+ };
145
+
146
+ // Interactive checkbox
147
+ export const Interactive: Story = {
148
+ render: () => {
149
+ const [checked, setChecked] = useState(false);
150
+ return (
151
+ <Checkbox
152
+ checked={checked}
153
+ onChange={(isChecked) => setChecked(isChecked)}
154
+ label="Click to toggle"
155
+ />
156
+ );
157
+ },
158
+ parameters: {
159
+ docs: {
160
+ description: {
161
+ story: "Interactive checkbox that can be toggled by clicking.",
162
+ },
163
+ },
164
+ },
165
+ };
166
+
167
+ // Multiple checkboxes
168
+ export const Multiple: Story = {
169
+ render: () => {
170
+ const [items, setItems] = useState([
171
+ { id: 1, label: "Option 1", checked: false },
172
+ { id: 2, label: "Option 2", checked: true },
173
+ { id: 3, label: "Option 3", checked: false },
174
+ ]);
175
+
176
+ const handleChange = (id: number, isChecked: boolean) => {
177
+ setItems(
178
+ items.map((item) =>
179
+ item.id === id ? { ...item, checked: isChecked } : item
180
+ )
181
+ );
182
+ };
183
+
184
+ return (
185
+ <div className="space-y-3">
186
+ {items.map((item) => (
187
+ <Checkbox
188
+ key={item.id}
189
+ checked={item.checked}
190
+ onChange={(isChecked) => handleChange(item.id, isChecked)}
191
+ label={item.label}
192
+ />
193
+ ))}
194
+ </div>
195
+ );
196
+ },
197
+ parameters: {
198
+ docs: {
199
+ description: {
200
+ story: "Multiple checkboxes in a group.",
201
+ },
202
+ },
203
+ },
204
+ };
205
+
206
+ // All variants showcase
207
+ export const AllVariants: Story = {
208
+ render: () => (
209
+ <div className="space-y-6">
210
+ <div>
211
+ <h3 className="mb-3 text-lg font-semibold">States</h3>
212
+ <div className="space-y-3">
213
+ <Checkbox checked={false} label="Unchecked" />
214
+ <Checkbox checked={true} label="Checked" />
215
+ <Checkbox checked={false} label="Disabled" disabled />
216
+ <Checkbox checked={true} label="Disabled Checked" disabled />
217
+ </div>
218
+ </div>
219
+ <div>
220
+ <h3 className="mb-3 text-lg font-semibold">With Error</h3>
221
+ <Checkbox checked={false} label="Error State" error />
222
+ </div>
223
+ <div>
224
+ <h3 className="mb-3 text-lg font-semibold">Required</h3>
225
+ <Checkbox checked={false} label="Required Field" required />
226
+ </div>
227
+ <div>
228
+ <h3 className="mb-3 text-lg font-semibold">With Info Icon</h3>
229
+ <Checkbox
230
+ checked={false}
231
+ label="With Info Icon"
232
+ renderInfoIcon={{
233
+ onClick: () => {},
234
+ dataTestId: "info",
235
+ }}
236
+ />
237
+ </div>
238
+ </div>
239
+ ),
240
+ parameters: {
241
+ docs: {
242
+ description: {
243
+ story: "Showcase of all checkbox variants and states.",
244
+ },
245
+ },
246
+ },
247
+ };
248
+