@alpic-ai/ui 0.0.0-dev.4a35dc7 → 0.0.0-dev.6953a69

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 (99) hide show
  1. package/dist/components/accordion-card.d.mts +1 -1
  2. package/dist/components/accordion.d.mts +1 -1
  3. package/dist/components/alert.d.mts +1 -1
  4. package/dist/components/attachment-tile.mjs +1 -1
  5. package/dist/components/avatar.d.mts +1 -1
  6. package/dist/components/breadcrumb.d.mts +1 -1
  7. package/dist/components/button.d.mts +1 -1
  8. package/dist/components/card.d.mts +1 -1
  9. package/dist/components/checkbox.d.mts +1 -1
  10. package/dist/components/collapsible.d.mts +1 -1
  11. package/dist/components/combobox.d.mts +1 -1
  12. package/dist/components/combobox.mjs +2 -2
  13. package/dist/components/command.d.mts +1 -1
  14. package/dist/components/copyable.d.mts +1 -1
  15. package/dist/components/copyable.mjs +1 -1
  16. package/dist/components/description-list.d.mts +1 -1
  17. package/dist/components/dialog.d.mts +1 -1
  18. package/dist/components/dialog.mjs +2 -2
  19. package/dist/components/dropdown-menu.d.mts +1 -1
  20. package/dist/components/form.d.mts +119 -0
  21. package/dist/components/form.mjs +192 -0
  22. package/dist/components/input-group.d.mts +1 -1
  23. package/dist/components/input.d.mts +3 -1
  24. package/dist/components/input.mjs +20 -11
  25. package/dist/components/label.d.mts +1 -1
  26. package/dist/components/pagination.d.mts +1 -1
  27. package/dist/components/popover.d.mts +1 -1
  28. package/dist/components/radio-group.d.mts +1 -1
  29. package/dist/components/scroll-area.d.mts +1 -1
  30. package/dist/components/select-trigger-variants.mjs +1 -0
  31. package/dist/components/select.d.mts +2 -10
  32. package/dist/components/select.mjs +8 -28
  33. package/dist/components/separator.d.mts +1 -1
  34. package/dist/components/sheet.d.mts +1 -1
  35. package/dist/components/sidebar.d.mts +1 -1
  36. package/dist/components/sidebar.mjs +8 -8
  37. package/dist/components/sonner.d.mts +1 -1
  38. package/dist/components/switch.d.mts +1 -1
  39. package/dist/components/table.d.mts +1 -1
  40. package/dist/components/tabs.d.mts +1 -1
  41. package/dist/components/tabs.mjs +1 -1
  42. package/dist/components/textarea.d.mts +3 -1
  43. package/dist/components/textarea.mjs +20 -11
  44. package/dist/components/toggle-group.d.mts +1 -1
  45. package/dist/components/toggle-group.mjs +1 -1
  46. package/dist/components/tooltip-icon-button.mjs +1 -1
  47. package/dist/components/tooltip.d.mts +1 -1
  48. package/package.json +10 -11
  49. package/src/components/combobox.tsx +1 -1
  50. package/src/components/dialog.tsx +2 -2
  51. package/src/components/form.tsx +343 -0
  52. package/src/components/input.tsx +12 -0
  53. package/src/components/select-trigger-variants.ts +1 -0
  54. package/src/components/select.tsx +2 -35
  55. package/src/components/sidebar.tsx +8 -10
  56. package/src/components/textarea.tsx +12 -1
  57. package/src/stories/accordion-card.stories.tsx +53 -0
  58. package/src/stories/accordion.stories.tsx +65 -0
  59. package/src/stories/alert.stories.tsx +58 -0
  60. package/src/stories/attachment-tile.stories.tsx +37 -0
  61. package/src/stories/avatar.stories.tsx +54 -0
  62. package/src/stories/badge.stories.tsx +50 -0
  63. package/src/stories/breadcrumb.stories.tsx +107 -0
  64. package/src/stories/button.stories.tsx +342 -0
  65. package/src/stories/card.stories.tsx +89 -0
  66. package/src/stories/checkbox.stories.tsx +56 -0
  67. package/src/stories/collapsible.stories.tsx +69 -0
  68. package/src/stories/combobox.stories.tsx +214 -0
  69. package/src/stories/command.stories.tsx +95 -0
  70. package/src/stories/copyable.stories.tsx +29 -0
  71. package/src/stories/description-list.stories.tsx +71 -0
  72. package/src/stories/dialog.stories.tsx +135 -0
  73. package/src/stories/dropdown-menu.stories.tsx +191 -0
  74. package/src/stories/form.stories.tsx +91 -0
  75. package/src/stories/input-group.stories.tsx +63 -0
  76. package/src/stories/input.stories.tsx +72 -0
  77. package/src/stories/label.stories.tsx +26 -0
  78. package/src/stories/ladle.css +3 -0
  79. package/src/stories/pagination.stories.tsx +35 -0
  80. package/src/stories/popover.stories.tsx +34 -0
  81. package/src/stories/radio-group.stories.tsx +59 -0
  82. package/src/stories/scroll-area.stories.tsx +43 -0
  83. package/src/stories/select.stories.tsx +95 -0
  84. package/src/stories/separator.stories.tsx +36 -0
  85. package/src/stories/sheet.stories.tsx +76 -0
  86. package/src/stories/sidebar.stories.tsx +255 -0
  87. package/src/stories/skeleton.stories.tsx +47 -0
  88. package/src/stories/sonner.stories.tsx +91 -0
  89. package/src/stories/spinner.stories.tsx +66 -0
  90. package/src/stories/status-dot.stories.tsx +27 -0
  91. package/src/stories/switch.stories.tsx +46 -0
  92. package/src/stories/table.stories.tsx +242 -0
  93. package/src/stories/tabs.stories.tsx +169 -0
  94. package/src/stories/tag.stories.tsx +82 -0
  95. package/src/stories/textarea.stories.tsx +60 -0
  96. package/src/stories/toggle-group.stories.tsx +142 -0
  97. package/src/stories/tooltip-icon-button.stories.tsx +59 -0
  98. package/src/stories/tooltip.stories.tsx +54 -0
  99. package/README.md +0 -33
@@ -0,0 +1,58 @@
1
+ import type { Story } from "@ladle/react";
2
+ import { AlertCircle, AlertTriangle, CheckCircle2, Info } from "lucide-react";
3
+
4
+ import { Alert, AlertDescription, AlertTitle, ErrorAlert, WarningAlert } from "../components/alert";
5
+
6
+ export const AllVariants: Story = () => (
7
+ <div className="flex flex-col gap-4 max-w-xl p-6">
8
+ <p className="type-text-xs font-medium text-subtle-foreground">Default</p>
9
+ <Alert>
10
+ <Info />
11
+ <AlertTitle>Best on desktop</AlertTitle>
12
+ <AlertDescription>
13
+ This site isn't optimised for small screens. For the best experience we recommend using a desktop or tablet.
14
+ </AlertDescription>
15
+ </Alert>
16
+
17
+ <p className="type-text-xs font-medium text-subtle-foreground">Destructive</p>
18
+ <Alert variant="destructive">
19
+ <AlertCircle />
20
+ <AlertTitle>Clone failed</AlertTitle>
21
+ <AlertDescription>Unable to clone the repository. Check your credentials and try again.</AlertDescription>
22
+ </Alert>
23
+
24
+ <p className="type-text-xs font-medium text-subtle-foreground">Warning</p>
25
+ <Alert variant="warning">
26
+ <AlertTriangle />
27
+ <AlertTitle>API key expiring soon</AlertTitle>
28
+ <AlertDescription>Your API key expires in 3 days. Rotate it to avoid service interruption.</AlertDescription>
29
+ </Alert>
30
+
31
+ <p className="type-text-xs font-medium text-subtle-foreground">Success</p>
32
+ <Alert variant="success">
33
+ <CheckCircle2 />
34
+ <AlertTitle>Deployment complete</AlertTitle>
35
+ <AlertDescription>Your project was deployed successfully and is now live.</AlertDescription>
36
+ </Alert>
37
+
38
+ <p className="type-text-xs font-medium text-subtle-foreground">Description only (no title)</p>
39
+ <Alert variant="destructive">
40
+ <AlertCircle />
41
+ <AlertDescription>
42
+ This is the only time you'll be able to see this API key. Make sure to copy it and store it securely.
43
+ </AlertDescription>
44
+ </Alert>
45
+
46
+ <p className="type-text-xs font-medium text-subtle-foreground">ErrorAlert (pre-composed)</p>
47
+ <ErrorAlert />
48
+
49
+ <p className="type-text-xs font-medium text-subtle-foreground">ErrorAlert (custom)</p>
50
+ <ErrorAlert title="Error loading projects" description="Failed to fetch your projects. Please refresh the page." />
51
+
52
+ <p className="type-text-xs font-medium text-subtle-foreground">WarningAlert</p>
53
+ <WarningAlert
54
+ title="Save your API key"
55
+ description="This is the only time you'll be able to see this API key. Make sure to copy it and store it securely."
56
+ />
57
+ </div>
58
+ );
@@ -0,0 +1,37 @@
1
+ import type { Story } from "@ladle/react";
2
+ import { AttachmentTile } from "../components/attachment-tile";
3
+
4
+ export const AllVariants: Story = () => (
5
+ <div className="flex flex-col gap-10 p-10">
6
+ <div className="flex flex-col gap-1.5">
7
+ <p className="type-text-xs font-medium text-subtle-foreground">Image attachment (with remove)</p>
8
+ <div className="flex gap-3">
9
+ <AttachmentTile
10
+ src="https://picsum.photos/seed/a/200/200"
11
+ isImage
12
+ onRemove={() => alert("Remove clicked")}
13
+ onClick={() => alert("Preview clicked")}
14
+ />
15
+ <AttachmentTile
16
+ src="https://picsum.photos/seed/b/200/200"
17
+ isImage
18
+ onRemove={() => alert("Remove clicked")}
19
+ onClick={() => alert("Preview clicked")}
20
+ />
21
+ </div>
22
+ </div>
23
+
24
+ <div className="flex flex-col gap-1.5">
25
+ <p className="type-text-xs font-medium text-subtle-foreground">File attachment (fallback icon)</p>
26
+ <AttachmentTile onRemove={() => alert("Remove clicked")} onClick={() => alert("Preview clicked")} />
27
+ </div>
28
+
29
+ <div className="flex flex-col gap-1.5">
30
+ <p className="type-text-xs font-medium text-subtle-foreground">Read-only (no remove button)</p>
31
+ <div className="flex gap-3">
32
+ <AttachmentTile src="https://picsum.photos/seed/c/200/200" isImage />
33
+ <AttachmentTile />
34
+ </div>
35
+ </div>
36
+ </div>
37
+ );
@@ -0,0 +1,54 @@
1
+ import type { Story } from "@ladle/react";
2
+ import { Avatar, AvatarFallback, AvatarImage, AvatarLabelGroup } from "../components/avatar";
3
+
4
+ const DEMO_SRC = "https://i.pravatar.cc/150";
5
+ const SIZES = ["xs", "sm", "md", "lg", "xl"] as const;
6
+
7
+ export const AllVariants: Story = () => (
8
+ <div className="flex flex-col gap-8 p-6 bg-background">
9
+ <div className="flex flex-col gap-3">
10
+ <p className="type-text-xs font-medium text-subtle-foreground">Sizes — with image</p>
11
+ <div className="flex items-center gap-4">
12
+ {SIZES.map((size) => (
13
+ <Avatar key={size} size={size}>
14
+ <AvatarImage src={DEMO_SRC} alt="User" />
15
+ <AvatarFallback>JD</AvatarFallback>
16
+ </Avatar>
17
+ ))}
18
+ </div>
19
+ </div>
20
+
21
+ <div className="flex flex-col gap-3">
22
+ <p className="type-text-xs font-medium text-subtle-foreground">Sizes — fallback (no image)</p>
23
+ <div className="flex items-center gap-4">
24
+ {SIZES.map((size) => (
25
+ <Avatar key={size} size={size}>
26
+ <AvatarFallback>OR</AvatarFallback>
27
+ </Avatar>
28
+ ))}
29
+ </div>
30
+ </div>
31
+
32
+ <div className="flex flex-col gap-3">
33
+ <p className="type-text-xs font-medium text-subtle-foreground">Online status indicator</p>
34
+ <div className="flex items-center gap-4">
35
+ {SIZES.map((size) => (
36
+ <Avatar key={size} size={size} status="online">
37
+ <AvatarImage src={DEMO_SRC} alt="User" />
38
+ <AvatarFallback>JD</AvatarFallback>
39
+ </Avatar>
40
+ ))}
41
+ </div>
42
+ </div>
43
+
44
+ <div className="flex flex-col gap-3">
45
+ <p className="type-text-xs font-medium text-subtle-foreground">Label group</p>
46
+ <div className="flex flex-col gap-4">
47
+ <AvatarLabelGroup size="sm" src={DEMO_SRC} name="Alice Martin" label="alice@example.com" />
48
+ <AvatarLabelGroup size="md" src={DEMO_SRC} name="Bob Dupont" label="bob@example.com" />
49
+ <AvatarLabelGroup size="md" src={DEMO_SRC} name="Charly Bernard" label="charly@example.com" status="online" />
50
+ <AvatarLabelGroup size="md" name="Daniel Wilson" label="daniel@example.com" />
51
+ </div>
52
+ </div>
53
+ </div>
54
+ );
@@ -0,0 +1,50 @@
1
+ import type { Story } from "@ladle/react";
2
+ import { AlertTriangle, CheckCircle2, XCircle } from "lucide-react";
3
+
4
+ import { Badge } from "../components/badge";
5
+
6
+ export const AllVariants: Story = () => (
7
+ <div className="flex flex-col gap-6">
8
+ <div className="flex flex-col gap-1.5">
9
+ <p className="type-text-xs font-medium text-subtle-foreground">Medium (default)</p>
10
+ <div className="flex items-center gap-2">
11
+ <Badge variant="primary">Primary</Badge>
12
+ <Badge>Secondary</Badge>
13
+ <Badge variant="success">
14
+ <CheckCircle2 />
15
+ Success
16
+ </Badge>
17
+ <Badge variant="warning">
18
+ <AlertTriangle />
19
+ Warning
20
+ </Badge>
21
+ <Badge variant="error">
22
+ <XCircle />
23
+ Error
24
+ </Badge>
25
+ </div>
26
+ </div>
27
+
28
+ <div className="flex flex-col gap-1.5">
29
+ <p className="type-text-xs font-medium text-subtle-foreground">Small</p>
30
+ <div className="flex items-center gap-2">
31
+ <Badge size="sm" variant="primary">
32
+ Primary
33
+ </Badge>
34
+ <Badge size="sm">Secondary</Badge>
35
+ <Badge size="sm" variant="success">
36
+ <CheckCircle2 />
37
+ Success
38
+ </Badge>
39
+ <Badge size="sm" variant="warning">
40
+ <AlertTriangle />
41
+ Warning
42
+ </Badge>
43
+ <Badge size="sm" variant="error">
44
+ <XCircle />
45
+ Error
46
+ </Badge>
47
+ </div>
48
+ </div>
49
+ </div>
50
+ );
@@ -0,0 +1,107 @@
1
+ import type { Story } from "@ladle/react";
2
+ import { Home } from "lucide-react";
3
+ import { useState } from "react";
4
+ import {
5
+ Breadcrumb,
6
+ BreadcrumbChevron,
7
+ BreadcrumbItem,
8
+ BreadcrumbLink,
9
+ BreadcrumbList,
10
+ BreadcrumbPage,
11
+ BreadcrumbSeparator,
12
+ } from "../components/breadcrumb";
13
+ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "../components/dropdown-menu";
14
+
15
+ const TREE: Record<string, string[]> = {
16
+ Home: ["Projects", "Settings", "Billing"],
17
+ Projects: ["my-mcp-server", "weather-api", "slack-bot"],
18
+ "my-mcp-server": ["Deployments", "Logs", "Environment"],
19
+ };
20
+
21
+ export const AllVariants: Story = () => {
22
+ const [trail, setTrail] = useState(["Home", "Projects", "my-mcp-server"]);
23
+
24
+ function handleSelect(index: number, option: string) {
25
+ setTrail([...trail.slice(0, index + 1), option]);
26
+ }
27
+
28
+ return (
29
+ <div className="flex flex-col gap-10">
30
+ <div className="flex flex-col gap-1.5">
31
+ <p className="type-text-xs font-medium text-subtle-foreground">
32
+ Interactive — click items to navigate, click chevrons for dropdown
33
+ </p>
34
+ <Breadcrumb>
35
+ <BreadcrumbList>
36
+ {trail.map((page, index) => {
37
+ const isLast = index === trail.length - 1;
38
+ const children = TREE[page];
39
+ return (
40
+ <li key={page} className="contents">
41
+ {index > 0 && <BreadcrumbSeparator />}
42
+ <DropdownMenu>
43
+ <DropdownMenuTrigger asChild>
44
+ <BreadcrumbItem className="cursor-pointer focus-visible:ring-2 focus-visible:ring-ring outline-none">
45
+ {isLast ? (
46
+ <BreadcrumbPage>{page}</BreadcrumbPage>
47
+ ) : (
48
+ <span className="type-text-sm font-medium text-subtle-foreground">{page}</span>
49
+ )}
50
+ {children && <BreadcrumbChevron />}
51
+ </BreadcrumbItem>
52
+ </DropdownMenuTrigger>
53
+ {children && (
54
+ <DropdownMenuContent align="start">
55
+ {children.map((child) => (
56
+ <DropdownMenuItem key={child} onSelect={() => handleSelect(index, child)}>
57
+ {child}
58
+ </DropdownMenuItem>
59
+ ))}
60
+ </DropdownMenuContent>
61
+ )}
62
+ </DropdownMenu>
63
+ </li>
64
+ );
65
+ })}
66
+ </BreadcrumbList>
67
+ </Breadcrumb>
68
+ </div>
69
+
70
+ <div className="flex flex-col gap-1.5">
71
+ <p className="type-text-xs font-medium text-subtle-foreground">With home icon (static)</p>
72
+ <Breadcrumb>
73
+ <BreadcrumbList>
74
+ <BreadcrumbItem>
75
+ <BreadcrumbLink href="#">
76
+ <Home className="size-5" />
77
+ </BreadcrumbLink>
78
+ </BreadcrumbItem>
79
+ <BreadcrumbSeparator />
80
+ <BreadcrumbItem>
81
+ <BreadcrumbLink href="#">Projects</BreadcrumbLink>
82
+ </BreadcrumbItem>
83
+ <BreadcrumbSeparator />
84
+ <BreadcrumbItem>
85
+ <BreadcrumbPage>my-mcp-server</BreadcrumbPage>
86
+ </BreadcrumbItem>
87
+ </BreadcrumbList>
88
+ </Breadcrumb>
89
+ </div>
90
+
91
+ <div className="flex flex-col gap-1.5">
92
+ <p className="type-text-xs font-medium text-subtle-foreground">Simple — two levels</p>
93
+ <Breadcrumb>
94
+ <BreadcrumbList>
95
+ <BreadcrumbItem>
96
+ <BreadcrumbLink href="#">Projects</BreadcrumbLink>
97
+ </BreadcrumbItem>
98
+ <BreadcrumbSeparator />
99
+ <BreadcrumbItem>
100
+ <BreadcrumbPage>my-mcp-server</BreadcrumbPage>
101
+ </BreadcrumbItem>
102
+ </BreadcrumbList>
103
+ </Breadcrumb>
104
+ </div>
105
+ </div>
106
+ );
107
+ };
@@ -0,0 +1,342 @@
1
+ import { Plus } from "lucide-react";
2
+
3
+ import { Button } from "../components/button";
4
+
5
+ // Simulated states via className — matches Figma page layout:
6
+ // variants stacked top-to-bottom, states left-to-right.
7
+
8
+ const VARIANT_LABEL = "type-text-xs text-muted-foreground w-20 shrink-0";
9
+ const STATE_HEADER = "type-text-xs text-muted-foreground font-medium w-32 text-center";
10
+ const SECTION_HEADER = "type-text-xs text-muted-foreground font-semibold uppercase tracking-wide pt-4";
11
+ const ROW = "flex items-center gap-2";
12
+ const CELL = "flex w-32 items-center justify-center";
13
+ const ICON_CELL = "flex w-16 items-center justify-center";
14
+ const ICON_STATE_HEADER = "type-text-xs text-muted-foreground font-medium w-16 text-center";
15
+
16
+ export const AllVariants = () => {
17
+ return (
18
+ <div className="flex flex-col gap-3 p-8">
19
+ {/* ── Text buttons ────────────────────────────────────────────────── */}
20
+ <span className={SECTION_HEADER}>Text</span>
21
+
22
+ <div className={ROW}>
23
+ <div className={VARIANT_LABEL} />
24
+ <div className={STATE_HEADER}>Default</div>
25
+ <div className={STATE_HEADER}>Disabled</div>
26
+ <div className={STATE_HEADER}>Loading</div>
27
+ </div>
28
+
29
+ {/* Primary */}
30
+ <div className={ROW}>
31
+ <span className={VARIANT_LABEL}>Primary</span>
32
+ <div className={CELL}>
33
+ <Button variant="primary" icon={<Plus />}>
34
+ Button CTA
35
+ </Button>
36
+ </div>
37
+ <div className={CELL}>
38
+ <Button variant="primary" icon={<Plus />} disabled>
39
+ Button CTA
40
+ </Button>
41
+ </div>
42
+ <div className={CELL}>
43
+ <Button variant="primary" icon={<Plus />} loading>
44
+ Button CTA
45
+ </Button>
46
+ </div>
47
+ </div>
48
+
49
+ {/* Secondary */}
50
+ <div className={ROW}>
51
+ <span className={VARIANT_LABEL}>Secondary</span>
52
+ <div className={CELL}>
53
+ <Button variant="secondary" icon={<Plus />}>
54
+ Button CTA
55
+ </Button>
56
+ </div>
57
+ <div className={CELL}>
58
+ <Button variant="secondary" icon={<Plus />} disabled>
59
+ Button CTA
60
+ </Button>
61
+ </div>
62
+ <div className={CELL}>
63
+ <Button variant="secondary" icon={<Plus />} loading>
64
+ Button CTA
65
+ </Button>
66
+ </div>
67
+ </div>
68
+
69
+ {/* Tertiary */}
70
+ <div className={ROW}>
71
+ <span className={VARIANT_LABEL}>Tertiary</span>
72
+ <div className={CELL}>
73
+ <Button variant="tertiary" icon={<Plus />}>
74
+ Button CTA
75
+ </Button>
76
+ </div>
77
+ <div className={CELL}>
78
+ <Button variant="tertiary" icon={<Plus />} disabled>
79
+ Button CTA
80
+ </Button>
81
+ </div>
82
+ <div className={CELL}>
83
+ <Button variant="tertiary" icon={<Plus />} loading>
84
+ Button CTA
85
+ </Button>
86
+ </div>
87
+ </div>
88
+
89
+ {/* Link color */}
90
+ <div className={ROW}>
91
+ <span className={VARIANT_LABEL}>Link</span>
92
+ <div className={CELL}>
93
+ <Button variant="link">Button CTA</Button>
94
+ </div>
95
+ <div className={CELL}>
96
+ <Button variant="link" disabled>
97
+ Button CTA
98
+ </Button>
99
+ </div>
100
+ <div className={CELL}>
101
+ <Button variant="link" loading>
102
+ Button CTA
103
+ </Button>
104
+ </div>
105
+ </div>
106
+
107
+ {/* Link gray */}
108
+ <div className={ROW}>
109
+ <span className={VARIANT_LABEL}>Link muted</span>
110
+ <div className={CELL}>
111
+ <Button variant="link-muted">Button CTA</Button>
112
+ </div>
113
+ <div className={CELL}>
114
+ <Button variant="link-muted" disabled>
115
+ Button CTA
116
+ </Button>
117
+ </div>
118
+ <div className={CELL}>
119
+ <Button variant="link-muted" loading>
120
+ Button CTA
121
+ </Button>
122
+ </div>
123
+ </div>
124
+
125
+ {/* Destructive */}
126
+ <div className={ROW}>
127
+ <span className={VARIANT_LABEL}>Destructive</span>
128
+ <div className={CELL}>
129
+ <Button variant="destructive" icon={<Plus />}>
130
+ Button CTA
131
+ </Button>
132
+ </div>
133
+ <div className={CELL}>
134
+ <Button variant="destructive" icon={<Plus />} disabled>
135
+ Button CTA
136
+ </Button>
137
+ </div>
138
+ <div className={CELL}>
139
+ <Button variant="destructive" icon={<Plus />} loading>
140
+ Button CTA
141
+ </Button>
142
+ </div>
143
+ </div>
144
+
145
+ {/* ── Icon only ───────────────────────────────────────────────────── */}
146
+ <span className={SECTION_HEADER}>Icon only</span>
147
+
148
+ <div className={ROW}>
149
+ <div className={VARIANT_LABEL} />
150
+ <div className={ICON_STATE_HEADER}>Default</div>
151
+ <div className={ICON_STATE_HEADER}>Hover</div>
152
+ <div className={ICON_STATE_HEADER}>Disabled</div>
153
+ <div className={ICON_STATE_HEADER}>Loading</div>
154
+ </div>
155
+
156
+ <div className={ROW}>
157
+ <span className={VARIANT_LABEL}>Primary</span>
158
+ <div className={ICON_CELL}>
159
+ <Button size="icon" variant="primary" icon={<Plus />} aria-label="Add" />
160
+ </div>
161
+ <div className={ICON_CELL}>
162
+ <Button size="icon" variant="primary" icon={<Plus />} className="bg-primary-hover" aria-label="Add" />
163
+ </div>
164
+ <div className={ICON_CELL}>
165
+ <Button size="icon" variant="primary" icon={<Plus />} disabled aria-label="Add" />
166
+ </div>
167
+ <div className={ICON_CELL}>
168
+ <Button size="icon" variant="primary" icon={<Plus />} loading aria-label="Add" />
169
+ </div>
170
+ </div>
171
+
172
+ <div className={ROW}>
173
+ <span className={VARIANT_LABEL}>Secondary</span>
174
+ <div className={ICON_CELL}>
175
+ <Button size="icon" variant="secondary" icon={<Plus />} aria-label="Add" />
176
+ </div>
177
+ <div className={ICON_CELL}>
178
+ <Button
179
+ size="icon"
180
+ variant="secondary"
181
+ icon={<Plus />}
182
+ className="bg-background-hover text-muted-foreground-hover"
183
+ aria-label="Add"
184
+ />
185
+ </div>
186
+ <div className={ICON_CELL}>
187
+ <Button size="icon" variant="secondary" icon={<Plus />} disabled aria-label="Add" />
188
+ </div>
189
+ <div className={ICON_CELL}>
190
+ <Button size="icon" variant="secondary" icon={<Plus />} loading aria-label="Add" />
191
+ </div>
192
+ </div>
193
+
194
+ <div className={ROW}>
195
+ <span className={VARIANT_LABEL}>Tertiary</span>
196
+ <div className={ICON_CELL}>
197
+ <Button size="icon" variant="tertiary" icon={<Plus />} aria-label="Add" />
198
+ </div>
199
+ <div className={ICON_CELL}>
200
+ <Button
201
+ size="icon"
202
+ variant="tertiary"
203
+ icon={<Plus />}
204
+ className="bg-background-hover text-muted-foreground-hover"
205
+ aria-label="Add"
206
+ />
207
+ </div>
208
+ <div className={ICON_CELL}>
209
+ <Button size="icon" variant="tertiary" icon={<Plus />} disabled aria-label="Add" />
210
+ </div>
211
+ <div className={ICON_CELL}>
212
+ <Button size="icon" variant="tertiary" icon={<Plus />} loading aria-label="Add" />
213
+ </div>
214
+ </div>
215
+
216
+ {/* ── Icon rounded ────────────────────────────────────────────────── */}
217
+ <span className={SECTION_HEADER}>Icon rounded</span>
218
+
219
+ <div className={ROW}>
220
+ <div className={VARIANT_LABEL} />
221
+ <div className={ICON_STATE_HEADER}>Default</div>
222
+ <div className={ICON_STATE_HEADER}>Hover</div>
223
+ <div className={ICON_STATE_HEADER}>Disabled</div>
224
+ <div className={ICON_STATE_HEADER}>Loading</div>
225
+ </div>
226
+
227
+ <div className={ROW}>
228
+ <span className={VARIANT_LABEL}>Primary</span>
229
+ <div className={ICON_CELL}>
230
+ <Button size="icon-rounded" variant="primary" icon={<Plus />} aria-label="Add" />
231
+ </div>
232
+ <div className={ICON_CELL}>
233
+ <Button size="icon-rounded" variant="primary" icon={<Plus />} className="bg-primary-hover" aria-label="Add" />
234
+ </div>
235
+ <div className={ICON_CELL}>
236
+ <Button size="icon-rounded" variant="primary" icon={<Plus />} disabled aria-label="Add" />
237
+ </div>
238
+ <div className={ICON_CELL}>
239
+ <Button size="icon-rounded" variant="primary" icon={<Plus />} loading aria-label="Add" />
240
+ </div>
241
+ </div>
242
+
243
+ <div className={ROW}>
244
+ <span className={VARIANT_LABEL}>Secondary</span>
245
+ <div className={ICON_CELL}>
246
+ <Button size="icon-rounded" variant="secondary" icon={<Plus />} aria-label="Add" />
247
+ </div>
248
+ <div className={ICON_CELL}>
249
+ <Button
250
+ size="icon-rounded"
251
+ variant="secondary"
252
+ icon={<Plus />}
253
+ className="bg-background-hover text-muted-foreground-hover"
254
+ aria-label="Add"
255
+ />
256
+ </div>
257
+ <div className={ICON_CELL}>
258
+ <Button size="icon-rounded" variant="secondary" icon={<Plus />} disabled aria-label="Add" />
259
+ </div>
260
+ <div className={ICON_CELL}>
261
+ <Button size="icon-rounded" variant="secondary" icon={<Plus />} loading aria-label="Add" />
262
+ </div>
263
+ </div>
264
+
265
+ <div className={ROW}>
266
+ <span className={VARIANT_LABEL}>Tertiary</span>
267
+ <div className={ICON_CELL}>
268
+ <Button size="icon-rounded" variant="tertiary" icon={<Plus />} aria-label="Add" />
269
+ </div>
270
+ <div className={ICON_CELL}>
271
+ <Button
272
+ size="icon-rounded"
273
+ variant="tertiary"
274
+ icon={<Plus />}
275
+ className="bg-background-hover text-muted-foreground-hover"
276
+ aria-label="Add"
277
+ />
278
+ </div>
279
+ <div className={ICON_CELL}>
280
+ <Button size="icon-rounded" variant="tertiary" icon={<Plus />} disabled aria-label="Add" />
281
+ </div>
282
+ <div className={ICON_CELL}>
283
+ <Button size="icon-rounded" variant="tertiary" icon={<Plus />} loading aria-label="Add" />
284
+ </div>
285
+ </div>
286
+
287
+ {/* ── Pill ──────────────────────────────────────────────────────────── */}
288
+ <span className={SECTION_HEADER}>Pill</span>
289
+
290
+ <div className="flex items-center gap-3">
291
+ <Button size="pill" variant="primary">
292
+ Label
293
+ </Button>
294
+ <Button size="pill" variant="secondary">
295
+ Label
296
+ </Button>
297
+ <Button size="pill" variant="secondary" disabled>
298
+ Label
299
+ </Button>
300
+ <Button size="pill" variant="secondary" loading>
301
+ Label
302
+ </Button>
303
+ </div>
304
+
305
+ {/* ── With icon (leading) ──────────────────────────────────────────── */}
306
+ <span className={SECTION_HEADER}>With icon</span>
307
+
308
+ <div className="flex items-center gap-3">
309
+ <Button variant="primary" icon={<Plus />}>
310
+ Button CTA
311
+ </Button>
312
+ <Button variant="secondary" icon={<Plus />}>
313
+ Button CTA
314
+ </Button>
315
+ <Button variant="tertiary" icon={<Plus />}>
316
+ Button CTA
317
+ </Button>
318
+ <Button variant="link" icon={<Plus />}>
319
+ Button CTA
320
+ </Button>
321
+ <Button variant="link-muted" icon={<Plus />}>
322
+ Button CTA
323
+ </Button>
324
+ </div>
325
+
326
+ {/* ── asChild ─────────────────────────────────────────────────────── */}
327
+ <span className={SECTION_HEADER}>asChild</span>
328
+
329
+ <div className="flex items-center gap-3">
330
+ <Button asChild variant="primary">
331
+ <a href="/docs">Rendered as &lt;a&gt;</a>
332
+ </Button>
333
+ <Button asChild variant="secondary">
334
+ <a href="/docs">Rendered as &lt;a&gt;</a>
335
+ </Button>
336
+ <Button asChild variant="tertiary">
337
+ <a href="/docs">Rendered as &lt;a&gt;</a>
338
+ </Button>
339
+ </div>
340
+ </div>
341
+ );
342
+ };