ruler-components 0.1.1 → 0.1.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 (118) hide show
  1. package/dist/index.d.mts +458 -0
  2. package/dist/index.d.ts +458 -0
  3. package/dist/index.js +3618 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/index.mjs +3467 -0
  6. package/dist/index.mjs.map +1 -0
  7. package/package.json +21 -2
  8. package/AGENTS.md +0 -9
  9. package/CLAUDE.md +0 -1
  10. package/app/docs/[slug]/page.tsx +0 -147
  11. package/app/docs/layout.tsx +0 -26
  12. package/app/docs/page.tsx +0 -148
  13. package/app/favicon.ico +0 -0
  14. package/app/globals.css +0 -168
  15. package/app/icon.png +0 -0
  16. package/app/layout.tsx +0 -90
  17. package/app/opengraph-image.tsx +0 -10
  18. package/app/page.tsx +0 -34
  19. package/app/twitter-image.tsx +0 -10
  20. package/components/docs/accordion-doc-page.tsx +0 -352
  21. package/components/docs/alert-doc-page.tsx +0 -293
  22. package/components/docs/allinput-doc-page.tsx +0 -183
  23. package/components/docs/avatar-doc-page.tsx +0 -424
  24. package/components/docs/badge-doc-page.tsx +0 -363
  25. package/components/docs/button-doc-page.tsx +0 -406
  26. package/components/docs/card-doc-page.tsx +0 -364
  27. package/components/docs/checkbox-doc-page.tsx +0 -277
  28. package/components/docs/colors-doc-page.tsx +0 -430
  29. package/components/docs/dialog-doc-page.tsx +0 -364
  30. package/components/docs/docs-footer.tsx +0 -11
  31. package/components/docs/docs-mobile-menu-bar.tsx +0 -22
  32. package/components/docs/docs-mobile-nav-context.tsx +0 -27
  33. package/components/docs/docs-page.tsx +0 -263
  34. package/components/docs/docs-search.tsx +0 -303
  35. package/components/docs/docs-sidebar.tsx +0 -165
  36. package/components/docs/docs-topbar.tsx +0 -32
  37. package/components/docs/dropdown-doc-page.tsx +0 -522
  38. package/components/docs/getting-started-doc-page.tsx +0 -205
  39. package/components/docs/label-doc-page.tsx +0 -173
  40. package/components/docs/loaders-doc-page.tsx +0 -244
  41. package/components/docs/menu-doc-page.tsx +0 -373
  42. package/components/docs/modal-doc-page.tsx +0 -436
  43. package/components/docs/next-steps.tsx +0 -53
  44. package/components/docs/pagination-doc-page.tsx +0 -316
  45. package/components/docs/progress-doc-page.tsx +0 -387
  46. package/components/docs/radio-doc-page.tsx +0 -270
  47. package/components/docs/skeleton-doc-page.tsx +0 -230
  48. package/components/docs/stepper-doc-page.tsx +0 -309
  49. package/components/docs/switch-doc-page.tsx +0 -264
  50. package/components/docs/table-doc-page.tsx +0 -689
  51. package/components/docs/tabs-doc-page.tsx +0 -359
  52. package/components/docs/theming-doc-page.tsx +0 -243
  53. package/components/docs/tooltip-doc-page.tsx +0 -357
  54. package/components/docs/usage-section.tsx +0 -21
  55. package/components/icons/discord.tsx +0 -9
  56. package/components/icons/github.tsx +0 -9
  57. package/components/icons/x.tsx +0 -9
  58. package/components/installation-section.tsx +0 -34
  59. package/components/landing/feature-highlights.tsx +0 -105
  60. package/components/landing/footer-strip.tsx +0 -45
  61. package/components/landing/hero-card.tsx +0 -14
  62. package/components/landing/hero-spotlight.tsx +0 -126
  63. package/components/landing/hero.tsx +0 -64
  64. package/components/landing/navbar.tsx +0 -44
  65. package/components/landing/quick-start-section.tsx +0 -59
  66. package/components/landing/site-footer.tsx +0 -55
  67. package/components/theme-provider.tsx +0 -60
  68. package/components/ui/accordion.tsx +0 -174
  69. package/components/ui/alert.tsx +0 -103
  70. package/components/ui/allinput.tsx +0 -210
  71. package/components/ui/avatar.tsx +0 -179
  72. package/components/ui/badge.tsx +0 -52
  73. package/components/ui/button.tsx +0 -75
  74. package/components/ui/card.tsx +0 -105
  75. package/components/ui/checkbox.tsx +0 -130
  76. package/components/ui/code-block.tsx +0 -60
  77. package/components/ui/data-table.tsx +0 -235
  78. package/components/ui/dialog.tsx +0 -173
  79. package/components/ui/dropdown.tsx +0 -78
  80. package/components/ui/feature-card.tsx +0 -38
  81. package/components/ui/input.tsx +0 -44
  82. package/components/ui/label.tsx +0 -110
  83. package/components/ui/loaders.tsx +0 -139
  84. package/components/ui/menu.tsx +0 -118
  85. package/components/ui/modal.tsx +0 -399
  86. package/components/ui/package-manager-tabs.tsx +0 -40
  87. package/components/ui/pagination.tsx +0 -200
  88. package/components/ui/progress.tsx +0 -134
  89. package/components/ui/radio.tsx +0 -262
  90. package/components/ui/skeleton.tsx +0 -102
  91. package/components/ui/steppers.tsx +0 -309
  92. package/components/ui/switch.tsx +0 -153
  93. package/components/ui/table.tsx +0 -58
  94. package/components/ui/tabs.tsx +0 -166
  95. package/components/ui/theme-toggle.tsx +0 -60
  96. package/components/ui/tooltip.tsx +0 -238
  97. package/data/color-palette.ts +0 -35
  98. package/data/docs-nav.ts +0 -84
  99. package/eslint.config.mjs +0 -18
  100. package/index.ts +0 -8
  101. package/lib/cn.ts +0 -4
  102. package/lib/color.ts +0 -85
  103. package/lib/og-image.tsx +0 -138
  104. package/lib/theme.ts +0 -33
  105. package/next.config.ts +0 -7
  106. package/postcss.config.mjs +0 -7
  107. package/public/dark.png +0 -0
  108. package/public/dark1.png +0 -0
  109. package/public/dark2.png +0 -0
  110. package/public/file.svg +0 -1
  111. package/public/globe.svg +0 -1
  112. package/public/light.png +0 -0
  113. package/public/light1.png +0 -0
  114. package/public/next.svg +0 -1
  115. package/public/vercel.svg +0 -1
  116. package/public/video/hero-demo.mp4 +0 -0
  117. package/public/window.svg +0 -1
  118. package/tsconfig.json +0 -34
@@ -1,364 +0,0 @@
1
- "use client";
2
-
3
- import React, { useState } from "react";
4
- import {
5
- ArrowRight,
6
- Check,
7
- CheckCircle2,
8
- Copy,
9
- LayoutTemplate,
10
- Sparkles,
11
- TrendingUp,
12
- Users,
13
- } from "lucide-react";
14
- import { Button } from "@/components/ui/button";
15
- import {
16
- Card,
17
- CardContent,
18
- CardDescription,
19
- CardFooter,
20
- CardHeader,
21
- CardTitle,
22
- type CardProps,
23
- } from "@/components/ui/card";
24
- import { Badge } from "@/components/ui/badge";
25
- import { Tooltip } from "@/components/ui/tooltip";
26
- import {
27
- DocsAccessibility,
28
- DocsApiSection,
29
- DocsApiTable,
30
- DocsPage,
31
- DocsPageHeader,
32
- DocsSection,
33
- DocsSectionGrid,
34
- DocsSimpleTable,
35
- DocsSubsection,
36
- } from "@/components/docs/docs-page";
37
- import { cn } from "@/lib/cn";
38
-
39
- const API_ROWS = [
40
- { prop: "variant", type: '"default" | "outline" | "elevated" | "interactive"', default: '"default"', description: "The visual style of the card" },
41
- { prop: "children", type: "ReactNode", default: "—", description: "Card content" },
42
- { prop: "className", type: "string", default: "—", description: "Additional CSS classes" },
43
- ];
44
-
45
- const SUBCOMPONENT_ROWS = [
46
- { name: "CardHeader", description: "Top section for title and description" },
47
- { name: "CardTitle", description: "Primary heading inside the card" },
48
- { name: "CardDescription", description: "Supporting text below the title" },
49
- { name: "CardContent", description: "Main body content area" },
50
- { name: "CardFooter", description: "Bottom section for actions" },
51
- ];
52
-
53
- const ACCESSIBILITY_ITEMS = [
54
- "Use semantic headings inside cards for proper document structure.",
55
- "Ensure interactive elements in card footers have accessible labels.",
56
- "Don't rely on card borders alone to convey grouping — use headings.",
57
- "Maintain sufficient contrast between card background and page background.",
58
- "Keep card content concise and scannable.",
59
- ];
60
-
61
- type Variant = NonNullable<CardProps["variant"]>;
62
-
63
- const VARIANTS: { value: Variant; label: string }[] = [
64
- { value: "default", label: "Default" },
65
- { value: "outline", label: "Outline" },
66
- { value: "elevated", label: "Elevated" },
67
- { value: "interactive", label: "Interactive" },
68
- ];
69
-
70
- function codeFor(variant: Variant, withFooter: boolean) {
71
- const openProps = variant !== "default" ? ` variant="${variant}"` : "";
72
- const footer = withFooter
73
- ? `\n <CardFooter>\n <Button size="sm">View report</Button>\n </CardFooter>`
74
- : "";
75
- return `<Card${openProps}>\n <CardHeader>\n <CardTitle>Weekly Performance</CardTitle>\n <CardDescription>Your team velocity compared to last week.</CardDescription>\n </CardHeader>\n <CardContent>...</CardContent>${footer}\n</Card>`;
76
- }
77
-
78
- export function CardDocPage() {
79
- const [variant, setVariant] = useState<Variant>("default");
80
- const [withFooter, setWithFooter] = useState(true);
81
- const [copied, setCopied] = useState(false);
82
-
83
- const snippet = codeFor(variant, withFooter);
84
-
85
- function copySnippet() {
86
- navigator.clipboard.writeText(snippet).catch(() => {});
87
- setCopied(true);
88
- setTimeout(() => setCopied(false), 1200);
89
- }
90
-
91
- return (
92
- <DocsPage>
93
- <DocsPageHeader
94
- icon={LayoutTemplate}
95
- title="Card"
96
- description="Groups related content into a clear, scannable surface — ideal for dashboards, settings, and summaries."
97
- />
98
-
99
- <DocsSection
100
- first
101
- title="Playground"
102
- description="Build a card and copy the exact markup — every variant, live."
103
- >
104
- <div className="overflow-hidden rounded-2xl border border-zinc-200 shadow-[0_2px_8px_rgba(0,0,0,0.04)] dark:border-zinc-800 dark:shadow-[0_2px_8px_rgba(0,0,0,0.2)]">
105
- <div className="relative flex min-h-[14rem] items-center justify-center overflow-hidden bg-zinc-50 p-6 dark:bg-zinc-900/40">
106
- <div
107
- aria-hidden
108
- className="pointer-events-none absolute inset-0 opacity-[0.4] dark:opacity-[0.15]"
109
- style={{
110
- backgroundImage:
111
- "linear-gradient(to right, rgb(161 161 170 / 0.35) 1px, transparent 1px), linear-gradient(to bottom, rgb(161 161 170 / 0.35) 1px, transparent 1px)",
112
- backgroundSize: "24px 24px",
113
- }}
114
- />
115
- <div
116
- key={`${variant}-${withFooter}`}
117
- className="relative w-full max-w-sm animate-[pagination-pop_0.2s_ease-out]"
118
- >
119
- <Card variant={variant}>
120
- <CardHeader>
121
- <div className="flex items-start justify-between gap-3">
122
- <div className="flex h-10 w-10 items-center justify-center rounded-xl bg-zinc-100 text-zinc-700 dark:bg-zinc-800 dark:text-zinc-200">
123
- <TrendingUp className="h-5 w-5" />
124
- </div>
125
- <Badge variant="success">+12%</Badge>
126
- </div>
127
- <CardTitle className="mt-3">Weekly Performance</CardTitle>
128
- <CardDescription>Your team velocity compared to last week.</CardDescription>
129
- </CardHeader>
130
- <CardContent>
131
- <div className="grid grid-cols-2 gap-4">
132
- <div>
133
- <p className="text-xs text-zinc-500 dark:text-zinc-400">Tasks done</p>
134
- <p className="mt-1 text-2xl font-semibold text-zinc-900 dark:text-white">24</p>
135
- </div>
136
- <div>
137
- <p className="text-xs text-zinc-500 dark:text-zinc-400">In progress</p>
138
- <p className="mt-1 text-2xl font-semibold text-zinc-900 dark:text-white">6</p>
139
- </div>
140
- </div>
141
- </CardContent>
142
- {withFooter && (
143
- <CardFooter>
144
- <Button size="sm">View report</Button>
145
- </CardFooter>
146
- )}
147
- </Card>
148
- </div>
149
- </div>
150
-
151
- <div className="flex flex-col gap-5 border-t border-zinc-200 p-5 dark:border-zinc-800">
152
- <div className="flex flex-wrap items-start justify-between gap-6">
153
- <div>
154
- <p className="mb-2 text-xs font-medium uppercase tracking-wide text-zinc-400 dark:text-zinc-500">
155
- Variant
156
- </p>
157
- <div className="flex flex-wrap items-center gap-1 rounded-lg border border-zinc-200 bg-zinc-50 p-1 dark:border-zinc-800 dark:bg-zinc-900/60">
158
- {VARIANTS.map((v) => (
159
- <button
160
- key={v.value}
161
- type="button"
162
- onClick={() => setVariant(v.value)}
163
- className={cn(
164
- "rounded-md px-3 py-1.5 text-xs font-medium transition-colors",
165
- variant === v.value
166
- ? "bg-white text-zinc-900 shadow-sm dark:bg-zinc-800 dark:text-white"
167
- : "text-zinc-500 hover:text-zinc-800 dark:text-zinc-400 dark:hover:text-zinc-200"
168
- )}
169
- >
170
- {v.label}
171
- </button>
172
- ))}
173
- </div>
174
- </div>
175
-
176
- <div>
177
- <p className="mb-2 text-xs font-medium uppercase tracking-wide text-zinc-400 dark:text-zinc-500">
178
- Footer
179
- </p>
180
- <button
181
- type="button"
182
- onClick={() => setWithFooter((v) => !v)}
183
- className={cn(
184
- "flex h-[2.125rem] items-center gap-2 rounded-lg border px-3 text-xs font-medium transition-colors",
185
- withFooter
186
- ? "border-zinc-900 bg-zinc-900 text-white dark:border-white dark:bg-white dark:text-zinc-900"
187
- : "border-zinc-200 text-zinc-500 hover:border-zinc-300 dark:border-zinc-700 dark:text-zinc-400"
188
- )}
189
- >
190
- {withFooter ? "On" : "Off"}
191
- </button>
192
- </div>
193
- </div>
194
-
195
- <div className="flex items-center justify-between gap-3 rounded-xl bg-zinc-900 px-4 py-3 dark:bg-black">
196
- <pre className="overflow-x-auto font-mono text-[13px] leading-relaxed text-zinc-100">
197
- <code>{snippet}</code>
198
- </pre>
199
- <Tooltip content={copied ? "Copied!" : "Copy code"}>
200
- <button
201
- type="button"
202
- onClick={copySnippet}
203
- className="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg text-zinc-400 transition-colors hover:bg-white/10 hover:text-white"
204
- >
205
- {copied ? <Check className="h-4 w-4 text-emerald-400" /> : <Copy className="h-4 w-4" />}
206
- </button>
207
- </Tooltip>
208
- </div>
209
- </div>
210
- </div>
211
- </DocsSection>
212
-
213
- <DocsSection
214
- title="Default"
215
- description="A balanced card with header, body, and a soft footer action area."
216
- >
217
- <div className="max-w-md">
218
- <Card>
219
- <CardHeader>
220
- <div className="flex items-start justify-between gap-3">
221
- <div className="flex h-10 w-10 items-center justify-center rounded-xl bg-zinc-100 text-zinc-700 dark:bg-zinc-800 dark:text-zinc-200">
222
- <TrendingUp className="h-5 w-5" />
223
- </div>
224
- <Badge variant="success">+12%</Badge>
225
- </div>
226
- <CardTitle className="mt-3">Weekly Performance</CardTitle>
227
- <CardDescription>Your team velocity compared to last week.</CardDescription>
228
- </CardHeader>
229
- <CardContent>
230
- <div className="grid grid-cols-2 gap-4">
231
- <div>
232
- <p className="text-xs text-zinc-500 dark:text-zinc-400">Tasks done</p>
233
- <p className="mt-1 text-2xl font-semibold text-zinc-900 dark:text-white">24</p>
234
- </div>
235
- <div>
236
- <p className="text-xs text-zinc-500 dark:text-zinc-400">In progress</p>
237
- <p className="mt-1 text-2xl font-semibold text-zinc-900 dark:text-white">6</p>
238
- </div>
239
- </div>
240
- </CardContent>
241
- <CardFooter>
242
- <Button size="sm">View report</Button>
243
- <Button variant="ghost" size="sm">Share</Button>
244
- </CardFooter>
245
- </Card>
246
- </div>
247
- </DocsSection>
248
-
249
- <DocsSection
250
- title="Variants"
251
- description="Pick the right surface weight for your layout hierarchy."
252
- contentClassName="grid gap-4 sm:grid-cols-2 xl:grid-cols-4"
253
- >
254
- <Card variant="default">
255
- <CardHeader>
256
- <CardTitle>Default</CardTitle>
257
- <CardDescription>Soft shadow for everyday content.</CardDescription>
258
- </CardHeader>
259
- </Card>
260
- <Card variant="outline">
261
- <CardHeader>
262
- <CardTitle>Outline</CardTitle>
263
- <CardDescription>Clean border, no elevation.</CardDescription>
264
- </CardHeader>
265
- </Card>
266
- <Card variant="elevated">
267
- <CardHeader>
268
- <CardTitle>Elevated</CardTitle>
269
- <CardDescription>Stronger depth for emphasis.</CardDescription>
270
- </CardHeader>
271
- </Card>
272
- <Card variant="interactive">
273
- <CardHeader>
274
- <CardTitle className="flex items-center justify-between">
275
- Interactive
276
- <ArrowRight className="h-4 w-4 text-zinc-400" />
277
- </CardTitle>
278
- <CardDescription>Hover to lift — great for links.</CardDescription>
279
- </CardHeader>
280
- </Card>
281
- </DocsSection>
282
-
283
- <DocsSection>
284
- <DocsSectionGrid className="lg:grid-cols-2">
285
- <DocsSubsection title="Pricing Card">
286
- <Card className="flex h-full max-w-sm flex-col">
287
- <CardHeader>
288
- <div className="flex items-center gap-2">
289
- <Sparkles className="h-4 w-4 text-zinc-500" />
290
- <Badge variant="info">Popular</Badge>
291
- </div>
292
- <CardTitle className="mt-2">Pro Plan</CardTitle>
293
- <CardDescription>Everything you need to ship faster.</CardDescription>
294
- </CardHeader>
295
- <CardContent>
296
- <div className="flex items-end gap-1">
297
- <span className="text-4xl font-bold tracking-tight text-zinc-900 dark:text-white">$29</span>
298
- <span className="mb-1 text-sm text-zinc-500 dark:text-zinc-400">/month</span>
299
- </div>
300
- <ul className="mt-5 space-y-2.5 text-sm text-zinc-600 dark:text-zinc-300">
301
- <li className="flex items-center gap-2">
302
- <CheckCircle2 className="h-4 w-4 shrink-0 text-green-500" />
303
- Unlimited projects
304
- </li>
305
- <li className="flex items-center gap-2">
306
- <CheckCircle2 className="h-4 w-4 shrink-0 text-green-500" />
307
- Priority support
308
- </li>
309
- <li className="flex items-center gap-2">
310
- <CheckCircle2 className="h-4 w-4 shrink-0 text-green-500" />
311
- Advanced analytics
312
- </li>
313
- </ul>
314
- </CardContent>
315
- <CardFooter className="mt-auto">
316
- <Button size="sm" className="w-full">Get started</Button>
317
- </CardFooter>
318
- </Card>
319
- </DocsSubsection>
320
-
321
- <DocsSubsection title="Team Card">
322
- <Card className="flex h-full max-w-sm flex-col">
323
- <CardHeader>
324
- <div className="flex items-center gap-3">
325
- <div className="flex h-10 w-10 items-center justify-center rounded-full bg-zinc-900 text-white dark:bg-zinc-100 dark:text-zinc-900">
326
- <Users className="h-5 w-5" />
327
- </div>
328
- <div>
329
- <CardTitle>Design Team</CardTitle>
330
- <CardDescription>5 members · 3 active now</CardDescription>
331
- </div>
332
- </div>
333
- </CardHeader>
334
- <CardContent>
335
- <div className="flex -space-x-2">
336
- {["ZK", "AM", "JR", "LS", "PN"].map((initials) => (
337
- <div
338
- key={initials}
339
- className="flex h-8 w-8 items-center justify-center rounded-full border-2 border-white bg-zinc-200 text-[10px] font-semibold text-zinc-700 dark:border-zinc-900 dark:bg-zinc-700 dark:text-zinc-200"
340
- >
341
- {initials}
342
- </div>
343
- ))}
344
- </div>
345
- <p className="mt-4 text-sm leading-relaxed text-zinc-600 dark:text-zinc-300">
346
- Collaborate on UI components, design tokens, and documentation.
347
- </p>
348
- </CardContent>
349
- <CardFooter className="mt-auto">
350
- <Button variant="ghost" size="sm">Manage team</Button>
351
- </CardFooter>
352
- </Card>
353
- </DocsSubsection>
354
- </DocsSectionGrid>
355
- </DocsSection>
356
-
357
- <DocsApiSection>
358
- <DocsApiTable title="API Reference — Card" rows={API_ROWS} />
359
- <DocsSimpleTable title="Subcomponents" rows={SUBCOMPONENT_ROWS} />
360
- <DocsAccessibility items={ACCESSIBILITY_ITEMS} />
361
- </DocsApiSection>
362
- </DocsPage>
363
- );
364
- }
@@ -1,277 +0,0 @@
1
- "use client";
2
-
3
- import React, { useState } from "react";
4
- import { Check, Copy, SquareCheck } from "lucide-react";
5
- import { Checkbox } from "@/components/ui/checkbox";
6
- import { Tooltip } from "@/components/ui/tooltip";
7
- import {
8
- DocsAccessibility,
9
- DocsApiSection,
10
- DocsApiTable,
11
- DocsPage,
12
- DocsPageHeader,
13
- DocsSection,
14
- DocsSectionGrid,
15
- DocsSubsection,
16
- } from "@/components/docs/docs-page";
17
- import { cn } from "@/lib/cn";
18
-
19
- const API_ROWS = [
20
- { prop: "checked", type: "boolean", default: "false", description: "Controlled checked state" },
21
- { prop: "defaultChecked", type: "boolean", default: "false", description: "Uncontrolled initial checked state" },
22
- { prop: "onChange", type: "(event) => void", default: "—", description: "Change event handler" },
23
- { prop: "disabled", type: "boolean", default: "false", description: "Disables the checkbox" },
24
- { prop: "size", type: '"sm" | "md" | "lg"', default: '"md"', description: "The size of the checkbox" },
25
- { prop: "variant", type: '"inline" | "card"', default: '"inline"', description: "Layout style — card auto-applies when description is set" },
26
- { prop: "label", type: "string", default: "—", description: "Label text displayed beside the checkbox" },
27
- { prop: "description", type: "string", default: "—", description: "Helper text below the label" },
28
- { prop: "className", type: "string", default: "—", description: "Additional CSS classes" },
29
- ];
30
-
31
- const ACCESSIBILITY_ITEMS = [
32
- "Always pair checkboxes with a visible label.",
33
- "Use fieldset and legend for groups of related checkboxes.",
34
- "Ensure focus states are clearly visible.",
35
- "Don't rely on color alone to indicate checked state.",
36
- "Support keyboard interaction with Space to toggle.",
37
- ];
38
-
39
- type Size = "sm" | "md" | "lg";
40
- type Variant = "inline" | "card";
41
-
42
- const SIZES: Size[] = ["sm", "md", "lg"];
43
-
44
- const VARIANTS: { value: Variant; label: string }[] = [
45
- { value: "inline", label: "Inline" },
46
- { value: "card", label: "Card" },
47
- ];
48
-
49
- function codeFor(variant: Variant, size: Size, disabled: boolean, checked: boolean) {
50
- const props = [
51
- size !== "md" && `size="${size}"`,
52
- variant !== "inline" && `variant="${variant}"`,
53
- checked && "defaultChecked",
54
- disabled && "disabled",
55
- ]
56
- .filter(Boolean)
57
- .join(" ");
58
- const descriptionLine = variant === "card" ? '\n description="A helper line of detail."' : "";
59
- const labelLine = `\n label="Accept terms"`;
60
- return `<Checkbox${labelLine}${descriptionLine}${props ? `\n ${props}` : ""}\n/>`;
61
- }
62
-
63
- export function CheckboxDocPage() {
64
- const [notifications, setNotifications] = React.useState({
65
- email: true,
66
- sms: false,
67
- push: true,
68
- });
69
-
70
- const [variant, setVariant] = useState<Variant>("inline");
71
- const [size, setSize] = useState<Size>("md");
72
- const [disabled, setDisabled] = useState(false);
73
- const [checked, setChecked] = useState(true);
74
- const [copied, setCopied] = useState(false);
75
-
76
- const snippet = codeFor(variant, size, disabled, checked);
77
-
78
- function copySnippet() {
79
- navigator.clipboard.writeText(snippet).catch(() => {});
80
- setCopied(true);
81
- setTimeout(() => setCopied(false), 1200);
82
- }
83
-
84
- return (
85
- <DocsPage>
86
- <DocsPageHeader
87
- icon={SquareCheck}
88
- title="Checkbox"
89
- description="Allows users to select one or more options from a set of choices."
90
- />
91
-
92
- <DocsSection
93
- first
94
- title="Playground"
95
- description="Build a checkbox and copy the exact markup — every combination, live."
96
- >
97
- <div className="overflow-hidden rounded-2xl border border-zinc-200 shadow-[0_2px_8px_rgba(0,0,0,0.04)] dark:border-zinc-800 dark:shadow-[0_2px_8px_rgba(0,0,0,0.2)]">
98
- <div className="relative flex min-h-[11rem] items-center justify-center overflow-hidden bg-zinc-50 p-8 dark:bg-zinc-900/40">
99
- <div
100
- aria-hidden
101
- className="pointer-events-none absolute inset-0 opacity-[0.4] dark:opacity-[0.15]"
102
- style={{
103
- backgroundImage:
104
- "linear-gradient(to right, rgb(161 161 170 / 0.35) 1px, transparent 1px), linear-gradient(to bottom, rgb(161 161 170 / 0.35) 1px, transparent 1px)",
105
- backgroundSize: "24px 24px",
106
- }}
107
- />
108
- <div className="relative w-full max-w-xs" key={`${variant}-${size}-${disabled}-${checked}`}>
109
- <Checkbox
110
- variant={variant}
111
- size={size}
112
- disabled={disabled}
113
- checked={checked}
114
- onChange={(e) => setChecked(e.target.checked)}
115
- label="Accept terms"
116
- description={variant === "card" ? "A helper line of detail." : undefined}
117
- className="items-center animate-[pagination-pop_0.25s_ease-out]"
118
- />
119
- </div>
120
- </div>
121
-
122
- <div className="flex flex-col gap-5 border-t border-zinc-200 p-5 dark:border-zinc-800">
123
- <div className="flex flex-wrap items-start justify-between gap-6">
124
- <div>
125
- <p className="mb-2 text-xs font-medium uppercase tracking-wide text-zinc-400 dark:text-zinc-500">
126
- Variant
127
- </p>
128
- <div className="flex flex-wrap items-center gap-1 rounded-lg border border-zinc-200 bg-zinc-50 p-1 dark:border-zinc-800 dark:bg-zinc-900/60">
129
- {VARIANTS.map((v) => (
130
- <button
131
- key={v.value}
132
- type="button"
133
- onClick={() => setVariant(v.value)}
134
- className={cn(
135
- "rounded-md px-3 py-1.5 text-xs font-medium transition-colors",
136
- variant === v.value
137
- ? "bg-white text-zinc-900 shadow-sm dark:bg-zinc-800 dark:text-white"
138
- : "text-zinc-500 hover:text-zinc-800 dark:text-zinc-400 dark:hover:text-zinc-200"
139
- )}
140
- >
141
- {v.label}
142
- </button>
143
- ))}
144
- </div>
145
- </div>
146
-
147
- <div>
148
- <p className="mb-2 text-xs font-medium uppercase tracking-wide text-zinc-400 dark:text-zinc-500">
149
- Size
150
- </p>
151
- <div className="flex flex-wrap items-center gap-1 rounded-lg border border-zinc-200 bg-zinc-50 p-1 dark:border-zinc-800 dark:bg-zinc-900/60">
152
- {SIZES.map((s) => (
153
- <button
154
- key={s}
155
- type="button"
156
- onClick={() => setSize(s)}
157
- className={cn(
158
- "rounded-md px-3 py-1.5 text-xs font-medium uppercase tracking-wide transition-colors",
159
- size === s
160
- ? "bg-white text-zinc-900 shadow-sm dark:bg-zinc-800 dark:text-white"
161
- : "text-zinc-500 hover:text-zinc-800 dark:text-zinc-400 dark:hover:text-zinc-200"
162
- )}
163
- >
164
- {s}
165
- </button>
166
- ))}
167
- </div>
168
- </div>
169
-
170
- <div>
171
- <p className="mb-2 text-xs font-medium uppercase tracking-wide text-zinc-400 dark:text-zinc-500">
172
- State
173
- </p>
174
- <button
175
- type="button"
176
- onClick={() => setDisabled((v) => !v)}
177
- className={cn(
178
- "flex h-[2.125rem] items-center gap-2 rounded-lg border px-3 text-xs font-medium transition-colors",
179
- disabled
180
- ? "border-zinc-900 bg-zinc-900 text-white dark:border-white dark:bg-white dark:text-zinc-900"
181
- : "border-zinc-200 text-zinc-500 hover:border-zinc-300 dark:border-zinc-700 dark:text-zinc-400"
182
- )}
183
- >
184
- <SquareCheck className="h-3.5 w-3.5" />
185
- {disabled ? "Disabled" : "Enabled"}
186
- </button>
187
- </div>
188
- </div>
189
-
190
- <div className="flex items-center justify-between gap-3 rounded-xl bg-zinc-900 px-4 py-3 dark:bg-black">
191
- <pre className="overflow-x-auto font-mono text-[13px] leading-relaxed text-zinc-100">
192
- <code>{snippet}</code>
193
- </pre>
194
- <Tooltip content={copied ? "Copied!" : "Copy code"}>
195
- <button
196
- type="button"
197
- onClick={copySnippet}
198
- className="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg text-zinc-400 transition-colors hover:bg-white/10 hover:text-white"
199
- >
200
- {copied ? <Check className="h-4 w-4 text-emerald-400" /> : <Copy className="h-4 w-4" />}
201
- </button>
202
- </Tooltip>
203
- </div>
204
- </div>
205
- </div>
206
- </DocsSection>
207
-
208
- <DocsSection>
209
- <DocsSectionGrid>
210
- <DocsSubsection title="Sizes">
211
- <div className="flex flex-col gap-2.5">
212
- <Checkbox size="sm" label="Small" defaultChecked />
213
- <Checkbox size="md" label="Medium" defaultChecked />
214
- <Checkbox size="lg" label="Large" defaultChecked />
215
- </div>
216
- </DocsSubsection>
217
- <DocsSubsection title="Disabled">
218
- <div className="flex flex-col gap-2.5">
219
- <Checkbox label="Disabled unchecked" disabled />
220
- <Checkbox label="Disabled checked" defaultChecked disabled />
221
- </div>
222
- </DocsSubsection>
223
- </DocsSectionGrid>
224
- </DocsSection>
225
-
226
- <DocsSection
227
- title="With Description"
228
- description="Card layout automatically applies for options with helper text."
229
- >
230
- <Checkbox
231
- label="Accept terms and conditions"
232
- description="You agree to our Terms of Service and Privacy Policy."
233
- />
234
- </DocsSection>
235
-
236
- <DocsSection
237
- title="Notification Preferences"
238
- description="Card-style checkboxes make multi-option settings easy to scan and tap."
239
- >
240
- <div className="flex max-w-md flex-col gap-2.5">
241
- <Checkbox
242
- variant="card"
243
- label="Email notifications"
244
- description="Receive updates and alerts in your inbox."
245
- checked={notifications.email}
246
- onChange={(e) =>
247
- setNotifications((prev) => ({ ...prev, email: e.target.checked }))
248
- }
249
- />
250
- <Checkbox
251
- variant="card"
252
- label="SMS notifications"
253
- description="Get text messages for urgent updates."
254
- checked={notifications.sms}
255
- onChange={(e) =>
256
- setNotifications((prev) => ({ ...prev, sms: e.target.checked }))
257
- }
258
- />
259
- <Checkbox
260
- variant="card"
261
- label="Push notifications"
262
- description="Instant alerts delivered to your device."
263
- checked={notifications.push}
264
- onChange={(e) =>
265
- setNotifications((prev) => ({ ...prev, push: e.target.checked }))
266
- }
267
- />
268
- </div>
269
- </DocsSection>
270
-
271
- <DocsApiSection>
272
- <DocsApiTable title="API Reference" rows={API_ROWS} />
273
- <DocsAccessibility items={ACCESSIBILITY_ITEMS} />
274
- </DocsApiSection>
275
- </DocsPage>
276
- );
277
- }