@a2v2ai/uikit 0.0.1 → 0.0.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.
Files changed (148) hide show
  1. package/Alert/Alert.stories.tsx +121 -0
  2. package/Alert/Alert.tsx +71 -0
  3. package/AlertDialog/AlertDialog.stories.tsx +665 -0
  4. package/AlertDialog/AlertDialog.tsx +241 -0
  5. package/Avatar/Avatar.stories.tsx +128 -0
  6. package/Avatar/Avatar.tsx +71 -0
  7. package/Badge/Badge.stories.tsx +76 -0
  8. package/Badge/Badge.tsx +39 -0
  9. package/Breadcrumb/Breadcrumb.stories.tsx +231 -0
  10. package/Breadcrumb/Breadcrumb.tsx +114 -0
  11. package/Button/Button.stories.tsx +684 -0
  12. package/Button/Button.tsx +90 -0
  13. package/Calendar/Calendar.stories.tsx +207 -0
  14. package/Calendar/Calendar.tsx +232 -0
  15. package/Card/Card.stories.tsx +136 -0
  16. package/Card/Card.tsx +96 -0
  17. package/ChatBubble/ChatBubble.stories.tsx +307 -0
  18. package/ChatBubble/ChatBubble.tsx +167 -0
  19. package/Checkbox/Checkbox.stories.tsx +137 -0
  20. package/Checkbox/Checkbox.tsx +53 -0
  21. package/Drawer/Drawer.stories.tsx +721 -0
  22. package/Drawer/Drawer.tsx +201 -0
  23. package/DropdownMenu/DropdownMenu.stories.tsx +251 -0
  24. package/DropdownMenu/DropdownMenu.tsx +199 -0
  25. package/ErrorMessage/ErrorMessage.stories.tsx +159 -0
  26. package/ErrorMessage/ErrorMessage.tsx +55 -0
  27. package/Flex/Flex.tsx +102 -0
  28. package/IconButton/IconButton.stories.tsx +566 -0
  29. package/IconButton/IconButton.tsx +95 -0
  30. package/Input/Input.stories.tsx +456 -0
  31. package/Input/Input.tsx +129 -0
  32. package/InputOTP/InputOTP.stories.tsx +246 -0
  33. package/InputOTP/InputOTP.tsx +127 -0
  34. package/Label/Label.stories.tsx +105 -0
  35. package/Label/Label.tsx +43 -0
  36. package/Loader/Loader.stories.tsx +170 -0
  37. package/Loader/Loader.tsx +62 -0
  38. package/Popover/Popover.stories.tsx +133 -0
  39. package/Popover/Popover.tsx +31 -0
  40. package/Progress/Progress.stories.tsx +146 -0
  41. package/Progress/Progress.tsx +67 -0
  42. package/README.md +12 -12
  43. package/RadioGroup/RadioGroup.stories.tsx +159 -0
  44. package/RadioGroup/RadioGroup.tsx +68 -0
  45. package/ScrollArea/ScrollArea.stories.tsx +136 -0
  46. package/ScrollArea/ScrollArea.tsx +46 -0
  47. package/Select/Select.stories.tsx +242 -0
  48. package/Select/Select.tsx +180 -0
  49. package/Separator/Separator.stories.tsx +110 -0
  50. package/Separator/Separator.tsx +29 -0
  51. package/Skeleton/Skeleton.stories.tsx +117 -0
  52. package/Skeleton/Skeleton.tsx +16 -0
  53. package/Spinner/Spinner.stories.tsx +210 -0
  54. package/Spinner/Spinner.tsx +78 -0
  55. package/Switch/Switch.stories.tsx +146 -0
  56. package/Switch/Switch.tsx +59 -0
  57. package/Tabs/Tabs.stories.tsx +197 -0
  58. package/Tabs/Tabs.tsx +74 -0
  59. package/Textarea/Textarea.stories.tsx +170 -0
  60. package/Textarea/Textarea.tsx +51 -0
  61. package/Toast/Toast.stories.tsx +285 -0
  62. package/Toast/Toast.tsx +59 -0
  63. package/Tooltip/Tooltip.stories.tsx +463 -0
  64. package/Tooltip/Tooltip.tsx +96 -0
  65. package/Typography/Typography.stories.tsx +235 -0
  66. package/Typography/Typography.tsx +171 -0
  67. package/helpers.ts +5 -0
  68. package/icons.ts +2 -0
  69. package/index.ts +136 -0
  70. package/lib/utils.ts +15 -0
  71. package/package.json +4 -1
  72. package/tsconfig.json +24 -0
  73. package/Alert/Alert.d.ts +0 -11
  74. package/Alert/Alert.js +0 -64
  75. package/AlertDialog/AlertDialog.d.ts +0 -35
  76. package/AlertDialog/AlertDialog.js +0 -121
  77. package/Avatar/Avatar.d.ts +0 -12
  78. package/Avatar/Avatar.js +0 -64
  79. package/Badge/Badge.d.ts +0 -9
  80. package/Badge/Badge.js +0 -26
  81. package/Breadcrumb/Breadcrumb.d.ts +0 -19
  82. package/Breadcrumb/Breadcrumb.js +0 -65
  83. package/Button/Button.d.ts +0 -14
  84. package/Button/Button.js +0 -75
  85. package/Calendar/Calendar.d.ts +0 -16
  86. package/Calendar/Calendar.js +0 -113
  87. package/Card/Card.d.ts +0 -14
  88. package/Card/Card.js +0 -70
  89. package/ChatBubble/ChatBubble.d.ts +0 -29
  90. package/ChatBubble/ChatBubble.js +0 -133
  91. package/Checkbox/Checkbox.d.ts +0 -10
  92. package/Checkbox/Checkbox.js +0 -57
  93. package/Dialog/Dialog.d.ts +0 -35
  94. package/Dialog/Dialog.js +0 -130
  95. package/Drawer/Drawer.d.ts +0 -31
  96. package/Drawer/Drawer.js +0 -69
  97. package/DropdownMenu/DropdownMenu.d.ts +0 -27
  98. package/DropdownMenu/DropdownMenu.js +0 -85
  99. package/ErrorMessage/ErrorMessage.d.ts +0 -27
  100. package/ErrorMessage/ErrorMessage.js +0 -15
  101. package/Flex/Flex.d.ts +0 -23
  102. package/Flex/Flex.js +0 -101
  103. package/IconButton/IconButton.d.ts +0 -17
  104. package/IconButton/IconButton.js +0 -85
  105. package/Input/Input.d.ts +0 -16
  106. package/Input/Input.js +0 -75
  107. package/InputOTP/InputOTP.d.ts +0 -18
  108. package/InputOTP/InputOTP.js +0 -85
  109. package/Label/Label.d.ts +0 -10
  110. package/Label/Label.js +0 -57
  111. package/Loader/Loader.d.ts +0 -18
  112. package/Loader/Loader.js +0 -67
  113. package/Popover/Popover.d.ts +0 -7
  114. package/Popover/Popover.js +0 -49
  115. package/Progress/Progress.d.ts +0 -13
  116. package/Progress/Progress.js +0 -71
  117. package/RadioGroup/RadioGroup.d.ts +0 -11
  118. package/RadioGroup/RadioGroup.js +0 -64
  119. package/ScrollArea/ScrollArea.d.ts +0 -5
  120. package/ScrollArea/ScrollArea.js +0 -48
  121. package/Select/Select.d.ts +0 -19
  122. package/Select/Select.js +0 -85
  123. package/Separator/Separator.d.ts +0 -4
  124. package/Separator/Separator.js +0 -43
  125. package/Skeleton/Skeleton.d.ts +0 -4
  126. package/Skeleton/Skeleton.js +0 -8
  127. package/Spinner/Spinner.d.ts +0 -15
  128. package/Spinner/Spinner.js +0 -68
  129. package/Switch/Switch.d.ts +0 -10
  130. package/Switch/Switch.js +0 -67
  131. package/Tabs/Tabs.d.ts +0 -13
  132. package/Tabs/Tabs.js +0 -64
  133. package/Textarea/Textarea.d.ts +0 -10
  134. package/Textarea/Textarea.js +0 -64
  135. package/Toast/Toast.d.ts +0 -10
  136. package/Toast/Toast.js +0 -29
  137. package/Tooltip/Tooltip.d.ts +0 -15
  138. package/Tooltip/Tooltip.js +0 -68
  139. package/Typography/Typography.d.ts +0 -15
  140. package/Typography/Typography.js +0 -125
  141. package/helpers.d.ts +0 -4
  142. package/helpers.js +0 -13
  143. package/icons.d.ts +0 -1
  144. package/icons.js +0 -18
  145. package/index.d.ts +0 -35
  146. package/index.js +0 -183
  147. package/lib/utils.d.ts +0 -3
  148. package/lib/utils.js +0 -18
package/Card/Card.tsx ADDED
@@ -0,0 +1,96 @@
1
+ import * as React from "react"
2
+ import { cva } from "class-variance-authority"
3
+
4
+ import { cn } from "../lib/utils"
5
+
6
+ type CardVariant = "default" | "outline"
7
+
8
+ const cardVariants = cva(
9
+ "rounded-xl border bg-white text-main-950 shadow-sm",
10
+ {
11
+ variants: {
12
+ variant: {
13
+ default: "border-grey-200",
14
+ outline: "border-grey-300 shadow-none",
15
+ },
16
+ },
17
+ defaultVariants: {
18
+ variant: "default",
19
+ },
20
+ }
21
+ )
22
+
23
+ export interface CardProps
24
+ extends React.HTMLAttributes<HTMLDivElement> {
25
+ variant?: CardVariant
26
+ }
27
+
28
+ const Card = React.forwardRef<HTMLDivElement, CardProps>(
29
+ ({ className, variant, ...props }, ref) => (
30
+ <div
31
+ ref={ref}
32
+ className={cn(cardVariants({ variant }), className)}
33
+ {...props}
34
+ />
35
+ )
36
+ )
37
+ Card.displayName = "Card"
38
+
39
+ const CardHeader = React.forwardRef<
40
+ HTMLDivElement,
41
+ React.HTMLAttributes<HTMLDivElement>
42
+ >(({ className, ...props }, ref) => (
43
+ <div
44
+ ref={ref}
45
+ className={cn("flex flex-col space-y-1.5 p-6", className)}
46
+ {...props}
47
+ />
48
+ ))
49
+ CardHeader.displayName = "CardHeader"
50
+
51
+ const CardTitle = React.forwardRef<
52
+ HTMLDivElement,
53
+ React.HTMLAttributes<HTMLDivElement>
54
+ >(({ className, ...props }, ref) => (
55
+ <div
56
+ ref={ref}
57
+ className={cn("font-semibold leading-none tracking-tight", className)}
58
+ {...props}
59
+ />
60
+ ))
61
+ CardTitle.displayName = "CardTitle"
62
+
63
+ const CardDescription = React.forwardRef<
64
+ HTMLDivElement,
65
+ React.HTMLAttributes<HTMLDivElement>
66
+ >(({ className, ...props }, ref) => (
67
+ <div
68
+ ref={ref}
69
+ className={cn("text-sm text-grey-500", className)}
70
+ {...props}
71
+ />
72
+ ))
73
+ CardDescription.displayName = "CardDescription"
74
+
75
+ const CardContent = React.forwardRef<
76
+ HTMLDivElement,
77
+ React.HTMLAttributes<HTMLDivElement>
78
+ >(({ className, ...props }, ref) => (
79
+ <div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
80
+ ))
81
+ CardContent.displayName = "CardContent"
82
+
83
+ const CardFooter = React.forwardRef<
84
+ HTMLDivElement,
85
+ React.HTMLAttributes<HTMLDivElement>
86
+ >(({ className, ...props }, ref) => (
87
+ <div
88
+ ref={ref}
89
+ className={cn("flex items-center p-6 pt-0", className)}
90
+ {...props}
91
+ />
92
+ ))
93
+ CardFooter.displayName = "CardFooter"
94
+
95
+ export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent, cardVariants }
96
+ export type { CardVariant }
@@ -0,0 +1,307 @@
1
+ import type { Meta, StoryObj } from "@storybook/react"
2
+ import { Flex } from "../Flex/Flex"
3
+ import { Typography } from "../Typography/Typography"
4
+ import { ChatBubble } from "./ChatBubble"
5
+
6
+ const meta: Meta<typeof ChatBubble> = {
7
+ title: "Components/ChatBubble",
8
+ component: ChatBubble,
9
+ parameters: {
10
+ layout: "centered",
11
+ backgrounds: {
12
+ default: "dark",
13
+ values: [
14
+ { name: "dark", value: "#1a1a1a" },
15
+ { name: "light", value: "#ffffff" },
16
+ ],
17
+ },
18
+ },
19
+ tags: ["autodocs"],
20
+ argTypes: {
21
+ side: {
22
+ control: "select",
23
+ options: ["left", "right"],
24
+ description: "The side of the chat bubble",
25
+ },
26
+ color: {
27
+ control: "select",
28
+ options: ["blue", "grey", "green"],
29
+ description: "The color variant of the bubble",
30
+ },
31
+ theme: {
32
+ control: "select",
33
+ options: ["dark", "light"],
34
+ description: "The theme variant",
35
+ },
36
+ size: {
37
+ control: "select",
38
+ options: ["small", "medium", "large", "xlarge"],
39
+ description: "The text size of the bubble",
40
+ },
41
+ label: {
42
+ control: "text",
43
+ description: "Label shown above the bubble",
44
+ },
45
+ showLabel: {
46
+ control: "boolean",
47
+ description: "Whether to show the label",
48
+ },
49
+ },
50
+ }
51
+
52
+ export default meta
53
+ type Story = StoryObj<typeof ChatBubble>
54
+
55
+ export const Default: Story = {
56
+ args: {
57
+ side: "left",
58
+ color: "blue",
59
+ theme: "dark",
60
+ label: "Your name",
61
+ children: "Your message goes here",
62
+ },
63
+ decorators: [
64
+ (Story) => (
65
+ <Flex className="w-[400px]">
66
+ <Story />
67
+ </Flex>
68
+ ),
69
+ ],
70
+ }
71
+
72
+ export const RightSide: Story = {
73
+ args: {
74
+ side: "right",
75
+ color: "blue",
76
+ theme: "dark",
77
+ label: "Your name",
78
+ children: "Your message goes here",
79
+ },
80
+ decorators: [
81
+ (Story) => (
82
+ <Flex className="w-[400px]">
83
+ <Story />
84
+ </Flex>
85
+ ),
86
+ ],
87
+ }
88
+
89
+ export const Grey: Story = {
90
+ args: {
91
+ side: "left",
92
+ color: "grey",
93
+ theme: "dark",
94
+ label: "Your name",
95
+ children: "Your message goes here",
96
+ },
97
+ decorators: [
98
+ (Story) => (
99
+ <Flex className="w-[400px]">
100
+ <Story />
101
+ </Flex>
102
+ ),
103
+ ],
104
+ }
105
+
106
+ export const Green: Story = {
107
+ args: {
108
+ side: "left",
109
+ color: "green",
110
+ theme: "dark",
111
+ label: "Your name",
112
+ children: "Your message goes here",
113
+ },
114
+ decorators: [
115
+ (Story) => (
116
+ <Flex className="w-[400px]">
117
+ <Story />
118
+ </Flex>
119
+ ),
120
+ ],
121
+ }
122
+
123
+ export const LightTheme: Story = {
124
+ args: {
125
+ side: "left",
126
+ color: "blue",
127
+ theme: "light",
128
+ label: "Your name",
129
+ children: "Your message goes here",
130
+ },
131
+ parameters: {
132
+ backgrounds: { default: "light" },
133
+ },
134
+ decorators: [
135
+ (Story) => (
136
+ <Flex className="w-[400px]">
137
+ <Story />
138
+ </Flex>
139
+ ),
140
+ ],
141
+ }
142
+
143
+ export const GreyLight: Story = {
144
+ args: {
145
+ side: "left",
146
+ color: "grey",
147
+ theme: "light",
148
+ label: "Your name",
149
+ children: "Your message goes here",
150
+ },
151
+ parameters: {
152
+ backgrounds: { default: "light" },
153
+ },
154
+ decorators: [
155
+ (Story) => (
156
+ <Flex className="w-[400px]">
157
+ <Story />
158
+ </Flex>
159
+ ),
160
+ ],
161
+ }
162
+
163
+ export const NoLabel: Story = {
164
+ args: {
165
+ side: "left",
166
+ color: "blue",
167
+ theme: "dark",
168
+ showLabel: false,
169
+ children: "Message without a label",
170
+ },
171
+ decorators: [
172
+ (Story) => (
173
+ <Flex className="w-[400px]">
174
+ <Story />
175
+ </Flex>
176
+ ),
177
+ ],
178
+ }
179
+
180
+ export const LongMessage: Story = {
181
+ args: {
182
+ side: "left",
183
+ color: "blue",
184
+ theme: "dark",
185
+ label: "Your name",
186
+ children:
187
+ "This is a longer message that demonstrates how the chat bubble handles multiple lines of text. The bubble should expand to accommodate the content while maintaining proper padding and border radius.",
188
+ },
189
+ decorators: [
190
+ (Story) => (
191
+ <Flex className="w-[400px]">
192
+ <Story />
193
+ </Flex>
194
+ ),
195
+ ],
196
+ }
197
+
198
+ // Conversation example
199
+ export const Conversation: Story = {
200
+ render: () => (
201
+ <Flex direction="column" gap={4} className="w-[400px]">
202
+ <ChatBubble side="left" color="grey" theme="dark" label="Alice">
203
+ Hey! How are you doing?
204
+ </ChatBubble>
205
+ <ChatBubble side="right" color="blue" theme="dark" label="You">
206
+ I'm doing great, thanks for asking!
207
+ </ChatBubble>
208
+ <ChatBubble side="left" color="grey" theme="dark" label="Alice">
209
+ That's wonderful to hear. Want to grab lunch later?
210
+ </ChatBubble>
211
+ <ChatBubble side="right" color="green" theme="dark" label="You">
212
+ Sounds perfect! See you at noon.
213
+ </ChatBubble>
214
+ </Flex>
215
+ ),
216
+ }
217
+
218
+ // All Variants
219
+ export const AllVariants: Story = {
220
+ render: () => (
221
+ <Flex direction="column" gap={8}>
222
+ {/* Dark Theme */}
223
+ <Flex direction="column" gap={4}>
224
+ <Typography variant="h4" className="text-white">Dark Theme</Typography>
225
+ <Flex gap={4}>
226
+ {/* Left side variants */}
227
+ <Flex direction="column" gap={4}>
228
+ <ChatBubble side="left" color="blue" theme="dark" label="Blue Left">
229
+ Your message goes here
230
+ </ChatBubble>
231
+ <ChatBubble side="left" color="grey" theme="dark" label="Grey Left">
232
+ Your message goes here
233
+ </ChatBubble>
234
+ <ChatBubble side="left" color="green" theme="dark" label="Green Left">
235
+ Your message goes here
236
+ </ChatBubble>
237
+ </Flex>
238
+ {/* Right side variants */}
239
+ <Flex direction="column" gap={4}>
240
+ <ChatBubble side="right" color="blue" theme="dark" label="Blue Right">
241
+ Your message goes here
242
+ </ChatBubble>
243
+ <ChatBubble side="right" color="grey" theme="dark" label="Grey Right">
244
+ Your message goes here
245
+ </ChatBubble>
246
+ <ChatBubble side="right" color="green" theme="dark" label="Green Right">
247
+ Your message goes here
248
+ </ChatBubble>
249
+ </Flex>
250
+ </Flex>
251
+ </Flex>
252
+
253
+ {/* Light Theme */}
254
+ <Flex direction="column" gap={4} className="bg-white p-6 rounded-lg">
255
+ <Typography variant="h4">Light Theme</Typography>
256
+ <Flex gap={4}>
257
+ {/* Left side variants */}
258
+ <Flex direction="column" gap={4}>
259
+ <ChatBubble side="left" color="blue" theme="light" label="Blue Left">
260
+ Your message goes here
261
+ </ChatBubble>
262
+ <ChatBubble side="left" color="grey" theme="light" label="Grey Left">
263
+ Your message goes here
264
+ </ChatBubble>
265
+ <ChatBubble side="left" color="green" theme="light" label="Green Left">
266
+ Your message goes here
267
+ </ChatBubble>
268
+ </Flex>
269
+ {/* Right side variants */}
270
+ <Flex direction="column" gap={4}>
271
+ <ChatBubble side="right" color="blue" theme="light" label="Blue Right">
272
+ Your message goes here
273
+ </ChatBubble>
274
+ <ChatBubble side="right" color="grey" theme="light" label="Grey Right">
275
+ Your message goes here
276
+ </ChatBubble>
277
+ <ChatBubble side="right" color="green" theme="light" label="Green Right">
278
+ Your message goes here
279
+ </ChatBubble>
280
+ </Flex>
281
+ </Flex>
282
+ </Flex>
283
+
284
+ {/* Sizes */}
285
+ <Flex direction="column" gap={4}>
286
+ <Typography variant="h4" className="text-white">Sizes</Typography>
287
+ <Flex direction="column" gap={2} className="w-[400px]">
288
+ <ChatBubble side="left" color="blue" theme="dark" size="small" label="Small">
289
+ Small text size
290
+ </ChatBubble>
291
+ <ChatBubble side="left" color="blue" theme="dark" size="medium" label="Medium">
292
+ Medium text size
293
+ </ChatBubble>
294
+ <ChatBubble side="left" color="blue" theme="dark" size="large" label="Large">
295
+ Large text size
296
+ </ChatBubble>
297
+ <ChatBubble side="left" color="blue" theme="dark" size="xlarge" label="XLarge">
298
+ Extra large text size
299
+ </ChatBubble>
300
+ </Flex>
301
+ </Flex>
302
+ </Flex>
303
+ ),
304
+ parameters: {
305
+ layout: "padded",
306
+ },
307
+ }
@@ -0,0 +1,167 @@
1
+ import * as React from "react"
2
+ import { cva } from "class-variance-authority"
3
+
4
+ import { cn } from "../lib/utils"
5
+
6
+ type ChatBubbleSide = "left" | "right"
7
+ type ChatBubbleColor = "blue" | "grey" | "green"
8
+ type ChatBubbleTheme = "dark" | "light"
9
+ type ChatBubbleSize = "small" | "medium" | "large" | "xlarge"
10
+
11
+ const chatBubbleVariants = cva(
12
+ "flex flex-col gap-1.5 w-full",
13
+ {
14
+ variants: {
15
+ side: {
16
+ left: "items-start",
17
+ right: "items-end",
18
+ },
19
+ },
20
+ defaultVariants: {
21
+ side: "left",
22
+ },
23
+ }
24
+ )
25
+
26
+ const bubbleContentVariants = cva(
27
+ "px-4 py-3 font-medium leading-normal max-w-[85%]",
28
+ {
29
+ variants: {
30
+ color: {
31
+ blue: "bg-blue-500",
32
+ grey: "",
33
+ green: "bg-green-500",
34
+ },
35
+ theme: {
36
+ dark: "",
37
+ light: "",
38
+ },
39
+ side: {
40
+ left: "rounded-2xl rounded-bl-md",
41
+ right: "rounded-2xl rounded-br-md",
42
+ },
43
+ size: {
44
+ small: "text-sm px-3 py-2",
45
+ medium: "text-base px-4 py-3",
46
+ large: "text-lg px-4 py-3",
47
+ xlarge: "text-xl px-5 py-4",
48
+ },
49
+ },
50
+ compoundVariants: [
51
+ // Blue variants
52
+ {
53
+ color: "blue",
54
+ theme: "dark",
55
+ className: "bg-blue-500 text-white",
56
+ },
57
+ {
58
+ color: "blue",
59
+ theme: "light",
60
+ className: "bg-[#2e9dfb] text-white",
61
+ },
62
+ // Grey variants
63
+ {
64
+ color: "grey",
65
+ theme: "dark",
66
+ className: "bg-[#232323] text-white",
67
+ },
68
+ {
69
+ color: "grey",
70
+ theme: "light",
71
+ className: "bg-[#e7e7e7] text-neutral-900",
72
+ },
73
+ // Green variants
74
+ {
75
+ color: "green",
76
+ theme: "dark",
77
+ className: "bg-green-500 text-white",
78
+ },
79
+ {
80
+ color: "green",
81
+ theme: "light",
82
+ className: "bg-green-500 text-white",
83
+ },
84
+ ],
85
+ defaultVariants: {
86
+ color: "blue",
87
+ theme: "dark",
88
+ side: "left",
89
+ size: "small",
90
+ },
91
+ }
92
+ )
93
+
94
+ const labelVariants = cva(
95
+ "text-sm text-neutral-400 mb-0.5",
96
+ {
97
+ variants: {
98
+ side: {
99
+ left: "ml-3",
100
+ right: "mr-3",
101
+ },
102
+ },
103
+ defaultVariants: {
104
+ side: "left",
105
+ },
106
+ }
107
+ )
108
+
109
+ export interface ChatBubbleProps
110
+ extends React.HTMLAttributes<HTMLDivElement> {
111
+ /** The side of the chat bubble (left for received, right for sent) */
112
+ side?: ChatBubbleSide
113
+ /** The color variant of the bubble */
114
+ color?: ChatBubbleColor
115
+ /** The theme variant */
116
+ theme?: ChatBubbleTheme
117
+ /** The text size of the bubble */
118
+ size?: ChatBubbleSize
119
+ /** The message content */
120
+ children: React.ReactNode
121
+ /** Optional label shown above the bubble (e.g., sender name) */
122
+ label?: string
123
+ /** Whether to show the label */
124
+ showLabel?: boolean
125
+ }
126
+
127
+ const ChatBubble = React.forwardRef<HTMLDivElement, ChatBubbleProps>(
128
+ (
129
+ {
130
+ className,
131
+ side = "left",
132
+ color = "blue",
133
+ theme = "dark",
134
+ size = "small",
135
+ children,
136
+ label,
137
+ showLabel = true,
138
+ ...props
139
+ },
140
+ ref
141
+ ) => {
142
+ return (
143
+ <div
144
+ ref={ref}
145
+ className={cn(chatBubbleVariants({ side, className }))}
146
+ {...props}
147
+ >
148
+ {showLabel && label && (
149
+ <span className={cn(labelVariants({ side }))}>
150
+ {label}
151
+ </span>
152
+ )}
153
+ <div
154
+ className={cn(
155
+ bubbleContentVariants({ color, theme, side, size })
156
+ )}
157
+ >
158
+ {children}
159
+ </div>
160
+ </div>
161
+ )
162
+ }
163
+ )
164
+ ChatBubble.displayName = "ChatBubble"
165
+
166
+ export { ChatBubble, chatBubbleVariants, bubbleContentVariants }
167
+ export type { ChatBubbleSide, ChatBubbleColor, ChatBubbleTheme, ChatBubbleSize }
@@ -0,0 +1,137 @@
1
+ import type { Meta, StoryObj } from "@storybook/react"
2
+ import { useState } from "react"
3
+
4
+ import { Label } from "../Label/Label"
5
+ import { Flex } from "../Flex/Flex"
6
+ import { Typography } from "../Typography/Typography"
7
+ import { Checkbox } from "./Checkbox"
8
+
9
+ function IndeterminateExample() {
10
+ const [checked, setChecked] = useState<boolean | "indeterminate">("indeterminate")
11
+ return (
12
+ <Flex align="center" gap={2}>
13
+ <Checkbox
14
+ id="indeterminate"
15
+ checked={checked}
16
+ onCheckedChange={(value) => setChecked(value)}
17
+ />
18
+ <Label htmlFor="indeterminate">Indeterminate</Label>
19
+ </Flex>
20
+ )
21
+ }
22
+
23
+ const meta: Meta<typeof Checkbox> = {
24
+ title: "Components/Checkbox",
25
+ component: Checkbox,
26
+ parameters: {
27
+ layout: "centered",
28
+ },
29
+ argTypes: {
30
+ size: {
31
+ control: "select",
32
+ options: ["small", "regular"],
33
+ description: "The size of the checkbox",
34
+ },
35
+ checked: {
36
+ control: "boolean",
37
+ description: "The checked state",
38
+ },
39
+ disabled: {
40
+ control: "boolean",
41
+ description: "Whether the checkbox is disabled",
42
+ },
43
+ },
44
+ tags: ["autodocs"],
45
+ }
46
+
47
+ export default meta
48
+ type Story = StoryObj<typeof meta>
49
+
50
+ export const Default: Story = {
51
+ render: () => <Checkbox />,
52
+ }
53
+
54
+ export const Checked: Story = {
55
+ render: () => <Checkbox defaultChecked />,
56
+ }
57
+
58
+ export const WithLabel: Story = {
59
+ render: () => (
60
+ <Flex align="center" gap={2}>
61
+ <Checkbox id="terms" />
62
+ <Label htmlFor="terms">Accept terms and conditions</Label>
63
+ </Flex>
64
+ ),
65
+ }
66
+
67
+ export const Disabled: Story = {
68
+ render: () => (
69
+ <Flex direction="column" gap={3}>
70
+ <Flex align="center" gap={2}>
71
+ <Checkbox id="disabled" disabled />
72
+ <Label htmlFor="disabled" className="opacity-50">Disabled</Label>
73
+ </Flex>
74
+ <Flex align="center" gap={2}>
75
+ <Checkbox id="disabled-checked" disabled defaultChecked />
76
+ <Label htmlFor="disabled-checked" className="opacity-50">Disabled checked</Label>
77
+ </Flex>
78
+ </Flex>
79
+ ),
80
+ }
81
+
82
+ export const Indeterminate: Story = {
83
+ render: () => <IndeterminateExample />,
84
+ }
85
+
86
+ export const Small: Story = {
87
+ render: () => (
88
+ <Flex align="center" gap={2}>
89
+ <Checkbox id="small" size="small" />
90
+ <Label htmlFor="small" className="text-sm">Small checkbox</Label>
91
+ </Flex>
92
+ ),
93
+ }
94
+
95
+ export const AllVariants: Story = {
96
+ render: () => (
97
+ <Flex direction="column" gap={6}>
98
+ <Typography variant="h4" className="text-white">Checkbox States</Typography>
99
+
100
+ <Flex direction="column" gap={4}>
101
+ <Flex align="center" gap={2}>
102
+ <Checkbox id="unchecked" />
103
+ <Label htmlFor="unchecked">Unchecked</Label>
104
+ </Flex>
105
+
106
+ <Flex align="center" gap={2}>
107
+ <Checkbox id="checked" defaultChecked />
108
+ <Label htmlFor="checked">Checked</Label>
109
+ </Flex>
110
+
111
+ <Flex align="center" gap={2}>
112
+ <Checkbox id="disabled-state" disabled />
113
+ <Label htmlFor="disabled-state" className="opacity-50">Disabled</Label>
114
+ </Flex>
115
+
116
+ <Flex align="center" gap={2}>
117
+ <Checkbox id="disabled-checked-state" disabled defaultChecked />
118
+ <Label htmlFor="disabled-checked-state" className="opacity-50">Disabled Checked</Label>
119
+ </Flex>
120
+ </Flex>
121
+
122
+ <Typography variant="h4" className="text-white mt-4">Sizes</Typography>
123
+
124
+ <Flex direction="column" gap={4}>
125
+ <Flex align="center" gap={2}>
126
+ <Checkbox id="small-size" size="small" defaultChecked />
127
+ <Label htmlFor="small-size" className="text-sm">Small</Label>
128
+ </Flex>
129
+
130
+ <Flex align="center" gap={2}>
131
+ <Checkbox id="regular-size" size="regular" defaultChecked />
132
+ <Label htmlFor="regular-size">Regular</Label>
133
+ </Flex>
134
+ </Flex>
135
+ </Flex>
136
+ ),
137
+ }