@bronzelabs/oakma-ui 0.0.1 → 0.0.2

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 (123) hide show
  1. package/dist/index.d.ts +345 -0
  2. package/dist/index.js +1 -0
  3. package/dist/oakma-ui.css +2 -0
  4. package/package.json +6 -2
  5. package/.prettierrc.cjs +0 -25
  6. package/.storybook/components/ActionButton.tsx +0 -44
  7. package/.storybook/components/DummyIcons.tsx +0 -47
  8. package/.storybook/components/index.ts +0 -2
  9. package/.storybook/docs/blocks/ImportStatement.tsx +0 -52
  10. package/.storybook/docs/blocks/index.ts +0 -1
  11. package/.storybook/docs/page.tsx +0 -41
  12. package/.storybook/main.ts +0 -21
  13. package/.storybook/postcss.config.cjs +0 -8
  14. package/.storybook/preview-body.html +0 -20
  15. package/.storybook/preview-head.html +0 -6
  16. package/.storybook/preview.tsx +0 -30
  17. package/.storybook/tailwind.css +0 -6
  18. package/.storybook/utils/index.ts +0 -2
  19. package/.storybook/utils/renderAsReact.tsx +0 -30
  20. package/.storybook/utils/renderDocsWithProps.tsx +0 -22
  21. package/@types/markdown.d.ts +0 -4
  22. package/eslint.config.js +0 -91
  23. package/postcss.config.cjs +0 -8
  24. package/scripts/release.sh +0 -76
  25. package/src/components/Button/Button.stories.tsx +0 -314
  26. package/src/components/Button/Button.tsx +0 -132
  27. package/src/components/Button/index.ts +0 -2
  28. package/src/components/Button/types.ts +0 -19
  29. package/src/components/Checkbox/Checkbox.stories.tsx +0 -152
  30. package/src/components/Checkbox/Checkbox.tsx +0 -90
  31. package/src/components/Checkbox/index.ts +0 -2
  32. package/src/components/Checkbox/types.ts +0 -6
  33. package/src/components/Chip/Chip.stories.tsx +0 -146
  34. package/src/components/Chip/Chip.tsx +0 -59
  35. package/src/components/Chip/index.ts +0 -2
  36. package/src/components/Chip/types.ts +0 -6
  37. package/src/components/Drawer/Drawer.docs.md +0 -88
  38. package/src/components/Drawer/Drawer.stories.tsx +0 -239
  39. package/src/components/Drawer/Drawer.tsx +0 -194
  40. package/src/components/Drawer/index.ts +0 -3
  41. package/src/components/Drawer/types.ts +0 -3
  42. package/src/components/Dropdown/AsyncDropdown.tsx +0 -105
  43. package/src/components/Dropdown/Dropdown.docs.md +0 -33
  44. package/src/components/Dropdown/Dropdown.stories.tsx +0 -419
  45. package/src/components/Dropdown/Dropdown.tsx +0 -104
  46. package/src/components/Dropdown/MultiValue.tsx +0 -19
  47. package/src/components/Dropdown/ValueContainer.tsx +0 -114
  48. package/src/components/Dropdown/index.ts +0 -4
  49. package/src/components/Dropdown/types.ts +0 -29
  50. package/src/components/Dropdown/useDropdown.tsx +0 -257
  51. package/src/components/Logo/Logo.stories.tsx +0 -130
  52. package/src/components/Logo/Logo.tsx +0 -80
  53. package/src/components/Logo/index.ts +0 -2
  54. package/src/components/Modal/Modal.docs.md +0 -94
  55. package/src/components/Modal/Modal.stories.tsx +0 -318
  56. package/src/components/Modal/Modal.tsx +0 -217
  57. package/src/components/Modal/index.ts +0 -1
  58. package/src/components/MultiSelect/AsyncMultiSelect.tsx +0 -47
  59. package/src/components/MultiSelect/MultiSelect.docs.md +0 -37
  60. package/src/components/MultiSelect/MultiSelect.stories.tsx +0 -493
  61. package/src/components/MultiSelect/MultiSelect.tsx +0 -81
  62. package/src/components/MultiSelect/index.ts +0 -2
  63. package/src/components/Notification/Notification.stories.tsx +0 -158
  64. package/src/components/Notification/Notification.tsx +0 -110
  65. package/src/components/Notification/index.ts +0 -1
  66. package/src/components/Notification/types.ts +0 -11
  67. package/src/components/Notifications/Notifications.docs.md +0 -103
  68. package/src/components/Notifications/Notifications.stories.tsx +0 -159
  69. package/src/components/Notifications/Notifications.tsx +0 -90
  70. package/src/components/Notifications/NotificationsContext.tsx +0 -90
  71. package/src/components/Notifications/index.ts +0 -7
  72. package/src/components/Select/Select.stories.tsx +0 -234
  73. package/src/components/Select/Select.tsx +0 -129
  74. package/src/components/Select/index.ts +0 -2
  75. package/src/components/Select/types.ts +0 -1
  76. package/src/components/Spinner/Spinner.stories.tsx +0 -55
  77. package/src/components/Spinner/Spinner.tsx +0 -48
  78. package/src/components/Spinner/index.ts +0 -2
  79. package/src/components/Spinner/types.ts +0 -8
  80. package/src/components/TextArea/TextArea.stories.tsx +0 -243
  81. package/src/components/TextArea/TextArea.tsx +0 -133
  82. package/src/components/TextArea/index.ts +0 -2
  83. package/src/components/TextArea/types.ts +0 -4
  84. package/src/components/TextField/Container.tsx +0 -68
  85. package/src/components/TextField/ErrorMessage.tsx +0 -37
  86. package/src/components/TextField/Icon.tsx +0 -77
  87. package/src/components/TextField/Label.tsx +0 -56
  88. package/src/components/TextField/NotchBorder.tsx +0 -67
  89. package/src/components/TextField/index.ts +0 -14
  90. package/src/components/TextField/types.ts +0 -15
  91. package/src/components/TextField/useInputKeyboardFocus.tsx +0 -63
  92. package/src/components/TextInput/TextInput.stories.tsx +0 -384
  93. package/src/components/TextInput/TextInput.tsx +0 -255
  94. package/src/components/TextInput/index.ts +0 -2
  95. package/src/components/TextInput/types.ts +0 -4
  96. package/src/components/Toggle/Toggle.stories.tsx +0 -142
  97. package/src/components/Toggle/Toggle.tsx +0 -69
  98. package/src/components/Toggle/index.ts +0 -1
  99. package/src/hooks/index.ts +0 -6
  100. package/src/hooks/useCombinedRefs.ts +0 -37
  101. package/src/hooks/useEventListener.ts +0 -87
  102. package/src/hooks/useFocusTrap/createAriaHider.ts +0 -62
  103. package/src/hooks/useFocusTrap/index.ts +0 -1
  104. package/src/hooks/useFocusTrap/scopeTab.ts +0 -46
  105. package/src/hooks/useFocusTrap/tabbable.ts +0 -107
  106. package/src/hooks/useFocusTrap/useFocusTrap.ts +0 -97
  107. package/src/hooks/useIsomorphicLayoutEffect.ts +0 -14
  108. package/src/hooks/useLockBodyScroll.ts +0 -24
  109. package/src/hooks/useOnClickOutside.ts +0 -53
  110. package/src/index.ts +0 -22
  111. package/src/tailwind.css +0 -4
  112. package/src/types/helpers.ts +0 -11
  113. package/src/types/polymorphic.ts +0 -39
  114. package/src/utils/animation/variants.ts +0 -21
  115. package/src/utils/array/index.ts +0 -1
  116. package/src/utils/array/uniqBy.ts +0 -12
  117. package/src/utils/common/index.ts +0 -1
  118. package/src/utils/common/isFunction.ts +0 -17
  119. package/src/utils/react/extractDisplayName.ts +0 -15
  120. package/src/utils/react/index.ts +0 -1
  121. package/tsconfig.json +0 -16
  122. package/tsconfig.production.json +0 -19
  123. package/tsup.config.ts +0 -16
@@ -1,314 +0,0 @@
1
- import React from "react"
2
-
3
- // Components
4
- import Button from "./Button"
5
-
6
- // Types
7
- import type { Meta, StoryFn } from "@storybook/react-webpack5"
8
- import type { ButtonProps } from "./Button"
9
- import { BUTTON_SIZES, BUTTON_VARIANTS } from "./types"
10
-
11
- // Utils
12
- import { DummyPhoneIcon } from "../../../.storybook/components"
13
-
14
- /*
15
-
16
-
17
-
18
-
19
-
20
- */
21
-
22
- const meta: Meta<ButtonProps<"button"> | ButtonProps<"a">> = {
23
- title: "Components/Button",
24
- component: Button,
25
- parameters: {
26
- docs: {
27
- description: {
28
- component: "A standard button and or link for common UI interactions.",
29
- },
30
- },
31
- controls: {
32
- exclude: ["className", "onClick"],
33
- },
34
- },
35
- argTypes: {
36
- size: {
37
- type: "string",
38
- description: "Size of the Button.",
39
- table: {
40
- type: {
41
- summary: Object.keys(BUTTON_SIZES)
42
- .map(s => `"${s}"`)
43
- .join("|"),
44
- },
45
- defaultValue: {
46
- summary: `"lg"`,
47
- },
48
- },
49
- options: Object.keys(BUTTON_SIZES),
50
- control: { type: "select" },
51
- },
52
- variant: {
53
- type: "string",
54
- description: "Style of the Button.",
55
- table: {
56
- type: {
57
- summary: Object.keys(BUTTON_VARIANTS)
58
- .map(v => `"${v}"`)
59
- .join("|"),
60
- },
61
- defaultValue: {
62
- summary: `"primary"`,
63
- },
64
- },
65
- options: Object.keys(BUTTON_VARIANTS),
66
- control: { type: "select" },
67
- },
68
- disabled: {
69
- type: "boolean",
70
- description: "Whether the Button should render as disabled.",
71
- table: {
72
- type: {
73
- summary: "boolean",
74
- },
75
- defaultValue: {
76
- summary: "false",
77
- },
78
- },
79
- },
80
- children: {
81
- type: "string",
82
- description:
83
- "The children to render inside the Button *(typically the text you want the Button to diplay)*.",
84
- table: {
85
- type: {
86
- summary: "string | React.ReactNode",
87
- },
88
- defaultValue: {
89
- summary: "undefined",
90
- },
91
- },
92
- },
93
- loading: {
94
- type: "boolean",
95
- description: "Whether the Button should show it's loading state.",
96
- table: {
97
- type: {
98
- summary: "boolean",
99
- },
100
- defaultValue: {
101
- summary: "false",
102
- },
103
- },
104
- },
105
- iconPosition: {
106
- type: "string",
107
- description: "The position of the icon if an icon is provided.",
108
- table: {
109
- type: {
110
- summary: `"left" | "right"`,
111
- },
112
- defaultValue: {
113
- summary: `"left"`,
114
- },
115
- },
116
- options: ["left", "right"],
117
- control: { type: "select" },
118
- },
119
- href: {
120
- type: "string",
121
- description:
122
- "Passing a href prop will result in a link Button being rendered with an <a> DOM node *(and then give access to additional props: `rel`, `target`, `referrerPolicy`)*.",
123
- table: {
124
- type: {
125
- summary: "string",
126
- },
127
- defaultValue: {
128
- summary: "undefined",
129
- },
130
- },
131
- },
132
- },
133
- args: {
134
- size: "lg",
135
- variant: "primary",
136
- as: "button",
137
- disabled: false,
138
- loading: false,
139
- iconPosition: "left",
140
- },
141
- }
142
-
143
- const Template: StoryFn<ButtonProps> = props => <Button {...props} />
144
-
145
- const SizesTemplate: StoryFn<ButtonProps> = args => (
146
- <>
147
- <Button {...args} size="lg">
148
- Large
149
- </Button>
150
- <Button {...args} size="md">
151
- Medium
152
- </Button>
153
- <Button {...args} size="sm">
154
- Small
155
- </Button>
156
- </>
157
- )
158
-
159
- const VariantsTemplate: StoryFn<ButtonProps> = args => (
160
- <>
161
- <Button {...args} variant="primary">
162
- Primary
163
- </Button>
164
- <Button {...args} variant="secondary">
165
- Secondary
166
- </Button>
167
- <div className="-m-1 bg-teal-100 p-1">
168
- <Button {...args} variant="outline-light">
169
- Outline Light
170
- </Button>
171
- </div>
172
- <Button {...args} variant="outline-dark">
173
- Outline Dark
174
- </Button>
175
- <Button {...args} variant="ghost">
176
- Ghost
177
- </Button>
178
- <Button {...args} variant="success">
179
- Success
180
- </Button>
181
- <Button {...args} variant="danger">
182
- Danger
183
- </Button>
184
- </>
185
- )
186
-
187
- const IconsTemplate: StoryFn<ButtonProps> = args => (
188
- <>
189
- <Button {...args} variant="primary">
190
- Primary
191
- </Button>
192
- <Button {...args} size="md" variant="secondary">
193
- Secondary
194
- </Button>
195
- <Button {...args} size="sm" variant="outline-dark">
196
- Outline Dark
197
- </Button>
198
- </>
199
- )
200
-
201
- const IconButtonTemplate: StoryFn<ButtonProps> = args => (
202
- <>
203
- <Button {...args} variant="primary" />
204
- <Button {...args} variant="secondary" />
205
- <div className="-m-1 bg-teal-100 p-1">
206
- <Button {...args} variant="outline-light" />
207
- </div>
208
- <Button {...args} variant="outline-dark" />
209
- <Button {...args} variant="ghost" />
210
- <Button {...args} variant="success" />
211
- <Button {...args} variant="danger" />
212
- </>
213
- )
214
-
215
- const Default = Template.bind({})
216
- const Sizes = SizesTemplate.bind({})
217
- const Variants = VariantsTemplate.bind({})
218
- const Icons = IconsTemplate.bind({})
219
- const IconButton = IconButtonTemplate.bind({})
220
- const Truncated = Template.bind({})
221
- const Disabled = VariantsTemplate.bind({})
222
-
223
- // Args
224
- Default.args = {
225
- children: "Button",
226
- }
227
-
228
- Icons.args = {
229
- icon: <DummyPhoneIcon />,
230
- }
231
-
232
- IconButton.args = {
233
- icon: <DummyPhoneIcon />,
234
- }
235
-
236
- Truncated.args = {
237
- children: "This is a very long button text that should be truncated",
238
- }
239
-
240
- Disabled.args = {
241
- disabled: true,
242
- }
243
-
244
- // Parameters
245
- Sizes.parameters = {
246
- docs: {
247
- description: {
248
- story:
249
- 'Button can be rendered in three different sizes (`"sm"`,`"md"`, `"lg"`). The default size is `"lg"`.',
250
- },
251
- },
252
- }
253
-
254
- Variants.parameters = {
255
- docs: {
256
- description: {
257
- story:
258
- 'Button can be rendered as seven different variants. The default variant is `"primary"`.',
259
- },
260
- },
261
- }
262
-
263
- IconButton.parameters = {
264
- docs: {
265
- description: {
266
- story: "An icon button can be created by passing a valid `icon` prop and no `children`.",
267
- },
268
- },
269
- }
270
-
271
- Disabled.parameters = {
272
- docs: {
273
- description: {
274
- story:
275
- "Passing `disabled={true}` will prevent input events being registered on the Button and result in it's disabled state being rendered.",
276
- },
277
- },
278
- }
279
-
280
- // Decorators
281
- Default.decorators = [
282
- Story => (
283
- <div className="flex flex-wrap items-center gap-6">
284
- <Story />
285
- </div>
286
- ),
287
- ]
288
-
289
- Sizes.decorators = [...Default.decorators]
290
-
291
- Variants.decorators = [
292
- Story => (
293
- <div className="grid grid-cols-4 items-center gap-6">
294
- <Story />
295
- </div>
296
- ),
297
- ]
298
-
299
- Icons.decorators = [...Default.decorators]
300
-
301
- IconButton.decorators = [...Default.decorators]
302
-
303
- Disabled.decorators = [...Variants.decorators]
304
-
305
- Truncated.decorators = [
306
- Story => (
307
- <div className="flex items-center gap-6" style={{ maxWidth: 164 }}>
308
- <Story />
309
- </div>
310
- ),
311
- ]
312
-
313
- export { Default, Sizes, Variants, Icons, IconButton, Disabled, Truncated }
314
- export default meta
@@ -1,132 +0,0 @@
1
- import React from "react"
2
-
3
- // Types
4
- import type { ButtonVariant, ButtonSize } from "./types"
5
- import type { PolymorphicComponentPropsWithRef } from "../../types/polymorphic"
6
-
7
- // Utils
8
- import { clsx } from "clsx"
9
- import Spinner from "../Spinner"
10
-
11
- // Params
12
- type ButtonElementType = "button" | "a"
13
-
14
- interface BaseButtonProps {
15
- variant?: ButtonVariant
16
- size?: ButtonSize
17
- icon?: React.ReactNode
18
- as?: ButtonElementType
19
- iconPosition?: "left" | "right"
20
- children?: React.ReactNode
21
- disabled?: boolean
22
- type?: "button" | "submit" | "reset"
23
- loading?: boolean
24
- }
25
-
26
- type ButtonProps<C extends ButtonElementType = "button"> = PolymorphicComponentPropsWithRef<
27
- C,
28
- BaseButtonProps
29
- >
30
-
31
- type ButtonComponent = <C extends ButtonElementType = "button">(
32
- props: ButtonProps<C>,
33
- ) => React.ReactNode
34
-
35
- /*
36
-
37
-
38
-
39
-
40
-
41
- */
42
-
43
- const Button: ButtonComponent = <C extends ButtonElementType = "button">({
44
- variant = "primary",
45
- size = "lg",
46
- as,
47
- icon,
48
- iconPosition = "left",
49
- children,
50
- className = "",
51
- disabled,
52
- loading,
53
- ...rest
54
- }: ButtonProps<C>) => {
55
- const Component = (as ?? "button") as React.ElementType
56
-
57
- return (
58
- <Component
59
- className={clsx(
60
- "tracking-heading inline-flex w-fit cursor-pointer items-center justify-center overflow-hidden rounded-full leading-[1.4]! font-medium whitespace-nowrap transition-colors ease-out disabled:cursor-default disabled:opacity-40",
61
- {
62
- primary:
63
- "bg-lime-100 text-teal-100 not-disabled:hover:bg-[hsl(95,81%,69%)] not-disabled:focus-visible:bg-[hsl(95,81%,69%)] not-disabled:active:bg-[hsl(95,67%,58%)]",
64
- secondary:
65
- "bg-teal-100 text-lime-100 not-disabled:hover:bg-[hsl(180,84%,20%)] not-disabled:focus-visible:bg-[hsl(180,84%,20%)] not-disabled:active:bg-[hsl(180,84%,10%)]",
66
- "outline-light":
67
- "border-[1.5px] border-white/30 text-white not-disabled:hover:bg-white/8 not-disabled:focus-visible:bg-white/8 not-disabled:active:bg-white/16",
68
- "outline-dark":
69
- "border-[1.5px] border-neutral-100/16 text-neutral-100 not-disabled:hover:border-neutral-100/20 not-disabled:hover:bg-neutral-100/4 not-disabled:focus-visible:border-neutral-100/20 not-disabled:active:border-neutral-100/20 not-disabled:active:bg-neutral-100/8",
70
- ghost:
71
- "text-neutral-50 not-disabled:hover:bg-teal-100/6 not-disabled:hover:text-neutral-100 not-disabled:focus-visible:bg-teal-100/6 not-disabled:focus-visible:text-neutral-100 not-disabled:active:bg-teal-100/12 not-disabled:active:text-neutral-100",
72
- danger:
73
- "bg-error-100 text-white not-disabled:hover:bg-[hsl(7,74%,42%)] not-disabled:focus-visible:bg-[hsl(7,74%,42%)] not-disabled:active:bg-[hsl(7,70%,35%)]",
74
- success:
75
- "bg-success-100 text-white not-disabled:hover:bg-[hsl(145,72%,29%)] not-disabled:focus-visible:bg-[hsl(145,72%,29%)] not-disabled:active:bg-[hsl(145,64%,24%)]",
76
- }[variant],
77
- {
78
- sm: [
79
- "min-h-9 gap-2 text-sm",
80
- icon && !children ? "aspect-square size-9 shrink-0 grow-0" : "px-4",
81
- ],
82
- md: [
83
- "min-h-12 gap-2.5 text-base",
84
- icon && !children ? "aspect-square size-12 shrink-0 grow-0" : "px-6",
85
- ],
86
- lg: [
87
- "min-h-12 gap-2.5 text-base lg:min-h-14 lg:gap-3.5",
88
- icon && !children ? "aspect-square size-12 shrink-0 grow-0 lg:size-14" : "px-6 lg:px-8",
89
- ],
90
- }[size],
91
- className,
92
- )}
93
- disabled={disabled}
94
- {...rest}
95
- >
96
- {iconPosition === "left" && (icon || loading) && (
97
- <div className={clsx("size-5", !!children && "-ml-1.5")}>
98
- {loading ? (
99
- <Spinner
100
- className={clsx(
101
- size === "sm"
102
- ? "mt-0.5 ml-0.5 [--spinner-size:1rem]!"
103
- : "[--spinner-size:1.25rem]!",
104
- )}
105
- />
106
- ) : (
107
- icon
108
- )}
109
- </div>
110
- )}
111
- {children && <div className="m-0 shrink grow truncate text-inherit">{children}</div>}
112
- {iconPosition === "right" && (icon || loading) && (
113
- <div className={clsx("size-5", !!children && "-mr-1.5")}>
114
- {loading ? (
115
- <Spinner
116
- className={clsx(
117
- size === "sm"
118
- ? "mt-0.5 mr-0.5 [--spinner-size:1rem]!"
119
- : "[--spinner-size:1.25rem]!",
120
- )}
121
- />
122
- ) : (
123
- icon
124
- )}
125
- </div>
126
- )}
127
- </Component>
128
- )
129
- }
130
-
131
- export default Button
132
- export type { ButtonProps }
@@ -1,2 +0,0 @@
1
- export { default, type ButtonProps } from "./Button"
2
- export { type ButtonSize, BUTTON_SIZES, BUTTON_VARIANTS, type ButtonVariant } from "./types"
@@ -1,19 +0,0 @@
1
- export const BUTTON_SIZES = {
2
- sm: "sm",
3
- md: "md",
4
- lg: "lg",
5
- } as const
6
-
7
- export type ButtonSize = keyof typeof BUTTON_SIZES
8
-
9
- export const BUTTON_VARIANTS = {
10
- primary: "primary",
11
- secondary: "secondary",
12
- "outline-light": "outline-light",
13
- "outline-dark": "outline-dark",
14
- ghost: "ghost",
15
- success: "success",
16
- danger: "danger",
17
- } as const
18
-
19
- export type ButtonVariant = keyof typeof BUTTON_VARIANTS
@@ -1,152 +0,0 @@
1
- import React from "react"
2
-
3
- // Components
4
- import Checkbox from "./Checkbox"
5
-
6
- // Types
7
- import type { Meta, StoryFn } from "@storybook/react-webpack5"
8
- import type { CheckboxProps } from "./Checkbox"
9
- import { CHECKBOX_SIZES } from "./types"
10
-
11
- /*
12
-
13
-
14
-
15
-
16
- */
17
-
18
- const meta: Meta<CheckboxProps> = {
19
- title: "Components/Checkbox",
20
- component: Checkbox,
21
- parameters: {
22
- docs: {
23
- description: {
24
- component: "A binary input control allowing users to toggle a selection on or off.",
25
- },
26
- },
27
- controls: {
28
- exclude: ["className", "ref"],
29
- },
30
- },
31
- argTypes: {
32
- size: {
33
- type: "string",
34
- description: "Visual size of the checkbox control.",
35
- table: {
36
- type: {
37
- summary: Object.keys(CHECKBOX_SIZES)
38
- .map(s => `"${s}"`)
39
- .join(" | "),
40
- },
41
- defaultValue: { summary: `"sm"` },
42
- },
43
- options: Object.keys(CHECKBOX_SIZES),
44
- control: { type: "select" },
45
- },
46
- label: {
47
- type: "string",
48
- description: "Label text displayed next to the checkbox.",
49
- table: {
50
- type: { summary: "string" },
51
- defaultValue: { summary: "undefined" },
52
- },
53
- },
54
- meta: {
55
- type: "string",
56
- description: "Secondary text displayed below the label.",
57
- table: {
58
- type: { summary: "string" },
59
- defaultValue: { summary: "undefined" },
60
- },
61
- },
62
- disabled: {
63
- description: "Disables the checkbox.",
64
- table: {
65
- type: { summary: "boolean" },
66
- defaultValue: { summary: "false" },
67
- },
68
- },
69
- },
70
- args: {
71
- size: "md",
72
- },
73
- }
74
-
75
- const Template: StoryFn<CheckboxProps> = args => <Checkbox {...args} />
76
-
77
- const SizesTemplate: StoryFn<CheckboxProps> = args => (
78
- <>
79
- <Checkbox {...args} size="sm" />
80
- <Checkbox {...args} size="md" />
81
- </>
82
- )
83
-
84
- const Default = Template.bind({})
85
- const Checked = Template.bind({})
86
- const Sizes = SizesTemplate.bind({})
87
- const WithLabel = Template.bind({})
88
- const WithLabelAndMeta = Template.bind({})
89
- const Disabled = Template.bind({})
90
- const DisabledChecked = Template.bind({})
91
-
92
- // Args
93
- Checked.args = { defaultChecked: true }
94
- WithLabel.args = { label: "Accept terms and conditions" }
95
- WithLabelAndMeta.args = {
96
- label: "Accept terms and conditions",
97
- meta: "You agree to our terms of service and privacy policy.",
98
- }
99
- Disabled.args = { disabled: true, label: "Disabled option" }
100
- DisabledChecked.args = { disabled: true, defaultChecked: true, label: "Disabled checked" }
101
-
102
- // Parameters
103
- Sizes.parameters = {
104
- docs: {
105
- description: {
106
- story: 'Checkbox renders in two sizes (`"sm"`, `"md"`). Default is `"sm"`.',
107
- },
108
- },
109
- }
110
-
111
- WithLabel.parameters = {
112
- docs: {
113
- description: {
114
- story: "Pass a `label` prop to display text alongside the checkbox.",
115
- },
116
- },
117
- }
118
-
119
- WithLabelAndMeta.parameters = {
120
- docs: {
121
- description: {
122
- story: "The `meta` prop renders secondary descriptive text below the label.",
123
- },
124
- },
125
- }
126
-
127
- Disabled.parameters = {
128
- docs: {
129
- description: {
130
- story: "Setting `disabled` reduces opacity and prevents interaction.",
131
- },
132
- },
133
- }
134
-
135
- // Decorators
136
- Default.decorators = [
137
- Story => (
138
- <div className="flex flex-wrap items-center gap-4">
139
- <Story />
140
- </div>
141
- ),
142
- ]
143
-
144
- Checked.decorators = [...Default.decorators]
145
- Sizes.decorators = [...Default.decorators]
146
- WithLabel.decorators = [...Default.decorators]
147
- WithLabelAndMeta.decorators = [...Default.decorators]
148
- Disabled.decorators = [...Default.decorators]
149
- DisabledChecked.decorators = [...Default.decorators]
150
-
151
- export { Default, Checked, Sizes, WithLabel, WithLabelAndMeta, Disabled, DisabledChecked }
152
- export default meta
@@ -1,90 +0,0 @@
1
- import React from "react"
2
-
3
- // Types
4
- import type { CheckboxSize } from "./types"
5
-
6
- // Utils
7
- import { clsx } from "clsx"
8
-
9
- // Params
10
- export interface CheckboxProps extends Omit<React.ComponentPropsWithRef<"input">, "size"> {
11
- /** Label text for the checkbox. */
12
- label?: string
13
- /** Secondary text displayed below the label. */
14
- meta?: string
15
- /** Visual size of the checkbox control. */
16
- size?: CheckboxSize
17
- }
18
-
19
- /*
20
-
21
-
22
-
23
-
24
- */
25
-
26
- const Checkbox: React.FC<CheckboxProps> = ({
27
- className,
28
- label,
29
- meta,
30
- size = "md",
31
- disabled,
32
- ref,
33
- ...rest
34
- }) => {
35
- return (
36
- <label
37
- className={clsx(
38
- "group/checkbox flex cursor-pointer items-start gap-2",
39
- disabled && "pointer-events-none opacity-40",
40
- className,
41
- )}
42
- >
43
- <input
44
- ref={ref}
45
- type="checkbox"
46
- className="peer absolute opacity-0"
47
- aria-label={label ?? "Checkbox"}
48
- disabled={disabled}
49
- {...rest}
50
- />
51
- <div
52
- className={clsx(
53
- "relative flex shrink-0 items-center justify-center rounded-sm border border-neutral-100/20 bg-transparent text-white transition-colors ease-out group-hover/checkbox:border-teal-100/16 group-hover/checkbox:bg-black/5 peer-checked:border-transparent peer-checked:bg-teal-100 peer-checked:group-hover/checkbox:bg-[hsl(180,84%,13%)] peer-focus-visible:ring-2 peer-focus-visible:ring-teal-100 peer-focus-visible:ring-offset-1",
54
- size === "sm" ? "size-4" : "size-5",
55
- )}
56
- >
57
- <div
58
- className={clsx(
59
- "invisible group-has-checked/checkbox:visible",
60
- size === "sm" ? "size-2.25" : "size-2.5",
61
- )}
62
- >
63
- <svg
64
- viewBox="0 0 10 8"
65
- fill="none"
66
- xmlns="http://www.w3.org/2000/svg"
67
- className="size-full"
68
- >
69
- <path
70
- d="M1 4L3.5 6.5L9 1"
71
- stroke="currentColor"
72
- strokeWidth="1.5"
73
- strokeLinecap="round"
74
- strokeLinejoin="round"
75
- />
76
- </svg>
77
- </div>
78
- </div>
79
- {label && (
80
- <span className="text-sm/snug text-neutral-100">
81
- {label}
82
- {meta && <span className="block text-xs/snug font-normal text-neutral-50">{meta}</span>}
83
- </span>
84
- )}
85
- </label>
86
- )
87
- }
88
-
89
- Checkbox.displayName = "Checkbox"
90
- export default Checkbox