@sanity/sanity-id 0.0.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 (77) hide show
  1. package/.turbo/turbo-build.log +32 -0
  2. package/README.md +272 -0
  3. package/css/all.css +3 -0
  4. package/css/colors.css +498 -0
  5. package/css/tailwind.css +3 -0
  6. package/css/variables.css +326 -0
  7. package/dist/Breadcrumbs.js +53 -0
  8. package/dist/Button.js +50 -0
  9. package/dist/Card.js +16 -0
  10. package/dist/Checkbox.js +31 -0
  11. package/dist/Eyebrow.js +30 -0
  12. package/dist/IconButton.js +38 -0
  13. package/dist/Input.js +16 -0
  14. package/dist/Input.module-P--gA8sq.js +6 -0
  15. package/dist/Label.js +22 -0
  16. package/dist/Link-BWIwmuYV.js +4068 -0
  17. package/dist/LinkCTA.js +53 -0
  18. package/dist/Radio.js +29 -0
  19. package/dist/RadioSwitch.js +87 -0
  20. package/dist/SanityIcon-Bl5or1b8.js +13 -0
  21. package/dist/Select.js +22 -0
  22. package/dist/Switch.js +29 -0
  23. package/dist/TextArea.js +21 -0
  24. package/dist/_commonjsHelpers-C6fGbg64.js +6 -0
  25. package/dist/clsx-OuTLNxxd.js +16 -0
  26. package/dist/colors.js +935 -0
  27. package/dist/styles.css +1 -0
  28. package/dist/tailwind.js +577 -0
  29. package/dist/useLinkWithRef-D9NOX6Bd.js +21 -0
  30. package/dist/utils.js +23 -0
  31. package/package.json +56 -0
  32. package/postcss.config.js +6 -0
  33. package/src/colors.ts +3 -0
  34. package/src/components/Breadcrumbs.module.css +21 -0
  35. package/src/components/Breadcrumbs.tsx +38 -0
  36. package/src/components/Button.module.css +407 -0
  37. package/src/components/Button.tsx +110 -0
  38. package/src/components/Card.module.css +19 -0
  39. package/src/components/Card.tsx +18 -0
  40. package/src/components/Checkbox.module.css +82 -0
  41. package/src/components/Checkbox.tsx +38 -0
  42. package/src/components/Eyebrow.module.css +28 -0
  43. package/src/components/Eyebrow.tsx +37 -0
  44. package/src/components/IconButton.module.css +196 -0
  45. package/src/components/IconButton.tsx +62 -0
  46. package/src/components/Input.module.css +55 -0
  47. package/src/components/Input.tsx +23 -0
  48. package/src/components/Label.module.css +53 -0
  49. package/src/components/Label.tsx +33 -0
  50. package/src/components/LinkCTA.module.css +122 -0
  51. package/src/components/LinkCTA.tsx +77 -0
  52. package/src/components/Radio.module.css +91 -0
  53. package/src/components/Radio.tsx +33 -0
  54. package/src/components/RadioSwitch.module.css +125 -0
  55. package/src/components/RadioSwitch.tsx +122 -0
  56. package/src/components/Select.module.css +35 -0
  57. package/src/components/Select.tsx +28 -0
  58. package/src/components/Switch.module.css +112 -0
  59. package/src/components/Switch.tsx +33 -0
  60. package/src/components/TextArea.module.css +17 -0
  61. package/src/components/TextArea.tsx +30 -0
  62. package/src/components/helpers/AddRefParam.tsx +29 -0
  63. package/src/components/helpers/Link.tsx +56 -0
  64. package/src/components/helpers/NavLink.tsx +20 -0
  65. package/src/components/helpers/SanityIcon.tsx +25 -0
  66. package/src/components/helpers/useIsCurrentPage.ts +39 -0
  67. package/src/components/helpers/useLinkWithRef.ts +27 -0
  68. package/src/components/helpers/useSafePathname.ts +17 -0
  69. package/src/css.d.ts +4 -0
  70. package/src/tailwind.ts +408 -0
  71. package/src/tokens/dynamic-colors.ts +154 -0
  72. package/src/tokens/primitive-colors.ts +237 -0
  73. package/src/tokens/semantic-colors.ts +574 -0
  74. package/src/utils.ts +58 -0
  75. package/tailwind.config.ts +7 -0
  76. package/tsconfig.json +17 -0
  77. package/vite.config.ts +29 -0
@@ -0,0 +1,21 @@
1
+ .nav {
2
+ @apply w-fit;
3
+ }
4
+
5
+ .list {
6
+ @apply flex w-fit list-none flex-wrap gap-x-8 p-0;
7
+ }
8
+
9
+ .listItem::after {
10
+ @apply label-md ml-8;
11
+
12
+ content: "/";
13
+ }
14
+
15
+ .link {
16
+ @apply label-md text-fg-dim no-underline underline-offset-2 hover:text-fg-strong hover:underline;
17
+
18
+ --focus-ring-width: 2px;
19
+ --focus-ring-color: currentColor;
20
+ --focus-ring-offset: 2px;
21
+ }
@@ -0,0 +1,38 @@
1
+ import cn from "clsx"
2
+ import { Suspense } from "react"
3
+ import { NavLink } from "./helpers/NavLink"
4
+ import css from "./Breadcrumbs.module.css"
5
+
6
+ export type Breadcrumb = {
7
+ title: string
8
+ href: string
9
+ current?: boolean
10
+ }
11
+
12
+ export type BreadcrumbsProps = {
13
+ label: string
14
+ links: Array<Breadcrumb>
15
+ className?: string
16
+ }
17
+
18
+ export function Breadcrumbs(props: BreadcrumbsProps) {
19
+ return (
20
+ <nav aria-label={props.label} className={cn(props.className, css.nav)}>
21
+ <ol className={css.list}>
22
+ {props.links.map((link) => (
23
+ <li key={link.href + link.title} className={css.listItem}>
24
+ <Suspense>
25
+ <NavLink
26
+ href={link.href}
27
+ aria-current={link.current ? "page" : undefined}
28
+ className={css.link}
29
+ >
30
+ {link.title}
31
+ </NavLink>
32
+ </Suspense>
33
+ </li>
34
+ ))}
35
+ </ol>
36
+ </nav>
37
+ )
38
+ }
@@ -0,0 +1,407 @@
1
+ .button {
2
+ @apply relative box-border flex min-w-fit cursor-pointer items-center justify-center border border-solid leading-[1.2lh] no-underline transition-colors;
3
+
4
+ &[data-size="sm"] {
5
+ @apply text-interactive-sm min-h-[25px] gap-x-2 rounded-sm px-8 py-[2px] font-semibold data-[no-label]:size-[25px];
6
+
7
+ .icon {
8
+ @apply size-19;
9
+ }
10
+ }
11
+
12
+ &[data-size="md"] {
13
+ @apply text-interactive-md min-h-[35px] gap-x-4 rounded-sm px-12 py-[6px] font-semibold data-[no-label]:size-[35px];
14
+
15
+ .icon {
16
+ @apply size-21;
17
+ }
18
+ }
19
+
20
+ &[data-size="lg"] {
21
+ @apply text-interactive-lg min-h-[45px] gap-x-6 rounded-md px-24 py-[9px] font-semibold data-[no-label]:size-[45px];
22
+
23
+ .icon {
24
+ @apply size-25;
25
+ }
26
+ }
27
+
28
+ &[data-no-label="true"] {
29
+ @apply p-0;
30
+ }
31
+
32
+ &[data-fill="solid"][data-color="primary"] {
33
+ @apply text-gray-50-dynamic @light:border-black @light:bg-black @dark:border-gray-50 @dark:bg-gray-50;
34
+
35
+ .icon {
36
+ @apply @light:text-gray-300 @dark:text-gray-700;
37
+ }
38
+
39
+ &:hover,
40
+ &[data-state="hover"],
41
+ &[data-state="loading"] {
42
+ @apply @light:border-gray-800 @light:bg-gray-800 @dark:border-white @dark:bg-white;
43
+ }
44
+
45
+ &:active,
46
+ &[data-state="active"] {
47
+ @apply @light:border-black @light:bg-black @dark:border-gray-50 @dark:bg-gray-50;
48
+ }
49
+ }
50
+
51
+ &[data-fill="solid"][data-color="accent"] {
52
+ @apply text-cyan-900 @light:border-cyan-300 @light:bg-cyan-300 @dark:border-cyan-400 @dark:bg-cyan-400;
53
+
54
+ .icon {
55
+ @apply text-cyan-600;
56
+ }
57
+
58
+ &:hover,
59
+ &[data-state="hover"],
60
+ &[data-state="loading"] {
61
+ @apply @light:border-cyan-200 @light:bg-cyan-200 @dark:border-cyan-200 @dark:bg-cyan-200;
62
+ }
63
+
64
+ &:active,
65
+ &[data-state="active"] {
66
+ @apply @light:border-cyan-300 @light:bg-cyan-300 @dark:border-cyan-400 @dark:bg-cyan-400;
67
+ }
68
+ }
69
+
70
+ &[data-fill="solid"][data-color="brand"] {
71
+ @apply border-red-500 bg-red-500 text-black;
72
+
73
+ .icon {
74
+ @apply text-red-800;
75
+ }
76
+
77
+ &:hover,
78
+ &[data-state="hover"],
79
+ &[data-state="loading"] {
80
+ @apply border-red-400 bg-red-400;
81
+ }
82
+
83
+ &:active,
84
+ &[data-state="active"] {
85
+ @apply border-red-500 bg-red-500;
86
+ }
87
+ }
88
+
89
+ &[data-fill="solid"][data-color="gray"] {
90
+ @apply @light:border-white @light:bg-white @light:text-gray-900 @dark:border-gray-900 @dark:bg-gray-900 @dark:text-gray-100;
91
+
92
+ .icon {
93
+ @apply @light:text-gray-600 @dark:text-gray-400;
94
+ }
95
+
96
+ &:hover,
97
+ &[data-state="hover"],
98
+ &[data-state="loading"] {
99
+ @apply @light:border-gray-200 @light:bg-gray-200 @dark:border-gray-800 @dark:bg-gray-800;
100
+ }
101
+
102
+ &:active,
103
+ &[data-state="active"] {
104
+ @apply @light:border-white @light:bg-white @dark:border-gray-900 @dark:bg-gray-900;
105
+ }
106
+ }
107
+
108
+ &[data-fill="outline"][data-color="accent"] {
109
+ @apply isolate border-0 bg-transparent @light:border-cyan-400 @light:text-cyan-700 @dark:border-cyan-800 @dark:text-cyan-100;
110
+
111
+ .icon {
112
+ @apply @light:text-cyan-600 @dark:text-cyan-300;
113
+ }
114
+
115
+ &:hover,
116
+ &[data-state="hover"],
117
+ &[data-state="loading"] {
118
+ @apply @light:border-cyan-200 @light:bg-cyan-200 @dark:border-cyan-700 @dark:bg-cyan-700 @dark:text-white;
119
+ }
120
+
121
+ &:active,
122
+ &[data-state="active"] {
123
+ @apply @light:border-cyan-300 @light:bg-cyan-300 @dark:border-cyan-400 @dark:bg-cyan-400 @dark:text-cyan-700;
124
+
125
+ .icon {
126
+ @apply text-cyan-700;
127
+ }
128
+ }
129
+ }
130
+
131
+ &[data-fill="outline"][data-color="gray"] {
132
+ @apply border-border-subtle bg-transparent text-fg-base;
133
+
134
+ .icon {
135
+ @apply @light:text-gray-600 @dark:text-gray-400;
136
+ }
137
+
138
+ &:hover,
139
+ &[data-state="hover"],
140
+ &[data-state="loading"] {
141
+ @apply @light:border-gray-200 @light:bg-gray-200 @dark:border-gray-800 @dark:bg-gray-800;
142
+ }
143
+
144
+ &:active,
145
+ &[data-state="active"] {
146
+ @apply @light:border-white @light:bg-white @dark:border-gray-900 @dark:bg-gray-900;
147
+ }
148
+ }
149
+
150
+ &[data-fill="ghost"] {
151
+ @apply border-transparent bg-transparent @light:text-gray-900 @dark:text-gray-100;
152
+
153
+ .icon {
154
+ @apply @light:text-gray-600 @dark:text-gray-400;
155
+ }
156
+
157
+ &:hover,
158
+ &[data-state="hover"],
159
+ &[data-state="loading"] {
160
+ @apply @light:border-gray-200 @light:bg-gray-200 @dark:border-gray-800 @dark:bg-gray-800;
161
+ }
162
+
163
+ &:active,
164
+ &[data-state="active"] {
165
+ @apply @light:border-white @light:bg-white @dark:border-gray-900 @dark:bg-gray-900;
166
+ }
167
+ }
168
+
169
+ &[data-rounded="true"] {
170
+ @apply rounded-full;
171
+ }
172
+
173
+ &:focus-visible,
174
+ &[data-state="focus"] {
175
+ @apply outline-2 outline-offset-2 outline-bg-inverse-base;
176
+ }
177
+
178
+ &:disabled,
179
+ &[data-state="disabled"] {
180
+ @apply !border-dashed !border-gray-400-dynamic !bg-transparent !text-gray-300;
181
+
182
+ .icon {
183
+ @apply !text-gray-300;
184
+ }
185
+ }
186
+ }
187
+
188
+ .icon {
189
+ @apply inline-block flex-shrink-0 place-items-center content-center;
190
+
191
+ & > * {
192
+ height: 100%;
193
+ width: 100%;
194
+ }
195
+
196
+ svg[data-icon="spinner"] {
197
+ @apply animate-spin;
198
+ }
199
+
200
+ .button[data-size="md"] &.iconLeft {
201
+ @apply -ml-2;
202
+ }
203
+
204
+ .button[data-size="md"] &.iconRight {
205
+ @apply -mr-2;
206
+ }
207
+
208
+ .button[data-size="lg"] &.iconLeft {
209
+ @apply -ml-4;
210
+ }
211
+
212
+ .button[data-size="lg"] &.iconRight {
213
+ @apply -mr-4;
214
+ }
215
+ }
216
+
217
+ :global([data-rebrand="true"]) {
218
+ .button {
219
+ @apply !rounded-full !font-normal !uppercase !transition-none !duration-0;
220
+ }
221
+
222
+ .button[data-fill="solid"][data-color="brand"] {
223
+ @apply !bg-[var(--brand)] !text-black !border-[var(--brand)];
224
+
225
+ --button-icon-color: currentColor !important;
226
+
227
+ &:hover,
228
+ &[data-state="hover"] {
229
+ @apply !bg-black-dynamic !text-[var(--brand)] !border-black-dynamic;
230
+ }
231
+
232
+ &:active,
233
+ &[data-state="active"] {
234
+ @apply !bg-[var(--brand)] !text-black;
235
+ }
236
+
237
+ &:disabled,
238
+ &[data-state="disabled"],
239
+ &[aria-disabled="true"] {
240
+ @apply !text-fg-dim !bg-transparent !border-dashed !border-[var(--brand)];
241
+
242
+ --button-icon-color: currentColor !important;
243
+ }
244
+ }
245
+
246
+ .button[data-fill="solid"][data-color="primary"] {
247
+ @apply border !border-black-dynamic !bg-black-dynamic !text-white-dynamic;
248
+
249
+ &:hover,
250
+ &[data-state="hover"] {
251
+ @apply !text-black-dynamic !bg-white-dynamic;
252
+ }
253
+
254
+ &:active,
255
+ &[data-state="active"] {
256
+ @apply border !border-black-dynamic !bg-black-dynamic !text-white-dynamic;
257
+ }
258
+
259
+ &:disabled,
260
+ &[data-state="disabled"],
261
+ &[aria-disabled="true"] {
262
+ @apply !text-fg-dim !bg-transparent !border-dashed !border-gray-400-dynamic;
263
+ }
264
+ }
265
+
266
+ .button[data-fill="solid"][data-color="primary-inverse"] {
267
+ @apply border !border-white-dynamic !bg-white-dynamic !text-black-dynamic;
268
+
269
+ &:hover,
270
+ &[data-state="hover"] {
271
+ @apply !text-white-dynamic !bg-black-dynamic;
272
+ }
273
+
274
+ &:active,
275
+ &[data-state="active"] {
276
+ @apply border !border-white-dynamic !bg-white-dynamic !text-black-dynamic;
277
+ }
278
+
279
+ &:disabled,
280
+ &[data-state="disabled"],
281
+ &[aria-disabled="true"] {
282
+ @apply !text-fg-dim !bg-transparent !border-dashed !border-gray-400-dynamic;
283
+ }
284
+ }
285
+
286
+ .button[data-fill="solid"][data-color="black"] {
287
+ @apply border !border-black !bg-black !text-white;
288
+
289
+ &:hover,
290
+ &[data-state="hover"] {
291
+ @apply !text-black !border-white !bg-white;
292
+ }
293
+
294
+ &:active,
295
+ &[data-state="active"] {
296
+ @apply border !border-black !bg-black !text-white;
297
+ }
298
+
299
+ &:disabled,
300
+ &[data-state="disabled"],
301
+ &[aria-disabled="true"] {
302
+ @apply !text-fg-dim !bg-transparent !border-dashed !border-gray-400-dynamic;
303
+ }
304
+ }
305
+
306
+ .button[data-fill="solid"][data-color="white"] {
307
+ @apply border !border-white !bg-white !text-black;
308
+
309
+ &:hover,
310
+ &[data-state="hover"] {
311
+ @apply !text-white !bg-black !border-black;
312
+ }
313
+
314
+ &:active,
315
+ &[data-state="active"] {
316
+ @apply border !border-white !bg-white !text-black;
317
+ }
318
+
319
+ &:disabled,
320
+ &[data-state="disabled"],
321
+ &[aria-disabled="true"] {
322
+ @apply !text-fg-dim !bg-transparent !border-dashed !border-gray-400-dynamic;
323
+ }
324
+ }
325
+
326
+ .button[data-fill="solid"][data-color="accent"] {
327
+ @apply border !border-blue-600 !bg-blue-600 !text-white;
328
+
329
+ &:hover,
330
+ &[data-state="hover"] {
331
+ @apply !bg-white-dynamic !text-blue-600;
332
+ }
333
+
334
+ &:active,
335
+ &[data-state="active"] {
336
+ @apply border !border-blue-600 !bg-blue-600 !text-white;
337
+ }
338
+
339
+ &:disabled,
340
+ &[data-state="disabled"],
341
+ &[aria-disabled="true"] {
342
+ @apply !text-fg-dim !bg-transparent !border-dashed !border-blue-600;
343
+ }
344
+ }
345
+
346
+ .button[data-fill="solid"][data-color="gray"] {
347
+ @apply border !border-gray-200-dynamic !bg-gray-200-dynamic !text-black-dynamic;
348
+
349
+ &:hover,
350
+ &[data-state="hover"] {
351
+ @apply !border-gray-300-dynamic !bg-gray-300-dynamic;
352
+ }
353
+
354
+ /* &:active,
355
+ &[data-state="active"] {
356
+ } */
357
+
358
+ &:disabled,
359
+ &[data-state="disabled"],
360
+ &[aria-disabled="true"] {
361
+ @apply !text-fg-dim !bg-transparent !border-dashed !border-gray-400-dynamic;
362
+ }
363
+ }
364
+
365
+ .button[data-fill="outline"] {
366
+ @apply border !border-black-dynamic !bg-transparent !text-black-dynamic;
367
+
368
+ &:hover,
369
+ &[data-state="hover"] {
370
+ @apply !bg-black-dynamic !text-white-dynamic;
371
+ }
372
+
373
+ /* &:active,
374
+ &[data-state="active"] {
375
+ } */
376
+
377
+ &:disabled,
378
+ &[data-state="disabled"],
379
+ &[aria-disabled="true"] {
380
+ @apply !text-fg-dim !bg-transparent !border-dashed !border-gray-400-dynamic;
381
+ }
382
+ }
383
+
384
+ .button[data-fill="ghost"] {
385
+ @apply border !border-transparent !bg-transparent !text-black-dynamic;
386
+
387
+ &:hover,
388
+ &[data-state="hover"] {
389
+ @apply !bg-gray-200-dynamic !border-gray-200-dynamic;
390
+ }
391
+
392
+ /* &:active,
393
+ &[data-state="active"] {
394
+ } */
395
+
396
+ &:disabled,
397
+ &[data-state="disabled"],
398
+ &[aria-disabled="true"] {
399
+ @apply !text-fg-dim !bg-transparent !border-dashed !border-gray-400-dynamic;
400
+ }
401
+ }
402
+
403
+ .icon.iconLeft,
404
+ .icon.iconRight {
405
+ color: var(--button-icon-color) !important;
406
+ }
407
+ }
@@ -0,0 +1,110 @@
1
+ "use client"
2
+
3
+ import cn from "clsx"
4
+ import { Link } from "./helpers/Link"
5
+ import { SanityIcon, type SanityIconName } from "./helpers/SanityIcon"
6
+ import { useLinkWithRef } from "./helpers/useLinkWithRef"
7
+ import css from "./Button.module.css"
8
+
9
+ type AnchorOrButton = Omit<Parameters<typeof Link>[0], "type" | "href"> &
10
+ React.ButtonHTMLAttributes<HTMLButtonElement>
11
+
12
+ export namespace Button {
13
+ export type State =
14
+ | "default"
15
+ | "hover"
16
+ | "active"
17
+ | "disabled"
18
+ | "loading"
19
+ | undefined
20
+
21
+ export type Fill = "solid" | "outline" | "ghost" | undefined
22
+ export type Props = AnchorOrButton & {
23
+ as?: "button" | "a" | "div" | "span" | "external"
24
+ size?: "sm" | "md" | "lg"
25
+ fill?: Fill
26
+ color?:
27
+ | "primary"
28
+ | "brand"
29
+ | "accent"
30
+ | "gray"
31
+ | "primary-inverse"
32
+ | "white"
33
+ | "black"
34
+ state?: State
35
+ iconLeft?: SanityIconName | React.ReactNode
36
+ iconRight?: SanityIconName | React.ReactNode
37
+ children?: React.ReactNode
38
+ href?: string
39
+ rounded?: boolean
40
+ injectRef?: boolean
41
+ disableLinkRef?: boolean
42
+ }
43
+ }
44
+
45
+ export function Button({
46
+ as,
47
+ size,
48
+ fill,
49
+ color,
50
+ state,
51
+ iconLeft,
52
+ iconRight,
53
+ children,
54
+ rounded,
55
+ injectRef = true,
56
+ disableLinkRef = false,
57
+ ...props
58
+ }: Button.Props) {
59
+ let href = props.href
60
+ const hrefWithRef = useLinkWithRef(props.href)
61
+
62
+ if (injectRef && !disableLinkRef) href = hrefWithRef
63
+
64
+ size ??= "md"
65
+ fill ??= "solid"
66
+ color ??= "primary"
67
+
68
+ if (state === "loading") {
69
+ if (iconLeft && !iconRight) iconLeft = "spinner"
70
+ else if (iconRight && !iconLeft) iconRight = "spinner"
71
+ else iconLeft = "spinner"
72
+ }
73
+
74
+ if (typeof iconLeft === "string") {
75
+ iconLeft = <SanityIcon icon={iconLeft as SanityIconName} />
76
+ }
77
+
78
+ if (typeof iconRight === "string") {
79
+ iconRight = <SanityIcon icon={iconRight as SanityIconName} />
80
+ }
81
+
82
+ let Element: React.ElementType = "div"
83
+ if (as === "a") Element = Link
84
+ else if (as === "external") Element = "a"
85
+ else if (as) Element = as
86
+ else if (href) Element = Link
87
+ else if (props.onClick) Element = "button"
88
+
89
+ return (
90
+ <Element
91
+ {...props}
92
+ className={cn(css.button, props.className)}
93
+ data-size={size}
94
+ data-fill={fill}
95
+ data-color={color}
96
+ data-state={state}
97
+ data-rounded={rounded}
98
+ data-no-label={children ? undefined : true}
99
+ href={href}
100
+ >
101
+ {iconLeft && (
102
+ <span className={cn(css.icon, css.iconLeft)}>{iconLeft}</span>
103
+ )}
104
+ {children}
105
+ {iconRight && (
106
+ <span className={cn(css.icon, css.iconRight)}>{iconRight}</span>
107
+ )}
108
+ </Element>
109
+ )
110
+ }
@@ -0,0 +1,19 @@
1
+ .card {
2
+ @apply overflow-clip transition-all hover:bg-bg-strong;
3
+
4
+ &[data-border="true"] {
5
+ @apply border border-border-subtle hover:shadow-3;
6
+ }
7
+
8
+ &[data-rounded="sm"] {
9
+ @apply rounded-sm;
10
+ }
11
+
12
+ &[data-rounded="md"] {
13
+ @apply rounded-md;
14
+ }
15
+
16
+ &[data-rounded="lg"] {
17
+ @apply rounded-lg;
18
+ }
19
+ }
@@ -0,0 +1,18 @@
1
+ import cn from "clsx"
2
+ import { Children, cloneElement } from "react"
3
+ import css from "./Card.module.css"
4
+
5
+ type CardProps = {
6
+ children: React.ReactElement
7
+ rounded?: "none" | "sm" | "md" | "lg"
8
+ border?: boolean
9
+ }
10
+
11
+ export function Card(props: CardProps) {
12
+ const child = Children.only(props.children)
13
+ return cloneElement(child, {
14
+ className: cn(child.props.className, css.card),
15
+ "data-rounded": props.rounded ?? "md",
16
+ "data-border": props.border ?? true,
17
+ })
18
+ }
@@ -0,0 +1,82 @@
1
+ @layer shared {
2
+ .wrapper {
3
+ --theme-colors-checkbox-fg: theme("colors.fg-strong");
4
+ --theme-colors-checkbox-bg: theme("colors.bg-strong");
5
+ --theme-colors-checkbox-bg-checked: theme("colors.fg-strong");
6
+ --theme-colors-checkbox-border: theme("colors.border-subtle");
7
+ --theme-colors-checkbox-border-hover: theme("colors.border-subtle");
8
+ --theme-colors-checkbox-icon: theme("colors.bg-strong");
9
+ --theme-colors-checkbox-outline: transparent;
10
+ --theme-colors-checkbox-outline-hover: theme("colors.bg-dim");
11
+ --theme-colors-checkbox-outline-focus: theme("colors.fg-strong");
12
+ }
13
+ }
14
+
15
+ .wrapper {
16
+ @apply flex items-start gap-x-8;
17
+ }
18
+
19
+ .input {
20
+ @apply sr-only;
21
+ }
22
+
23
+ .box {
24
+ @apply flex-shrink-0 rounded-sm border outline outline-0 outline-transparent transition-all;
25
+
26
+ background: var(--theme-colors-checkbox-bg);
27
+ border-color: var(--theme-colors-checkbox-border);
28
+
29
+ .wrapper[data-size="md"] & {
30
+ @apply h-[19px] w-[19px];
31
+ }
32
+
33
+ .wrapper[data-size="lg"] & {
34
+ @apply h-[21px] w-[21px];
35
+ }
36
+
37
+ .wrapper:hover &,
38
+ .wrapper[data-state="hover"] & {
39
+ @apply outline-4;
40
+
41
+ border-color: var(--theme-colors-checkbox-border-hover);
42
+ outline-color: var(--theme-colors-checkbox-outline-hover);
43
+ }
44
+
45
+ .input:focus + &,
46
+ .wrapper[data-state="focus"] & {
47
+ @apply outline-2 outline-offset-2;
48
+
49
+ border-color: var(--theme-colors-checkbox-border-hover);
50
+ outline-color: var(--theme-colors-checkbox-outline-focus);
51
+ }
52
+
53
+ .input:checked + &,
54
+ .wrapper[data-state="checked"] & {
55
+ background: var(--theme-colors-checkbox-bg-checked);
56
+ }
57
+ }
58
+
59
+ .label {
60
+ @apply -mt-[1px];
61
+
62
+ color: var(--theme-colors-checkbox-fg);
63
+
64
+ .wrapper[data-size="md"] & {
65
+ @apply text-interactive-md;
66
+ }
67
+
68
+ .wrapper[data-size="lg"] & {
69
+ @apply text-interactive-lg;
70
+ }
71
+ }
72
+
73
+ .icon {
74
+ @apply h-full w-full opacity-0 transition-opacity;
75
+
76
+ color: var(--theme-colors-checkbox-icon);
77
+
78
+ .input:checked + .box &,
79
+ .wrapper[data-state="checked"] & {
80
+ @apply opacity-100;
81
+ }
82
+ }