ruler-components 0.1.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.
- package/AGENTS.md +9 -0
- package/CLAUDE.md +1 -0
- package/LICENSE +21 -0
- package/README.md +45 -0
- package/app/docs/[slug]/page.tsx +147 -0
- package/app/docs/layout.tsx +26 -0
- package/app/docs/page.tsx +148 -0
- package/app/favicon.ico +0 -0
- package/app/globals.css +168 -0
- package/app/icon.png +0 -0
- package/app/layout.tsx +90 -0
- package/app/opengraph-image.tsx +10 -0
- package/app/page.tsx +34 -0
- package/app/twitter-image.tsx +10 -0
- package/components/docs/accordion-doc-page.tsx +352 -0
- package/components/docs/alert-doc-page.tsx +293 -0
- package/components/docs/allinput-doc-page.tsx +183 -0
- package/components/docs/avatar-doc-page.tsx +424 -0
- package/components/docs/badge-doc-page.tsx +363 -0
- package/components/docs/button-doc-page.tsx +406 -0
- package/components/docs/card-doc-page.tsx +364 -0
- package/components/docs/checkbox-doc-page.tsx +277 -0
- package/components/docs/colors-doc-page.tsx +430 -0
- package/components/docs/dialog-doc-page.tsx +364 -0
- package/components/docs/docs-footer.tsx +11 -0
- package/components/docs/docs-mobile-menu-bar.tsx +22 -0
- package/components/docs/docs-mobile-nav-context.tsx +27 -0
- package/components/docs/docs-page.tsx +263 -0
- package/components/docs/docs-search.tsx +303 -0
- package/components/docs/docs-sidebar.tsx +165 -0
- package/components/docs/docs-topbar.tsx +32 -0
- package/components/docs/dropdown-doc-page.tsx +522 -0
- package/components/docs/getting-started-doc-page.tsx +205 -0
- package/components/docs/label-doc-page.tsx +173 -0
- package/components/docs/loaders-doc-page.tsx +244 -0
- package/components/docs/menu-doc-page.tsx +373 -0
- package/components/docs/modal-doc-page.tsx +436 -0
- package/components/docs/next-steps.tsx +53 -0
- package/components/docs/pagination-doc-page.tsx +316 -0
- package/components/docs/progress-doc-page.tsx +387 -0
- package/components/docs/radio-doc-page.tsx +270 -0
- package/components/docs/skeleton-doc-page.tsx +230 -0
- package/components/docs/stepper-doc-page.tsx +309 -0
- package/components/docs/switch-doc-page.tsx +264 -0
- package/components/docs/table-doc-page.tsx +689 -0
- package/components/docs/tabs-doc-page.tsx +359 -0
- package/components/docs/theming-doc-page.tsx +243 -0
- package/components/docs/tooltip-doc-page.tsx +357 -0
- package/components/docs/usage-section.tsx +21 -0
- package/components/icons/discord.tsx +9 -0
- package/components/icons/github.tsx +9 -0
- package/components/icons/x.tsx +9 -0
- package/components/installation-section.tsx +34 -0
- package/components/landing/feature-highlights.tsx +105 -0
- package/components/landing/footer-strip.tsx +45 -0
- package/components/landing/hero-card.tsx +14 -0
- package/components/landing/hero-spotlight.tsx +126 -0
- package/components/landing/hero.tsx +64 -0
- package/components/landing/navbar.tsx +44 -0
- package/components/landing/quick-start-section.tsx +59 -0
- package/components/landing/site-footer.tsx +55 -0
- package/components/theme-provider.tsx +60 -0
- package/components/ui/accordion.tsx +174 -0
- package/components/ui/alert.tsx +103 -0
- package/components/ui/allinput.tsx +210 -0
- package/components/ui/avatar.tsx +179 -0
- package/components/ui/badge.tsx +52 -0
- package/components/ui/button.tsx +75 -0
- package/components/ui/card.tsx +105 -0
- package/components/ui/checkbox.tsx +130 -0
- package/components/ui/code-block.tsx +60 -0
- package/components/ui/data-table.tsx +235 -0
- package/components/ui/dialog.tsx +173 -0
- package/components/ui/dropdown.tsx +78 -0
- package/components/ui/feature-card.tsx +38 -0
- package/components/ui/input.tsx +44 -0
- package/components/ui/label.tsx +110 -0
- package/components/ui/loaders.tsx +139 -0
- package/components/ui/menu.tsx +118 -0
- package/components/ui/modal.tsx +399 -0
- package/components/ui/package-manager-tabs.tsx +40 -0
- package/components/ui/pagination.tsx +200 -0
- package/components/ui/progress.tsx +134 -0
- package/components/ui/radio.tsx +262 -0
- package/components/ui/skeleton.tsx +102 -0
- package/components/ui/steppers.tsx +309 -0
- package/components/ui/switch.tsx +153 -0
- package/components/ui/table.tsx +58 -0
- package/components/ui/tabs.tsx +166 -0
- package/components/ui/theme-toggle.tsx +60 -0
- package/components/ui/tooltip.tsx +238 -0
- package/data/color-palette.ts +35 -0
- package/data/docs-nav.ts +84 -0
- package/eslint.config.mjs +18 -0
- package/index.ts +8 -0
- package/lib/cn.ts +4 -0
- package/lib/color.ts +85 -0
- package/lib/og-image.tsx +138 -0
- package/lib/theme.ts +33 -0
- package/next.config.ts +7 -0
- package/package.json +30 -0
- package/postcss.config.mjs +7 -0
- package/public/dark.png +0 -0
- package/public/dark1.png +0 -0
- package/public/dark2.png +0 -0
- package/public/file.svg +1 -0
- package/public/globe.svg +1 -0
- package/public/light.png +0 -0
- package/public/light1.png +0 -0
- package/public/next.svg +1 -0
- package/public/vercel.svg +1 -0
- package/public/video/hero-demo.mp4 +0 -0
- package/public/window.svg +1 -0
- package/tsconfig.json +34 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { Check, Copy, RotateCcw, TriangleAlert } from "lucide-react";
|
|
5
|
+
import { Alert } from "@/components/ui/alert";
|
|
6
|
+
import { Button } from "@/components/ui/button";
|
|
7
|
+
import { Tooltip } from "@/components/ui/tooltip";
|
|
8
|
+
import {
|
|
9
|
+
DocsAccessibility,
|
|
10
|
+
DocsApiSection,
|
|
11
|
+
DocsApiTable,
|
|
12
|
+
DocsPage,
|
|
13
|
+
DocsPageHeader,
|
|
14
|
+
DocsSection,
|
|
15
|
+
DocsSectionGrid,
|
|
16
|
+
} from "@/components/docs/docs-page";
|
|
17
|
+
import { cn } from "@/lib/cn";
|
|
18
|
+
|
|
19
|
+
const API_ROWS = [
|
|
20
|
+
{ prop: "variant", type: '"info" | "success" | "warning" | "error"', default: '"info"', description: "The style variant" },
|
|
21
|
+
{ prop: "title", type: "string", default: "—", description: "The title text" },
|
|
22
|
+
{ prop: "description", type: "string", default: "—", description: "The description text" },
|
|
23
|
+
{ prop: "dismissible", type: "boolean", default: "false", description: "Shows close button" },
|
|
24
|
+
{ prop: "onDismiss", type: "() => void", default: "—", description: "Dismiss callback" },
|
|
25
|
+
{ prop: "action", type: "ReactNode", default: "—", description: "Trailing action, e.g. a button" },
|
|
26
|
+
{ prop: "children", type: "ReactNode", default: "—", description: "Custom content" },
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
const ACCESSIBILITY_ITEMS = [
|
|
30
|
+
"Use appropriate semantic markup.",
|
|
31
|
+
"Important alerts should use an appropriate ARIA role.",
|
|
32
|
+
"Don't rely on color alone to communicate status.",
|
|
33
|
+
"Provide meaningful text for screen readers.",
|
|
34
|
+
"Dismiss buttons should have an accessible label.",
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
type Variant = "info" | "success" | "warning" | "error";
|
|
38
|
+
|
|
39
|
+
const VARIANTS: { value: Variant; label: string; swatch: string }[] = [
|
|
40
|
+
{ value: "info", label: "Info", swatch: "bg-[#0070BA]" },
|
|
41
|
+
{ value: "success", label: "Success", swatch: "bg-[#28A745]" },
|
|
42
|
+
{ value: "warning", label: "Warning", swatch: "bg-[#E58E00]" },
|
|
43
|
+
{ value: "error", label: "Error", swatch: "bg-[#D93025]" },
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
const COPY: Record<Variant, { title: string; description: string }> = {
|
|
47
|
+
info: { title: "Information", description: "This is an informational message for the user." },
|
|
48
|
+
success: { title: "Success", description: "Your changes have been saved successfully." },
|
|
49
|
+
warning: { title: "Warning", description: "This action may affect your existing data." },
|
|
50
|
+
error: { title: "Error", description: "Something went wrong. Please try again." },
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
function codeFor(variant: Variant, dismissible: boolean, withAction: boolean) {
|
|
54
|
+
const { title, description } = COPY[variant];
|
|
55
|
+
const lines = [
|
|
56
|
+
variant !== "info" ? `variant="${variant}"` : null,
|
|
57
|
+
`title="${title}"`,
|
|
58
|
+
`description="${description}"`,
|
|
59
|
+
dismissible ? "dismissible" : null,
|
|
60
|
+
withAction ? "action={<Button size=\"sm\">Action</Button>}" : null,
|
|
61
|
+
].filter(Boolean);
|
|
62
|
+
return `<Alert\n ${lines.join("\n ")}\n/>`;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const ACTION_BUTTON_CLASS =
|
|
66
|
+
"h-7 cursor-pointer whitespace-nowrap border border-zinc-300 px-2 text-[10px] text-zinc-500 transition-colors hover:bg-zinc-100 hover:text-zinc-700 dark:border-zinc-700 dark:text-zinc-300 dark:hover:bg-zinc-800 dark:hover:text-white";
|
|
67
|
+
|
|
68
|
+
const NOTIFICATIONS = [
|
|
69
|
+
{ id: 1, variant: "info" as const, title: "Scheduled maintenance", description: "Search will be briefly unavailable tonight at 2 AM UTC." },
|
|
70
|
+
{ id: 2, variant: "success" as const, title: "Payment received", description: "Your invoice #4471 has been paid in full." },
|
|
71
|
+
{ id: 3, variant: "warning" as const, title: "Storage almost full", description: "You've used 92% of your workspace storage." },
|
|
72
|
+
{ id: 4, variant: "error" as const, title: "Sync failed", description: "3 files couldn't be uploaded. Check your connection." },
|
|
73
|
+
];
|
|
74
|
+
|
|
75
|
+
export function AlertDocPage() {
|
|
76
|
+
const [variant, setVariant] = useState<Variant>("warning");
|
|
77
|
+
const [dismissible, setDismissible] = useState(false);
|
|
78
|
+
const [withAction, setWithAction] = useState(true);
|
|
79
|
+
const [dismissed, setDismissed] = useState(false);
|
|
80
|
+
const [copied, setCopied] = useState(false);
|
|
81
|
+
const [dismissedIds, setDismissedIds] = useState<number[]>([]);
|
|
82
|
+
|
|
83
|
+
const snippet = codeFor(variant, dismissible, withAction);
|
|
84
|
+
const visibleNotifications = NOTIFICATIONS.filter((n) => !dismissedIds.includes(n.id));
|
|
85
|
+
|
|
86
|
+
function copySnippet() {
|
|
87
|
+
navigator.clipboard.writeText(snippet).catch(() => {});
|
|
88
|
+
setCopied(true);
|
|
89
|
+
setTimeout(() => setCopied(false), 1200);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<DocsPage>
|
|
94
|
+
<DocsPageHeader
|
|
95
|
+
icon={TriangleAlert}
|
|
96
|
+
title="Alert"
|
|
97
|
+
description="Displays a prominent message to inform users about important changes, warnings, or system status."
|
|
98
|
+
/>
|
|
99
|
+
|
|
100
|
+
<DocsSection
|
|
101
|
+
first
|
|
102
|
+
title="Playground"
|
|
103
|
+
description="Every variant, with or without a dismiss button and action — live, with the exact markup to match."
|
|
104
|
+
>
|
|
105
|
+
<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)]">
|
|
106
|
+
<div className="relative flex min-h-[11rem] items-center justify-center overflow-hidden bg-zinc-50 p-6 dark:bg-zinc-900/40">
|
|
107
|
+
<div
|
|
108
|
+
aria-hidden
|
|
109
|
+
className="pointer-events-none absolute inset-0 opacity-[0.4] dark:opacity-[0.15]"
|
|
110
|
+
style={{
|
|
111
|
+
backgroundImage:
|
|
112
|
+
"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)",
|
|
113
|
+
backgroundSize: "24px 24px",
|
|
114
|
+
}}
|
|
115
|
+
/>
|
|
116
|
+
{dismissed ? (
|
|
117
|
+
<button
|
|
118
|
+
type="button"
|
|
119
|
+
onClick={() => setDismissed(false)}
|
|
120
|
+
className="relative flex items-center gap-2 rounded-lg border border-dashed border-zinc-300 px-4 py-2.5 text-sm font-medium text-zinc-500 transition-colors hover:border-zinc-400 hover:text-zinc-700 dark:border-zinc-700 dark:text-zinc-400 dark:hover:border-zinc-600 dark:hover:text-zinc-200"
|
|
121
|
+
>
|
|
122
|
+
<RotateCcw className="h-3.5 w-3.5" />
|
|
123
|
+
Dismissed — show it again
|
|
124
|
+
</button>
|
|
125
|
+
) : (
|
|
126
|
+
<div
|
|
127
|
+
key={`${variant}-${dismissible}-${withAction}`}
|
|
128
|
+
className="relative w-full max-w-md animate-[pagination-pop_0.2s_ease-out]"
|
|
129
|
+
>
|
|
130
|
+
<Alert
|
|
131
|
+
variant={variant}
|
|
132
|
+
title={COPY[variant].title}
|
|
133
|
+
description={COPY[variant].description}
|
|
134
|
+
dismissible={dismissible}
|
|
135
|
+
onDismiss={dismissible ? () => setDismissed(true) : undefined}
|
|
136
|
+
action={withAction ? <Button variant="outline" size="sm" className={ACTION_BUTTON_CLASS}>Action</Button> : undefined}
|
|
137
|
+
/>
|
|
138
|
+
</div>
|
|
139
|
+
)}
|
|
140
|
+
</div>
|
|
141
|
+
|
|
142
|
+
<div className="flex flex-col gap-5 border-t border-zinc-200 p-5 dark:border-zinc-800">
|
|
143
|
+
<div className="flex flex-wrap items-start justify-between gap-6">
|
|
144
|
+
<div>
|
|
145
|
+
<p className="mb-2 text-xs font-medium uppercase tracking-wide text-zinc-400 dark:text-zinc-500">
|
|
146
|
+
Variant
|
|
147
|
+
</p>
|
|
148
|
+
<div className="flex flex-wrap gap-1.5">
|
|
149
|
+
{VARIANTS.map((v) => (
|
|
150
|
+
<Tooltip key={v.value} content={v.label}>
|
|
151
|
+
<button
|
|
152
|
+
type="button"
|
|
153
|
+
onClick={() => setVariant(v.value)}
|
|
154
|
+
aria-label={v.label}
|
|
155
|
+
className={cn(
|
|
156
|
+
"flex h-8 w-8 items-center justify-center rounded-lg border transition-all",
|
|
157
|
+
variant === v.value
|
|
158
|
+
? "border-zinc-900 ring-2 ring-zinc-900 ring-offset-2 ring-offset-zinc-50 dark:border-white dark:ring-white dark:ring-offset-zinc-900"
|
|
159
|
+
: "border-zinc-200 hover:border-zinc-300 dark:border-zinc-700 dark:hover:border-zinc-600"
|
|
160
|
+
)}
|
|
161
|
+
>
|
|
162
|
+
<span className={cn("h-3.5 w-3.5 rounded-full", v.swatch)} />
|
|
163
|
+
</button>
|
|
164
|
+
</Tooltip>
|
|
165
|
+
))}
|
|
166
|
+
</div>
|
|
167
|
+
</div>
|
|
168
|
+
|
|
169
|
+
<div>
|
|
170
|
+
<p className="mb-2 text-xs font-medium uppercase tracking-wide text-zinc-400 dark:text-zinc-500">
|
|
171
|
+
Dismissible
|
|
172
|
+
</p>
|
|
173
|
+
<button
|
|
174
|
+
type="button"
|
|
175
|
+
onClick={() => setDismissible((v) => !v)}
|
|
176
|
+
className={cn(
|
|
177
|
+
"flex h-[2.125rem] items-center gap-2 rounded-lg border px-3 text-xs font-medium transition-colors",
|
|
178
|
+
dismissible
|
|
179
|
+
? "border-zinc-900 bg-zinc-900 text-white dark:border-white dark:bg-white dark:text-zinc-900"
|
|
180
|
+
: "border-zinc-200 text-zinc-500 hover:border-zinc-300 dark:border-zinc-700 dark:text-zinc-400"
|
|
181
|
+
)}
|
|
182
|
+
>
|
|
183
|
+
{dismissible ? "On" : "Off"}
|
|
184
|
+
</button>
|
|
185
|
+
</div>
|
|
186
|
+
|
|
187
|
+
<div>
|
|
188
|
+
<p className="mb-2 text-xs font-medium uppercase tracking-wide text-zinc-400 dark:text-zinc-500">
|
|
189
|
+
Action
|
|
190
|
+
</p>
|
|
191
|
+
<button
|
|
192
|
+
type="button"
|
|
193
|
+
onClick={() => setWithAction((v) => !v)}
|
|
194
|
+
className={cn(
|
|
195
|
+
"flex h-[2.125rem] items-center gap-2 rounded-lg border px-3 text-xs font-medium transition-colors",
|
|
196
|
+
withAction
|
|
197
|
+
? "border-zinc-900 bg-zinc-900 text-white dark:border-white dark:bg-white dark:text-zinc-900"
|
|
198
|
+
: "border-zinc-200 text-zinc-500 hover:border-zinc-300 dark:border-zinc-700 dark:text-zinc-400"
|
|
199
|
+
)}
|
|
200
|
+
>
|
|
201
|
+
{withAction ? "On" : "Off"}
|
|
202
|
+
</button>
|
|
203
|
+
</div>
|
|
204
|
+
</div>
|
|
205
|
+
|
|
206
|
+
<div className="flex items-center justify-between gap-3 rounded-xl bg-zinc-900 px-4 py-3 dark:bg-black">
|
|
207
|
+
<pre className="overflow-x-auto font-mono text-[13px] leading-relaxed text-zinc-100">
|
|
208
|
+
<code>{snippet}</code>
|
|
209
|
+
</pre>
|
|
210
|
+
<Tooltip content={copied ? "Copied!" : "Copy code"}>
|
|
211
|
+
<button
|
|
212
|
+
type="button"
|
|
213
|
+
onClick={copySnippet}
|
|
214
|
+
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"
|
|
215
|
+
>
|
|
216
|
+
{copied ? <Check className="h-4 w-4 text-emerald-400" /> : <Copy className="h-4 w-4" />}
|
|
217
|
+
</button>
|
|
218
|
+
</Tooltip>
|
|
219
|
+
</div>
|
|
220
|
+
</div>
|
|
221
|
+
</div>
|
|
222
|
+
</DocsSection>
|
|
223
|
+
|
|
224
|
+
<DocsSection
|
|
225
|
+
title="In context"
|
|
226
|
+
description="Alerts rarely stand alone — here's how they read inside real UI."
|
|
227
|
+
>
|
|
228
|
+
<DocsSectionGrid className="lg:grid-cols-[1.2fr_1fr]">
|
|
229
|
+
<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)]">
|
|
230
|
+
<div className="flex items-center justify-between border-b border-zinc-200 bg-zinc-50/70 px-4 py-2.5 dark:border-zinc-800 dark:bg-zinc-900/40">
|
|
231
|
+
<p className="text-sm font-semibold text-zinc-900 dark:text-white">Notification center</p>
|
|
232
|
+
{dismissedIds.length > 0 && (
|
|
233
|
+
<button
|
|
234
|
+
type="button"
|
|
235
|
+
onClick={() => setDismissedIds([])}
|
|
236
|
+
className="flex items-center gap-1 text-xs font-medium text-zinc-500 transition-colors hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-white"
|
|
237
|
+
>
|
|
238
|
+
<RotateCcw className="h-3 w-3" />
|
|
239
|
+
Restore all
|
|
240
|
+
</button>
|
|
241
|
+
)}
|
|
242
|
+
</div>
|
|
243
|
+
<div className="flex flex-col gap-3 p-4">
|
|
244
|
+
{visibleNotifications.length === 0 ? (
|
|
245
|
+
<p className="py-8 text-center text-sm text-zinc-400 dark:text-zinc-600">
|
|
246
|
+
All caught up — nothing left to review.
|
|
247
|
+
</p>
|
|
248
|
+
) : (
|
|
249
|
+
visibleNotifications.map((n) => (
|
|
250
|
+
<Alert
|
|
251
|
+
key={n.id}
|
|
252
|
+
variant={n.variant}
|
|
253
|
+
title={n.title}
|
|
254
|
+
description={n.description}
|
|
255
|
+
dismissible
|
|
256
|
+
onDismiss={() => setDismissedIds((ids) => [...ids, n.id])}
|
|
257
|
+
/>
|
|
258
|
+
))
|
|
259
|
+
)}
|
|
260
|
+
</div>
|
|
261
|
+
</div>
|
|
262
|
+
|
|
263
|
+
<div className="flex flex-col gap-4">
|
|
264
|
+
<div className="rounded-2xl border border-zinc-200 bg-white p-5 shadow-[0_1px_2px_rgba(0,0,0,0.03)] dark:border-zinc-800 dark:bg-zinc-950">
|
|
265
|
+
<p className="text-sm font-semibold text-zinc-900 dark:text-white">Invite teammates</p>
|
|
266
|
+
<label className="mt-3 block text-xs font-medium text-zinc-500 dark:text-zinc-400">
|
|
267
|
+
Email address
|
|
268
|
+
</label>
|
|
269
|
+
<input
|
|
270
|
+
readOnly
|
|
271
|
+
value="not-an-email"
|
|
272
|
+
className="mt-1.5 w-full rounded-lg border border-red-300 bg-red-50/50 px-3 py-2 text-sm text-zinc-700 outline-none dark:border-red-900/60 dark:bg-red-950/20 dark:text-zinc-200"
|
|
273
|
+
/>
|
|
274
|
+
<div className="mt-2">
|
|
275
|
+
<Alert variant="error" description="Enter a valid email address to continue." />
|
|
276
|
+
</div>
|
|
277
|
+
</div>
|
|
278
|
+
|
|
279
|
+
<div className="rounded-2xl border border-zinc-200 bg-white p-5 shadow-[0_1px_2px_rgba(0,0,0,0.03)] dark:border-zinc-800 dark:bg-zinc-950">
|
|
280
|
+
<p className="mb-3 text-sm font-semibold text-zinc-900 dark:text-white">Plain, no title</p>
|
|
281
|
+
<Alert variant="info" description="This is a simple informational alert without a title." />
|
|
282
|
+
</div>
|
|
283
|
+
</div>
|
|
284
|
+
</DocsSectionGrid>
|
|
285
|
+
</DocsSection>
|
|
286
|
+
|
|
287
|
+
<DocsApiSection>
|
|
288
|
+
<DocsApiTable title="API Reference" rows={API_ROWS} />
|
|
289
|
+
<DocsAccessibility items={ACCESSIBILITY_ITEMS} />
|
|
290
|
+
</DocsApiSection>
|
|
291
|
+
</DocsPage>
|
|
292
|
+
);
|
|
293
|
+
}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { Mail, TextCursorInput } from "lucide-react";
|
|
5
|
+
import {
|
|
6
|
+
InputStandard,
|
|
7
|
+
InputFilled,
|
|
8
|
+
InputUnderline,
|
|
9
|
+
InputFloating,
|
|
10
|
+
InputSearch,
|
|
11
|
+
InputPassword,
|
|
12
|
+
InputAddon,
|
|
13
|
+
InputIcon,
|
|
14
|
+
InputOTP,
|
|
15
|
+
InputAutocomplete,
|
|
16
|
+
} from "@/components/ui/allinput";
|
|
17
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
|
18
|
+
import {
|
|
19
|
+
DocsAccessibility,
|
|
20
|
+
DocsApiSection,
|
|
21
|
+
DocsPage,
|
|
22
|
+
DocsPageHeader,
|
|
23
|
+
DocsSection,
|
|
24
|
+
DocsSectionGrid,
|
|
25
|
+
DocsSimpleTable,
|
|
26
|
+
} from "@/components/docs/docs-page";
|
|
27
|
+
|
|
28
|
+
const COMPONENT_ROWS = [
|
|
29
|
+
{ name: "InputStandard", description: "Bordered outline field — the default choice for most forms." },
|
|
30
|
+
{ name: "InputFilled", description: "Borderless, filled surface inspired by Material Design." },
|
|
31
|
+
{ name: "InputUnderline", description: "Minimal single-line border that animates in on focus." },
|
|
32
|
+
{ name: "InputFloating", description: "Label starts inline and floats above the value on focus." },
|
|
33
|
+
{ name: "InputSearch", description: "Pill-shaped field with a leading search icon." },
|
|
34
|
+
{ name: "InputPassword", description: "Masked field with a show/hide visibility toggle." },
|
|
35
|
+
{ name: "InputAddon", description: "Wraps the field with static prefix and/or suffix text." },
|
|
36
|
+
{ name: "InputIcon", description: "Places a leading or trailing icon inside the field." },
|
|
37
|
+
{ name: "InputOTP", description: "Four-cell segmented field for one-time passcodes." },
|
|
38
|
+
{ name: "InputAutocomplete", description: "Text field paired with a type-ahead suggestion list." },
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
const ACCESSIBILITY_ITEMS = [
|
|
42
|
+
"Always pair an input with a visible or programmatically associated <label>.",
|
|
43
|
+
"Use aria-label on icon-only controls, like the password visibility toggle.",
|
|
44
|
+
"Communicate validation errors with text, not color alone.",
|
|
45
|
+
"OTP and segmented fields should expose each cell as a distinct, labeled input.",
|
|
46
|
+
"Preserve native input behavior — don't block paste, autofill, or keyboard navigation.",
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
export function InputDocPage() {
|
|
50
|
+
return (
|
|
51
|
+
<DocsPage>
|
|
52
|
+
<DocsPageHeader
|
|
53
|
+
icon={TextCursorInput}
|
|
54
|
+
title="Input"
|
|
55
|
+
description="Professional UI inputs with distinct visual identities — from bordered fields to floating labels and segmented codes."
|
|
56
|
+
/>
|
|
57
|
+
|
|
58
|
+
<DocsSection first title="Foundation" description="Two dependable base styles for everyday forms.">
|
|
59
|
+
<DocsSectionGrid>
|
|
60
|
+
<Card>
|
|
61
|
+
<CardHeader>
|
|
62
|
+
<CardTitle className="text-base">Outlined</CardTitle>
|
|
63
|
+
<CardDescription>The default bordered field for most forms.</CardDescription>
|
|
64
|
+
</CardHeader>
|
|
65
|
+
<CardContent>
|
|
66
|
+
<InputStandard placeholder="Email address" />
|
|
67
|
+
</CardContent>
|
|
68
|
+
</Card>
|
|
69
|
+
<Card>
|
|
70
|
+
<CardHeader>
|
|
71
|
+
<CardTitle className="text-base">Filled</CardTitle>
|
|
72
|
+
<CardDescription>A soft, borderless surface with a filled background.</CardDescription>
|
|
73
|
+
</CardHeader>
|
|
74
|
+
<CardContent>
|
|
75
|
+
<InputFilled placeholder="Your full name" />
|
|
76
|
+
</CardContent>
|
|
77
|
+
</Card>
|
|
78
|
+
</DocsSectionGrid>
|
|
79
|
+
</DocsSection>
|
|
80
|
+
|
|
81
|
+
<DocsSection title="Minimal & Floating" description="Understated styles that keep the focus on content.">
|
|
82
|
+
<DocsSectionGrid>
|
|
83
|
+
<Card>
|
|
84
|
+
<CardHeader>
|
|
85
|
+
<CardTitle className="text-base">Underline</CardTitle>
|
|
86
|
+
<CardDescription>A single border that animates in on focus.</CardDescription>
|
|
87
|
+
</CardHeader>
|
|
88
|
+
<CardContent>
|
|
89
|
+
<InputUnderline placeholder="Company" />
|
|
90
|
+
</CardContent>
|
|
91
|
+
</Card>
|
|
92
|
+
<Card>
|
|
93
|
+
<CardHeader>
|
|
94
|
+
<CardTitle className="text-base">Floating Label</CardTitle>
|
|
95
|
+
<CardDescription>The label lifts above the value once focused or filled.</CardDescription>
|
|
96
|
+
</CardHeader>
|
|
97
|
+
<CardContent>
|
|
98
|
+
<InputFloating label="Phone" placeholder=" " />
|
|
99
|
+
</CardContent>
|
|
100
|
+
</Card>
|
|
101
|
+
</DocsSectionGrid>
|
|
102
|
+
</DocsSection>
|
|
103
|
+
|
|
104
|
+
<DocsSection title="Search & Security" description="Purpose-built fields for lookup and sensitive data entry.">
|
|
105
|
+
<DocsSectionGrid>
|
|
106
|
+
<Card>
|
|
107
|
+
<CardHeader>
|
|
108
|
+
<CardTitle className="text-base">Search</CardTitle>
|
|
109
|
+
<CardDescription>Pill-shaped with a leading search icon.</CardDescription>
|
|
110
|
+
</CardHeader>
|
|
111
|
+
<CardContent>
|
|
112
|
+
<InputSearch placeholder="Search..." />
|
|
113
|
+
</CardContent>
|
|
114
|
+
</Card>
|
|
115
|
+
<Card>
|
|
116
|
+
<CardHeader>
|
|
117
|
+
<CardTitle className="text-base">Password</CardTitle>
|
|
118
|
+
<CardDescription>Includes a toggle to reveal the typed value.</CardDescription>
|
|
119
|
+
</CardHeader>
|
|
120
|
+
<CardContent>
|
|
121
|
+
<InputPassword placeholder="Password" />
|
|
122
|
+
</CardContent>
|
|
123
|
+
</Card>
|
|
124
|
+
</DocsSectionGrid>
|
|
125
|
+
</DocsSection>
|
|
126
|
+
|
|
127
|
+
<DocsSection title="Addons & Icons" description="Add context with affixes or a leading/trailing icon.">
|
|
128
|
+
<DocsSectionGrid>
|
|
129
|
+
<Card>
|
|
130
|
+
<CardHeader>
|
|
131
|
+
<CardTitle className="text-base">With Addons</CardTitle>
|
|
132
|
+
<CardDescription>Static prefix and suffix text framed around the value.</CardDescription>
|
|
133
|
+
</CardHeader>
|
|
134
|
+
<CardContent>
|
|
135
|
+
<InputAddon prefix="https://" suffix=".io" placeholder="domain" />
|
|
136
|
+
</CardContent>
|
|
137
|
+
</Card>
|
|
138
|
+
<Card>
|
|
139
|
+
<CardHeader>
|
|
140
|
+
<CardTitle className="text-base">With Icon</CardTitle>
|
|
141
|
+
<CardDescription>A leading icon adds meaning at a glance.</CardDescription>
|
|
142
|
+
</CardHeader>
|
|
143
|
+
<CardContent>
|
|
144
|
+
<InputIcon icon={Mail} placeholder="Support email" />
|
|
145
|
+
</CardContent>
|
|
146
|
+
</Card>
|
|
147
|
+
</DocsSectionGrid>
|
|
148
|
+
</DocsSection>
|
|
149
|
+
|
|
150
|
+
<DocsSection
|
|
151
|
+
title="Advanced Patterns"
|
|
152
|
+
description="Segmented codes and intelligent type-ahead suggestions."
|
|
153
|
+
className="pb-28"
|
|
154
|
+
>
|
|
155
|
+
<DocsSectionGrid>
|
|
156
|
+
<Card>
|
|
157
|
+
<CardHeader>
|
|
158
|
+
<CardTitle className="text-base">OTP / Code</CardTitle>
|
|
159
|
+
<CardDescription>Four-cell segmented field for verification codes.</CardDescription>
|
|
160
|
+
</CardHeader>
|
|
161
|
+
<CardContent>
|
|
162
|
+
<InputOTP />
|
|
163
|
+
</CardContent>
|
|
164
|
+
</Card>
|
|
165
|
+
<Card>
|
|
166
|
+
<CardHeader>
|
|
167
|
+
<CardTitle className="text-base">Autocomplete</CardTitle>
|
|
168
|
+
<CardDescription>Suggests matching values as the user types.</CardDescription>
|
|
169
|
+
</CardHeader>
|
|
170
|
+
<CardContent>
|
|
171
|
+
<InputAutocomplete placeholder="Search a company..." suggestions={["Apple", "Amazon", "Adobe"]} />
|
|
172
|
+
</CardContent>
|
|
173
|
+
</Card>
|
|
174
|
+
</DocsSectionGrid>
|
|
175
|
+
</DocsSection>
|
|
176
|
+
|
|
177
|
+
<DocsApiSection>
|
|
178
|
+
<DocsSimpleTable title="Available Components" rows={COMPONENT_ROWS} />
|
|
179
|
+
<DocsAccessibility items={ACCESSIBILITY_ITEMS} />
|
|
180
|
+
</DocsApiSection>
|
|
181
|
+
</DocsPage>
|
|
182
|
+
);
|
|
183
|
+
}
|