ruler-components 0.1.1 → 0.1.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.
- package/dist/index.d.mts +51 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.js +534 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +498 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +21 -2
- package/AGENTS.md +0 -9
- package/CLAUDE.md +0 -1
- package/app/docs/[slug]/page.tsx +0 -147
- package/app/docs/layout.tsx +0 -26
- package/app/docs/page.tsx +0 -148
- package/app/favicon.ico +0 -0
- package/app/globals.css +0 -168
- package/app/icon.png +0 -0
- package/app/layout.tsx +0 -90
- package/app/opengraph-image.tsx +0 -10
- package/app/page.tsx +0 -34
- package/app/twitter-image.tsx +0 -10
- package/components/docs/accordion-doc-page.tsx +0 -352
- package/components/docs/alert-doc-page.tsx +0 -293
- package/components/docs/allinput-doc-page.tsx +0 -183
- package/components/docs/avatar-doc-page.tsx +0 -424
- package/components/docs/badge-doc-page.tsx +0 -363
- package/components/docs/button-doc-page.tsx +0 -406
- package/components/docs/card-doc-page.tsx +0 -364
- package/components/docs/checkbox-doc-page.tsx +0 -277
- package/components/docs/colors-doc-page.tsx +0 -430
- package/components/docs/dialog-doc-page.tsx +0 -364
- package/components/docs/docs-footer.tsx +0 -11
- package/components/docs/docs-mobile-menu-bar.tsx +0 -22
- package/components/docs/docs-mobile-nav-context.tsx +0 -27
- package/components/docs/docs-page.tsx +0 -263
- package/components/docs/docs-search.tsx +0 -303
- package/components/docs/docs-sidebar.tsx +0 -165
- package/components/docs/docs-topbar.tsx +0 -32
- package/components/docs/dropdown-doc-page.tsx +0 -522
- package/components/docs/getting-started-doc-page.tsx +0 -205
- package/components/docs/label-doc-page.tsx +0 -173
- package/components/docs/loaders-doc-page.tsx +0 -244
- package/components/docs/menu-doc-page.tsx +0 -373
- package/components/docs/modal-doc-page.tsx +0 -436
- package/components/docs/next-steps.tsx +0 -53
- package/components/docs/pagination-doc-page.tsx +0 -316
- package/components/docs/progress-doc-page.tsx +0 -387
- package/components/docs/radio-doc-page.tsx +0 -270
- package/components/docs/skeleton-doc-page.tsx +0 -230
- package/components/docs/stepper-doc-page.tsx +0 -309
- package/components/docs/switch-doc-page.tsx +0 -264
- package/components/docs/table-doc-page.tsx +0 -689
- package/components/docs/tabs-doc-page.tsx +0 -359
- package/components/docs/theming-doc-page.tsx +0 -243
- package/components/docs/tooltip-doc-page.tsx +0 -357
- package/components/docs/usage-section.tsx +0 -21
- package/components/icons/discord.tsx +0 -9
- package/components/icons/github.tsx +0 -9
- package/components/icons/x.tsx +0 -9
- package/components/installation-section.tsx +0 -34
- package/components/landing/feature-highlights.tsx +0 -105
- package/components/landing/footer-strip.tsx +0 -45
- package/components/landing/hero-card.tsx +0 -14
- package/components/landing/hero-spotlight.tsx +0 -126
- package/components/landing/hero.tsx +0 -64
- package/components/landing/navbar.tsx +0 -44
- package/components/landing/quick-start-section.tsx +0 -59
- package/components/landing/site-footer.tsx +0 -55
- package/components/theme-provider.tsx +0 -60
- package/components/ui/accordion.tsx +0 -174
- package/components/ui/alert.tsx +0 -103
- package/components/ui/allinput.tsx +0 -210
- package/components/ui/avatar.tsx +0 -179
- package/components/ui/badge.tsx +0 -52
- package/components/ui/button.tsx +0 -75
- package/components/ui/card.tsx +0 -105
- package/components/ui/checkbox.tsx +0 -130
- package/components/ui/code-block.tsx +0 -60
- package/components/ui/data-table.tsx +0 -235
- package/components/ui/dialog.tsx +0 -173
- package/components/ui/dropdown.tsx +0 -78
- package/components/ui/feature-card.tsx +0 -38
- package/components/ui/input.tsx +0 -44
- package/components/ui/label.tsx +0 -110
- package/components/ui/loaders.tsx +0 -139
- package/components/ui/menu.tsx +0 -118
- package/components/ui/modal.tsx +0 -399
- package/components/ui/package-manager-tabs.tsx +0 -40
- package/components/ui/pagination.tsx +0 -200
- package/components/ui/progress.tsx +0 -134
- package/components/ui/radio.tsx +0 -262
- package/components/ui/skeleton.tsx +0 -102
- package/components/ui/steppers.tsx +0 -309
- package/components/ui/switch.tsx +0 -153
- package/components/ui/table.tsx +0 -58
- package/components/ui/tabs.tsx +0 -166
- package/components/ui/theme-toggle.tsx +0 -60
- package/components/ui/tooltip.tsx +0 -238
- package/data/color-palette.ts +0 -35
- package/data/docs-nav.ts +0 -84
- package/eslint.config.mjs +0 -18
- package/index.ts +0 -8
- package/lib/cn.ts +0 -4
- package/lib/color.ts +0 -85
- package/lib/og-image.tsx +0 -138
- package/lib/theme.ts +0 -33
- package/next.config.ts +0 -7
- package/postcss.config.mjs +0 -7
- package/public/dark.png +0 -0
- package/public/dark1.png +0 -0
- package/public/dark2.png +0 -0
- package/public/file.svg +0 -1
- package/public/globe.svg +0 -1
- package/public/light.png +0 -0
- package/public/light1.png +0 -0
- package/public/next.svg +0 -1
- package/public/vercel.svg +0 -1
- package/public/video/hero-demo.mp4 +0 -0
- package/public/window.svg +0 -1
- package/tsconfig.json +0 -34
|
@@ -1,522 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import React, { useState } from "react";
|
|
4
|
-
import { ArrowUpDown, Calendar, Check, ChevronDown, Copy, Filter, LogOut, Pencil, Search, Settings, Trash2, User } from "lucide-react";
|
|
5
|
-
import { Dropdown, DropdownTrigger, DropdownContent, DropdownItem, DropdownLabel, DropdownDivider } from "@/components/ui/dropdown";
|
|
6
|
-
import { Card, CardHeader, CardTitle, CardDescription, CardContent } from "@/components/ui/card";
|
|
7
|
-
import { Badge } from "@/components/ui/badge";
|
|
8
|
-
import { Button } from "@/components/ui/button";
|
|
9
|
-
import { Tooltip } from "@/components/ui/tooltip";
|
|
10
|
-
import {
|
|
11
|
-
DocsAccessibility,
|
|
12
|
-
DocsApiSection,
|
|
13
|
-
DocsApiTable,
|
|
14
|
-
DocsPage,
|
|
15
|
-
DocsPageHeader,
|
|
16
|
-
DocsSection,
|
|
17
|
-
DocsSectionGrid,
|
|
18
|
-
} from "@/components/docs/docs-page";
|
|
19
|
-
import { cn } from "@/lib/cn";
|
|
20
|
-
|
|
21
|
-
const DROPDOWN_API_ROWS = [
|
|
22
|
-
{ prop: "children", type: "ReactNode", default: "—", description: "A DropdownTrigger and DropdownContent pair" },
|
|
23
|
-
];
|
|
24
|
-
|
|
25
|
-
const TRIGGER_API_ROWS = [
|
|
26
|
-
{ prop: "children", type: "ReactElement", default: "—", description: "A single element cloned with the open/close click handler" },
|
|
27
|
-
];
|
|
28
|
-
|
|
29
|
-
const CONTENT_API_ROWS = [
|
|
30
|
-
{ prop: "children", type: "ReactNode", default: "—", description: "DropdownItem, DropdownLabel, and DropdownDivider elements" },
|
|
31
|
-
{ prop: "align", type: '"left" | "right"', default: '"left"', description: "Anchors the panel to the trigger's left or right edge" },
|
|
32
|
-
{ prop: "className", type: "string", default: "—", description: "Additional CSS classes" },
|
|
33
|
-
];
|
|
34
|
-
|
|
35
|
-
const ITEM_API_ROWS = [
|
|
36
|
-
{ prop: "label", type: "string", default: "—", description: "Row text" },
|
|
37
|
-
{ prop: "icon", type: "LucideIcon", default: "—", description: "Optional leading icon" },
|
|
38
|
-
{ prop: "selected", type: "boolean", default: "false", description: "Shows a trailing check mark" },
|
|
39
|
-
{ prop: "onClick", type: "() => void", default: "—", description: "Called when the item is chosen" },
|
|
40
|
-
{ prop: "variant", type: '"default" | "destructive"', default: '"default"', description: "Red styling for irreversible actions like sign-out" },
|
|
41
|
-
];
|
|
42
|
-
|
|
43
|
-
const ACCESSIBILITY_ITEMS = [
|
|
44
|
-
"DropdownContent carries role=\"menu\" and each DropdownItem is a real <button> with role=\"menuitem\" — reachable and activatable via keyboard by default.",
|
|
45
|
-
"The trigger gets aria-haspopup=\"menu\" and aria-expanded, so assistive tech announces the menu's state.",
|
|
46
|
-
"Pressing Escape or clicking outside the panel closes it, matching platform conventions.",
|
|
47
|
-
"DropdownDivider carries role=\"separator\" — it's structural, not another option.",
|
|
48
|
-
"Pair the destructive item variant with an explicit label, like \"Log out\" rather than a bare icon.",
|
|
49
|
-
];
|
|
50
|
-
|
|
51
|
-
type Align = "left" | "right";
|
|
52
|
-
|
|
53
|
-
const ALIGNMENTS: { value: Align; label: string }[] = [
|
|
54
|
-
{ value: "left", label: "Left" },
|
|
55
|
-
{ value: "right", label: "Right" },
|
|
56
|
-
];
|
|
57
|
-
|
|
58
|
-
function codeFor(align: Align, withIcons: boolean, withDestructive: boolean) {
|
|
59
|
-
const contentProps = align !== "left" ? ` align="${align}"` : "";
|
|
60
|
-
const items = [
|
|
61
|
-
withIcons ? `<DropdownItem label="Edit" icon={Pencil} />` : `<DropdownItem label="Edit" />`,
|
|
62
|
-
withIcons ? `<DropdownItem label="Duplicate" icon={Copy} />` : `<DropdownItem label="Duplicate" />`,
|
|
63
|
-
];
|
|
64
|
-
if (withDestructive) {
|
|
65
|
-
items.push("<DropdownDivider />");
|
|
66
|
-
items.push(
|
|
67
|
-
withIcons
|
|
68
|
-
? `<DropdownItem label="Delete" icon={Trash2} variant="destructive" />`
|
|
69
|
-
: `<DropdownItem label="Delete" variant="destructive" />`
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
const body = items.join("\n ");
|
|
73
|
-
return `<Dropdown>\n <DropdownTrigger>\n <Button variant="outline">Options <ChevronDown size={16} /></Button>\n </DropdownTrigger>\n <DropdownContent${contentProps}>\n ${body}\n </DropdownContent>\n</Dropdown>`;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export function DropdownDocPage() {
|
|
77
|
-
const [selectedCountry, setSelectedCountry] = useState("United States");
|
|
78
|
-
const [multiSelect, setMultiSelect] = useState(["React"]);
|
|
79
|
-
const [cascading, setCascading] = useState({ country: "Select", state: "Select" });
|
|
80
|
-
|
|
81
|
-
const [align, setAlign] = useState<Align>("left");
|
|
82
|
-
const [withIcons, setWithIcons] = useState(true);
|
|
83
|
-
const [withDestructive, setWithDestructive] = useState(true);
|
|
84
|
-
const [copied, setCopied] = useState(false);
|
|
85
|
-
|
|
86
|
-
const snippet = codeFor(align, withIcons, withDestructive);
|
|
87
|
-
|
|
88
|
-
function copySnippet() {
|
|
89
|
-
navigator.clipboard.writeText(snippet).catch(() => {});
|
|
90
|
-
setCopied(true);
|
|
91
|
-
setTimeout(() => setCopied(false), 1200);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
return (
|
|
95
|
-
<DocsPage>
|
|
96
|
-
<DocsPageHeader
|
|
97
|
-
icon={ChevronDown}
|
|
98
|
-
title="Dropdown"
|
|
99
|
-
description="A contextual menu anchored to a trigger — for selection, navigation, filtering, and account actions."
|
|
100
|
-
/>
|
|
101
|
-
|
|
102
|
-
<DocsSection
|
|
103
|
-
first
|
|
104
|
-
title="Playground"
|
|
105
|
-
description="Build a dropdown menu and copy the exact markup — alignment, icons, and destructive actions, live."
|
|
106
|
-
>
|
|
107
|
-
<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)]">
|
|
108
|
-
<div className="relative flex min-h-[16rem] items-center justify-center overflow-visible bg-zinc-50 p-6 dark:bg-zinc-900/40">
|
|
109
|
-
<div
|
|
110
|
-
aria-hidden
|
|
111
|
-
className="pointer-events-none absolute inset-0 opacity-[0.4] dark:opacity-[0.15]"
|
|
112
|
-
style={{
|
|
113
|
-
backgroundImage:
|
|
114
|
-
"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)",
|
|
115
|
-
backgroundSize: "24px 24px",
|
|
116
|
-
}}
|
|
117
|
-
/>
|
|
118
|
-
<div key={`${align}-${withIcons}-${withDestructive}`} className="relative animate-[pagination-pop_0.2s_ease-out]">
|
|
119
|
-
<Dropdown>
|
|
120
|
-
<DropdownTrigger>
|
|
121
|
-
<Button variant="outline">
|
|
122
|
-
Options <ChevronDown size={16} />
|
|
123
|
-
</Button>
|
|
124
|
-
</DropdownTrigger>
|
|
125
|
-
<DropdownContent align={align} className="w-52">
|
|
126
|
-
{withIcons ? (
|
|
127
|
-
<DropdownItem label="Edit" icon={Pencil} />
|
|
128
|
-
) : (
|
|
129
|
-
<DropdownItem label="Edit" />
|
|
130
|
-
)}
|
|
131
|
-
{withIcons ? (
|
|
132
|
-
<DropdownItem label="Duplicate" icon={Copy} />
|
|
133
|
-
) : (
|
|
134
|
-
<DropdownItem label="Duplicate" />
|
|
135
|
-
)}
|
|
136
|
-
{withDestructive && (
|
|
137
|
-
<>
|
|
138
|
-
<DropdownDivider />
|
|
139
|
-
{withIcons ? (
|
|
140
|
-
<DropdownItem label="Delete" icon={Trash2} variant="destructive" />
|
|
141
|
-
) : (
|
|
142
|
-
<DropdownItem label="Delete" variant="destructive" />
|
|
143
|
-
)}
|
|
144
|
-
</>
|
|
145
|
-
)}
|
|
146
|
-
</DropdownContent>
|
|
147
|
-
</Dropdown>
|
|
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
|
-
Alignment
|
|
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
|
-
{ALIGNMENTS.map((a) => (
|
|
159
|
-
<button
|
|
160
|
-
key={a.value}
|
|
161
|
-
type="button"
|
|
162
|
-
onClick={() => setAlign(a.value)}
|
|
163
|
-
className={cn(
|
|
164
|
-
"rounded-md px-3 py-1.5 text-xs font-medium uppercase tracking-wide transition-colors",
|
|
165
|
-
align === a.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
|
-
{a.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
|
-
With icons
|
|
179
|
-
</p>
|
|
180
|
-
<button
|
|
181
|
-
type="button"
|
|
182
|
-
onClick={() => setWithIcons((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
|
-
withIcons
|
|
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
|
-
{withIcons ? "On" : "Off"}
|
|
191
|
-
</button>
|
|
192
|
-
</div>
|
|
193
|
-
|
|
194
|
-
<div>
|
|
195
|
-
<p className="mb-2 text-xs font-medium uppercase tracking-wide text-zinc-400 dark:text-zinc-500">
|
|
196
|
-
With destructive item
|
|
197
|
-
</p>
|
|
198
|
-
<button
|
|
199
|
-
type="button"
|
|
200
|
-
onClick={() => setWithDestructive((v) => !v)}
|
|
201
|
-
className={cn(
|
|
202
|
-
"flex h-[2.125rem] items-center gap-2 rounded-lg border px-3 text-xs font-medium transition-colors",
|
|
203
|
-
withDestructive
|
|
204
|
-
? "border-zinc-900 bg-zinc-900 text-white dark:border-white dark:bg-white dark:text-zinc-900"
|
|
205
|
-
: "border-zinc-200 text-zinc-500 hover:border-zinc-300 dark:border-zinc-700 dark:text-zinc-400"
|
|
206
|
-
)}
|
|
207
|
-
>
|
|
208
|
-
{withDestructive ? "On" : "Off"}
|
|
209
|
-
</button>
|
|
210
|
-
</div>
|
|
211
|
-
</div>
|
|
212
|
-
|
|
213
|
-
<div className="flex items-center justify-between gap-3 rounded-xl bg-zinc-900 px-4 py-3 dark:bg-black">
|
|
214
|
-
<pre className="overflow-x-auto font-mono text-[13px] leading-relaxed text-zinc-100">
|
|
215
|
-
<code>{snippet}</code>
|
|
216
|
-
</pre>
|
|
217
|
-
<Tooltip content={copied ? "Copied!" : "Copy code"}>
|
|
218
|
-
<button
|
|
219
|
-
type="button"
|
|
220
|
-
onClick={copySnippet}
|
|
221
|
-
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"
|
|
222
|
-
>
|
|
223
|
-
{copied ? <Check className="h-4 w-4 text-emerald-400" /> : <Copy className="h-4 w-4" />}
|
|
224
|
-
</button>
|
|
225
|
-
</Tooltip>
|
|
226
|
-
</div>
|
|
227
|
-
</div>
|
|
228
|
-
</div>
|
|
229
|
-
</DocsSection>
|
|
230
|
-
|
|
231
|
-
<DocsSection title="Default" description="An account menu — the most common dropdown pattern in any app header.">
|
|
232
|
-
<Card className="max-w-xl">
|
|
233
|
-
<CardHeader className="border-b border-zinc-100 dark:border-zinc-800">
|
|
234
|
-
<div className="flex items-center justify-between gap-4">
|
|
235
|
-
<div>
|
|
236
|
-
<CardTitle>Account menu</CardTitle>
|
|
237
|
-
<CardDescription>Anchored to a trigger, dismissed on outside click or Escape.</CardDescription>
|
|
238
|
-
</div>
|
|
239
|
-
<Badge variant="outline">Interactive</Badge>
|
|
240
|
-
</div>
|
|
241
|
-
</CardHeader>
|
|
242
|
-
<CardContent className="pt-6">
|
|
243
|
-
<Dropdown>
|
|
244
|
-
<DropdownTrigger>
|
|
245
|
-
<div className="flex h-10 w-10 cursor-pointer items-center justify-center rounded-full bg-zinc-100 transition-colors hover:bg-zinc-200 dark:bg-zinc-800 dark:hover:bg-zinc-700">
|
|
246
|
-
<User size={20} className="text-zinc-600 dark:text-zinc-400" />
|
|
247
|
-
</div>
|
|
248
|
-
</DropdownTrigger>
|
|
249
|
-
<DropdownContent align="left" className="w-56">
|
|
250
|
-
<div className="px-3 py-2">
|
|
251
|
-
<p className="text-sm font-bold text-zinc-900 dark:text-white">John Doe</p>
|
|
252
|
-
<p className="text-xs text-zinc-500 dark:text-zinc-400">john@example.com</p>
|
|
253
|
-
</div>
|
|
254
|
-
<DropdownDivider />
|
|
255
|
-
<DropdownItem label="Profile" icon={User} />
|
|
256
|
-
<DropdownItem label="Settings" icon={Settings} />
|
|
257
|
-
<DropdownDivider />
|
|
258
|
-
<DropdownItem label="Log out" icon={LogOut} variant="destructive" />
|
|
259
|
-
</DropdownContent>
|
|
260
|
-
</Dropdown>
|
|
261
|
-
</CardContent>
|
|
262
|
-
</Card>
|
|
263
|
-
</DocsSection>
|
|
264
|
-
|
|
265
|
-
<DocsSection title="Selection & Search" description="Core selection behaviors for single and filtered data.">
|
|
266
|
-
<DocsSectionGrid>
|
|
267
|
-
<Card>
|
|
268
|
-
<CardHeader>
|
|
269
|
-
<CardTitle className="text-base">Select</CardTitle>
|
|
270
|
-
<CardDescription>A labeled list with a checkmark on the current selection.</CardDescription>
|
|
271
|
-
</CardHeader>
|
|
272
|
-
<CardContent>
|
|
273
|
-
<Dropdown>
|
|
274
|
-
<DropdownTrigger>
|
|
275
|
-
<Button variant="outline" className="w-full justify-between">
|
|
276
|
-
{selectedCountry} <ChevronDown size={16} />
|
|
277
|
-
</Button>
|
|
278
|
-
</DropdownTrigger>
|
|
279
|
-
<DropdownContent className="w-56">
|
|
280
|
-
<DropdownLabel>Country</DropdownLabel>
|
|
281
|
-
<DropdownItem label="United States" selected={selectedCountry === "United States"} onClick={() => setSelectedCountry("United States")} />
|
|
282
|
-
<DropdownItem label="Canada" selected={selectedCountry === "Canada"} onClick={() => setSelectedCountry("Canada")} />
|
|
283
|
-
<DropdownItem label="United Kingdom" selected={selectedCountry === "United Kingdom"} onClick={() => setSelectedCountry("United Kingdom")} />
|
|
284
|
-
</DropdownContent>
|
|
285
|
-
</Dropdown>
|
|
286
|
-
</CardContent>
|
|
287
|
-
</Card>
|
|
288
|
-
|
|
289
|
-
<Card>
|
|
290
|
-
<CardHeader>
|
|
291
|
-
<CardTitle className="text-base">Searchable</CardTitle>
|
|
292
|
-
<CardDescription>An input embedded at the top of the panel for filtering long lists.</CardDescription>
|
|
293
|
-
</CardHeader>
|
|
294
|
-
<CardContent>
|
|
295
|
-
<Dropdown>
|
|
296
|
-
<DropdownTrigger>
|
|
297
|
-
<Button variant="outline" className="w-full justify-between">
|
|
298
|
-
Select category <Search size={14} />
|
|
299
|
-
</Button>
|
|
300
|
-
</DropdownTrigger>
|
|
301
|
-
<DropdownContent className="w-64">
|
|
302
|
-
<div className="p-2">
|
|
303
|
-
<div className="flex items-center gap-2 rounded-md border border-zinc-200 bg-zinc-50 px-2 py-1.5 dark:border-zinc-800 dark:bg-zinc-900">
|
|
304
|
-
<Search size={14} className="text-zinc-400" />
|
|
305
|
-
<input className="w-full bg-transparent text-sm text-zinc-900 outline-none placeholder:text-zinc-400 dark:text-zinc-100" placeholder="Search..." />
|
|
306
|
-
</div>
|
|
307
|
-
</div>
|
|
308
|
-
<DropdownDivider />
|
|
309
|
-
<DropdownItem label="Technology" />
|
|
310
|
-
<DropdownItem label="Healthcare" />
|
|
311
|
-
<DropdownItem label="Finance" />
|
|
312
|
-
</DropdownContent>
|
|
313
|
-
</Dropdown>
|
|
314
|
-
</CardContent>
|
|
315
|
-
</Card>
|
|
316
|
-
</DocsSectionGrid>
|
|
317
|
-
</DocsSection>
|
|
318
|
-
|
|
319
|
-
<DocsSection title="Multi-Select & Suggestions" description="Handles complex selection states and type-ahead suggestions.">
|
|
320
|
-
<DocsSectionGrid>
|
|
321
|
-
<Card>
|
|
322
|
-
<CardHeader>
|
|
323
|
-
<CardTitle className="text-base">Multi-select</CardTitle>
|
|
324
|
-
<CardDescription>Toggle several options without the panel closing.</CardDescription>
|
|
325
|
-
</CardHeader>
|
|
326
|
-
<CardContent>
|
|
327
|
-
<Dropdown>
|
|
328
|
-
<DropdownTrigger>
|
|
329
|
-
<Button variant="outline" className="w-full justify-between">
|
|
330
|
-
Stack ({multiSelect.length}) <ChevronDown size={16} />
|
|
331
|
-
</Button>
|
|
332
|
-
</DropdownTrigger>
|
|
333
|
-
<DropdownContent className="w-56">
|
|
334
|
-
{["React", "Next.js", "Tailwind", "TypeScript"].map((tech) => (
|
|
335
|
-
<DropdownItem
|
|
336
|
-
key={tech}
|
|
337
|
-
label={tech}
|
|
338
|
-
selected={multiSelect.includes(tech)}
|
|
339
|
-
onClick={() => setMultiSelect((prev) => (prev.includes(tech) ? prev.filter((t) => t !== tech) : [...prev, tech]))}
|
|
340
|
-
/>
|
|
341
|
-
))}
|
|
342
|
-
</DropdownContent>
|
|
343
|
-
</Dropdown>
|
|
344
|
-
</CardContent>
|
|
345
|
-
</Card>
|
|
346
|
-
|
|
347
|
-
<Card>
|
|
348
|
-
<CardHeader>
|
|
349
|
-
<CardTitle className="text-base">Autocomplete</CardTitle>
|
|
350
|
-
<CardDescription>DropdownItem composed under a search field for type-ahead suggestions.</CardDescription>
|
|
351
|
-
</CardHeader>
|
|
352
|
-
<CardContent>
|
|
353
|
-
<div className="relative w-full">
|
|
354
|
-
<input
|
|
355
|
-
className="w-full rounded-lg border border-zinc-200 bg-white p-2.5 text-sm text-zinc-900 outline-none transition-colors placeholder:text-zinc-400 focus:border-zinc-900 focus:ring-2 focus:ring-zinc-900/10 dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-100 dark:focus:border-zinc-400 dark:focus:ring-zinc-400/15"
|
|
356
|
-
placeholder="Type to search..."
|
|
357
|
-
defaultValue="A"
|
|
358
|
-
readOnly
|
|
359
|
-
/>
|
|
360
|
-
<div className="relative z-10 mt-1.5 w-full rounded-lg border border-zinc-100 bg-white p-1 shadow-[0_4px_12px_rgba(0,0,0,0.08)] dark:border-zinc-800 dark:bg-zinc-950">
|
|
361
|
-
<DropdownItem label="Apple" />
|
|
362
|
-
<DropdownItem label="Amazon" />
|
|
363
|
-
<DropdownItem label="Adobe" />
|
|
364
|
-
</div>
|
|
365
|
-
</div>
|
|
366
|
-
</CardContent>
|
|
367
|
-
</Card>
|
|
368
|
-
</DocsSectionGrid>
|
|
369
|
-
</DocsSection>
|
|
370
|
-
|
|
371
|
-
<DocsSection title="Navigation & Filtering" description="Common patterns for site navigation and dataset filters.">
|
|
372
|
-
<DocsSectionGrid>
|
|
373
|
-
<Card>
|
|
374
|
-
<CardHeader>
|
|
375
|
-
<CardTitle className="text-base">Navigation menu</CardTitle>
|
|
376
|
-
<CardDescription>A wider panel with grouped descriptions, ideal for a top nav.</CardDescription>
|
|
377
|
-
</CardHeader>
|
|
378
|
-
<CardContent>
|
|
379
|
-
<Dropdown>
|
|
380
|
-
<DropdownTrigger>
|
|
381
|
-
<Button variant="outline" className="w-full justify-between">
|
|
382
|
-
Resources <ChevronDown size={16} />
|
|
383
|
-
</Button>
|
|
384
|
-
</DropdownTrigger>
|
|
385
|
-
<DropdownContent className="w-72 p-2">
|
|
386
|
-
<div className="grid gap-1">
|
|
387
|
-
<div className="group cursor-pointer rounded-md p-3 hover:bg-zinc-50 dark:hover:bg-zinc-900">
|
|
388
|
-
<p className="text-sm font-bold text-zinc-900 group-hover:text-zinc-900 dark:text-zinc-100 dark:group-hover:text-white">Documentation</p>
|
|
389
|
-
<p className="text-xs text-zinc-400">Guides and API reference.</p>
|
|
390
|
-
</div>
|
|
391
|
-
<div className="group cursor-pointer rounded-md p-3 hover:bg-zinc-50 dark:hover:bg-zinc-900">
|
|
392
|
-
<p className="text-sm font-bold text-zinc-900 dark:text-zinc-100">Showcase</p>
|
|
393
|
-
<p className="text-xs text-zinc-400">Apps built with our UI.</p>
|
|
394
|
-
</div>
|
|
395
|
-
</div>
|
|
396
|
-
</DropdownContent>
|
|
397
|
-
</Dropdown>
|
|
398
|
-
</CardContent>
|
|
399
|
-
</Card>
|
|
400
|
-
|
|
401
|
-
<Card>
|
|
402
|
-
<CardHeader>
|
|
403
|
-
<CardTitle className="text-base">Filter</CardTitle>
|
|
404
|
-
<CardDescription>Grouped options under labeled sections.</CardDescription>
|
|
405
|
-
</CardHeader>
|
|
406
|
-
<CardContent>
|
|
407
|
-
<Dropdown>
|
|
408
|
-
<DropdownTrigger>
|
|
409
|
-
<Button variant="outline" className="w-full">
|
|
410
|
-
<Filter size={14} />
|
|
411
|
-
Filter options
|
|
412
|
-
</Button>
|
|
413
|
-
</DropdownTrigger>
|
|
414
|
-
<DropdownContent className="w-52">
|
|
415
|
-
<DropdownLabel>Price range</DropdownLabel>
|
|
416
|
-
<DropdownItem label="$0 – $50" />
|
|
417
|
-
<DropdownItem label="$50 – $200" />
|
|
418
|
-
<DropdownDivider />
|
|
419
|
-
<DropdownLabel>Status</DropdownLabel>
|
|
420
|
-
<DropdownItem label="Available" />
|
|
421
|
-
<DropdownItem label="Out of stock" />
|
|
422
|
-
</DropdownContent>
|
|
423
|
-
</Dropdown>
|
|
424
|
-
</CardContent>
|
|
425
|
-
</Card>
|
|
426
|
-
</DocsSectionGrid>
|
|
427
|
-
</DocsSection>
|
|
428
|
-
|
|
429
|
-
<DocsSection title="Data Tools" description="Sorting controls and a lightweight date picker.">
|
|
430
|
-
<DocsSectionGrid>
|
|
431
|
-
<Card>
|
|
432
|
-
<CardHeader>
|
|
433
|
-
<CardTitle className="text-base">Sort</CardTitle>
|
|
434
|
-
<CardDescription>A quiet ghost trigger for secondary table actions.</CardDescription>
|
|
435
|
-
</CardHeader>
|
|
436
|
-
<CardContent>
|
|
437
|
-
<Dropdown>
|
|
438
|
-
<DropdownTrigger>
|
|
439
|
-
<Button variant="ghost" className="w-full border border-zinc-200 dark:border-zinc-800">
|
|
440
|
-
<ArrowUpDown size={14} />
|
|
441
|
-
Sort data
|
|
442
|
-
</Button>
|
|
443
|
-
</DropdownTrigger>
|
|
444
|
-
<DropdownContent className="w-52">
|
|
445
|
-
<DropdownItem label="Newest first" icon={ArrowUpDown} />
|
|
446
|
-
<DropdownItem label="Price: high to low" />
|
|
447
|
-
<DropdownItem label="Customer rating" />
|
|
448
|
-
</DropdownContent>
|
|
449
|
-
</Dropdown>
|
|
450
|
-
</CardContent>
|
|
451
|
-
</Card>
|
|
452
|
-
|
|
453
|
-
<Card>
|
|
454
|
-
<CardHeader>
|
|
455
|
-
<CardTitle className="text-base">Date picker</CardTitle>
|
|
456
|
-
<CardDescription>A calendar grid rendered inside the dropdown panel.</CardDescription>
|
|
457
|
-
</CardHeader>
|
|
458
|
-
<CardContent>
|
|
459
|
-
<Dropdown>
|
|
460
|
-
<DropdownTrigger>
|
|
461
|
-
<Button variant="outline" className="w-full">
|
|
462
|
-
<Calendar size={16} />
|
|
463
|
-
Select range
|
|
464
|
-
</Button>
|
|
465
|
-
</DropdownTrigger>
|
|
466
|
-
<DropdownContent className="w-64 p-3 text-center">
|
|
467
|
-
<div className="mb-2 grid grid-cols-7 gap-1 text-[10px] font-bold text-zinc-400">
|
|
468
|
-
<span>S</span><span>M</span><span>T</span><span>W</span><span>T</span><span>F</span><span>S</span>
|
|
469
|
-
</div>
|
|
470
|
-
<div className="grid grid-cols-7 gap-1">
|
|
471
|
-
{Array.from({ length: 28 }).map((_, i) => (
|
|
472
|
-
<div key={i} className="flex h-7 w-7 cursor-pointer items-center justify-center rounded-md text-xs text-zinc-700 hover:bg-zinc-100 dark:text-zinc-300 dark:hover:bg-zinc-800">
|
|
473
|
-
{i + 1}
|
|
474
|
-
</div>
|
|
475
|
-
))}
|
|
476
|
-
</div>
|
|
477
|
-
</DropdownContent>
|
|
478
|
-
</Dropdown>
|
|
479
|
-
</CardContent>
|
|
480
|
-
</Card>
|
|
481
|
-
</DocsSectionGrid>
|
|
482
|
-
</DocsSection>
|
|
483
|
-
|
|
484
|
-
<DocsSection title="Cascading Selects" description="One dropdown's selection determines the options available in the next.">
|
|
485
|
-
<Card className="max-w-md">
|
|
486
|
-
<CardContent className="flex gap-2 pt-6">
|
|
487
|
-
<Dropdown>
|
|
488
|
-
<DropdownTrigger>
|
|
489
|
-
<Button variant="outline" className="flex-1">{cascading.country}</Button>
|
|
490
|
-
</DropdownTrigger>
|
|
491
|
-
<DropdownContent className="w-32">
|
|
492
|
-
<DropdownItem label="USA" onClick={() => setCascading({ country: "USA", state: "Select" })} />
|
|
493
|
-
<DropdownItem label="UK" onClick={() => setCascading({ country: "UK", state: "Select" })} />
|
|
494
|
-
</DropdownContent>
|
|
495
|
-
</Dropdown>
|
|
496
|
-
<Dropdown>
|
|
497
|
-
<DropdownTrigger>
|
|
498
|
-
<Button variant="outline" className="flex-1" disabled={cascading.country === "Select"}>
|
|
499
|
-
{cascading.state}
|
|
500
|
-
</Button>
|
|
501
|
-
</DropdownTrigger>
|
|
502
|
-
<DropdownContent className="w-32">
|
|
503
|
-
<DropdownItem
|
|
504
|
-
label={cascading.country === "USA" ? "California" : "London"}
|
|
505
|
-
onClick={() => setCascading({ ...cascading, state: cascading.country === "USA" ? "California" : "London" })}
|
|
506
|
-
/>
|
|
507
|
-
</DropdownContent>
|
|
508
|
-
</Dropdown>
|
|
509
|
-
</CardContent>
|
|
510
|
-
</Card>
|
|
511
|
-
</DocsSection>
|
|
512
|
-
|
|
513
|
-
<DocsApiSection>
|
|
514
|
-
<DocsApiTable title="API Reference — Dropdown" rows={DROPDOWN_API_ROWS} />
|
|
515
|
-
<DocsApiTable title="API Reference — DropdownTrigger" rows={TRIGGER_API_ROWS} />
|
|
516
|
-
<DocsApiTable title="API Reference — DropdownContent" rows={CONTENT_API_ROWS} />
|
|
517
|
-
<DocsApiTable title="API Reference — DropdownItem" rows={ITEM_API_ROWS} />
|
|
518
|
-
<DocsAccessibility items={ACCESSIBILITY_ITEMS} />
|
|
519
|
-
</DocsApiSection>
|
|
520
|
-
</DocsPage>
|
|
521
|
-
);
|
|
522
|
-
}
|