Skip to content

Commit 436e1d9

Browse files
committed
refactor(ui, docs): add InputGroup and Field components and integrate into registry
Introduced `InputGroup` and `Field` components with subcomponents (`InputGroupAddon`, `InputGroupButton`, `FieldSet`, `FieldLegend`, etc.). Registered the components in the docs app's registry and updated the `ui` package index file to enable reuse. Enhanced examples demonstrate use cases and customizations. Refactored `Input` component and extended ESLint rules for accessibility.
1 parent 36985d3 commit 436e1d9

File tree

10 files changed

+1032
-78
lines changed

10 files changed

+1032
-78
lines changed

.changeset/quiet-planets-sort.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@codefast/ui": patch
3+
---
4+
5+
refactor(ui, docs): add `InputGroup` and `Field` components and integrate into registry
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
"use client";
2+
3+
import type { JSX } from "react";
4+
5+
import { InfoIcon, ShieldCheckIcon } from "lucide-react";
6+
import { useState } from "react";
7+
8+
import { GridWrapper } from "@/components/grid-wrapper";
9+
import {
10+
Badge,
11+
Button,
12+
Checkbox,
13+
Field,
14+
FieldContent,
15+
FieldDescription,
16+
FieldError,
17+
FieldLabel,
18+
FieldLegend,
19+
FieldSeparator,
20+
FieldSet,
21+
FieldTitle,
22+
Input,
23+
RadioGroup,
24+
RadioGroupItem,
25+
Switch,
26+
Textarea,
27+
} from "@codefast/ui";
28+
29+
export function FieldDemo(): JSX.Element {
30+
const [showSlugError, setShowSlugError] = useState<boolean>(true);
31+
const [usage, setUsage] = useState<string>("team");
32+
33+
return (
34+
<GridWrapper className="*:flex *:flex-col *:gap-6 @3xl:grid-cols-2 @5xl:grid-cols-3">
35+
<div>
36+
<FieldSet>
37+
<Field>
38+
<FieldLabel htmlFor="field-name">Full name</FieldLabel>
39+
<FieldDescription>Displayed on invoices and shared reports.</FieldDescription>
40+
<Input id="field-name" placeholder="Leslie Knope" />
41+
</Field>
42+
43+
<Field>
44+
<FieldLabel htmlFor="field-about">
45+
About
46+
<Badge className="ml-auto" variant="secondary">
47+
Optional
48+
</Badge>
49+
</FieldLabel>
50+
<Textarea id="field-about" placeholder="Share a short bio…" rows={3} />
51+
<FieldDescription>Tell collaborators a little about yourself.</FieldDescription>
52+
</Field>
53+
54+
<Field>
55+
<FieldLabel htmlFor="field-slug">Workspace slug</FieldLabel>
56+
<Input
57+
aria-invalid={showSlugError}
58+
defaultValue="north-park"
59+
id="field-slug"
60+
placeholder="north-park"
61+
/>
62+
<FieldDescription>Lowercase letters, numbers, and dashes only.</FieldDescription>
63+
<FieldError
64+
errors={
65+
showSlugError
66+
? [
67+
{ message: "Slug is already in use." },
68+
{ message: "Try including your team name." },
69+
]
70+
: undefined
71+
}
72+
/>
73+
</Field>
74+
75+
<FieldSeparator />
76+
77+
<Button
78+
aria-pressed={showSlugError}
79+
size="sm"
80+
variant="outline"
81+
onClick={() => {
82+
setShowSlugError((previous) => !previous);
83+
}}
84+
>
85+
{showSlugError ? "Hide validation messages" : "Show validation messages"}
86+
</Button>
87+
</FieldSet>
88+
</div>
89+
90+
<div>
91+
<FieldSet>
92+
<FieldLegend variant="label">Security options</FieldLegend>
93+
<FieldDescription>
94+
Control how your organisation protects sessions and invites.
95+
</FieldDescription>
96+
97+
<Field orientation="horizontal">
98+
<Switch defaultChecked id="field-session" />
99+
<FieldContent>
100+
<FieldLabel htmlFor="field-session">Require session re-auth</FieldLabel>
101+
<FieldDescription>Ask members to sign in again every 30 days.</FieldDescription>
102+
</FieldContent>
103+
</Field>
104+
105+
<Field orientation="horizontal">
106+
<Checkbox id="field-invite" />
107+
<FieldContent>
108+
<FieldTitle>Restrict invites to verified domains</FieldTitle>
109+
<FieldDescription>
110+
Members can only invite collaborators with company email addresses.
111+
</FieldDescription>
112+
</FieldContent>
113+
</Field>
114+
115+
<Field orientation="horizontal">
116+
<Checkbox defaultChecked id="field-admin" />
117+
<FieldContent>
118+
<FieldLabel htmlFor="field-admin">Require admin approval</FieldLabel>
119+
<FieldDescription>
120+
New members remain pending until an admin approves them.
121+
</FieldDescription>
122+
</FieldContent>
123+
</Field>
124+
125+
<FieldSeparator>
126+
<span className="inline-flex items-center gap-1.5 text-xs font-medium">
127+
<ShieldCheckIcon className="size-3.5" />
128+
Recommended
129+
</span>
130+
</FieldSeparator>
131+
132+
<Field orientation="horizontal">
133+
<FieldLabel htmlFor="field-two-factor">Require 2-step verification</FieldLabel>
134+
<Switch id="field-two-factor" />
135+
</Field>
136+
</FieldSet>
137+
</div>
138+
139+
<div className="@5xl:col-span-1">
140+
<FieldSet>
141+
<FieldLegend>Usage intent</FieldLegend>
142+
<FieldDescription>Choose what fits best so we can tailor onboarding.</FieldDescription>
143+
<RadioGroup className="gap-4" value={usage} onValueChange={setUsage}>
144+
<Field orientation="horizontal">
145+
<RadioGroupItem id="usage-team" value="team" />
146+
<FieldContent>
147+
<FieldLabel htmlFor="usage-team">Team collaboration</FieldLabel>
148+
<FieldDescription>
149+
Coordinate projects, share documents, and manage feedback loops.
150+
</FieldDescription>
151+
</FieldContent>
152+
</Field>
153+
<Field orientation="horizontal">
154+
<RadioGroupItem id="usage-client" value="client" />
155+
<FieldContent>
156+
<FieldLabel htmlFor="usage-client">Client delivery</FieldLabel>
157+
<FieldDescription>
158+
Invite clients to review progress and sign off on milestones.
159+
</FieldDescription>
160+
</FieldContent>
161+
</Field>
162+
<Field orientation="horizontal">
163+
<RadioGroupItem id="usage-community" value="community" />
164+
<FieldContent>
165+
<FieldLabel htmlFor="usage-community">Community programs</FieldLabel>
166+
<FieldDescription>
167+
Manage volunteers, track participation, and share updates.
168+
</FieldDescription>
169+
</FieldContent>
170+
</Field>
171+
</RadioGroup>
172+
173+
<FieldSeparator />
174+
175+
<Field>
176+
<FieldLabel htmlFor="usage-notes">
177+
Additional notes
178+
<InfoIcon className="text-muted-foreground ml-auto size-3.5" />
179+
</FieldLabel>
180+
<Textarea
181+
id="usage-notes"
182+
placeholder="Anything specific you want us to know?"
183+
rows={4}
184+
/>
185+
</Field>
186+
</FieldSet>
187+
</div>
188+
</GridWrapper>
189+
);
190+
}

apps/docs/src/app/(app)/components/_components/input-demo.tsx

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import type { JSX } from "react";
22

3-
import { MailIcon } from "lucide-react";
4-
53
import { GridWrapper } from "@/components/grid-wrapper";
64
import { Input } from "@codefast/ui";
75

@@ -50,21 +48,9 @@ export function InputDemo(): JSX.Element {
5048
<div className="">
5149
<Input placeholder="Week" type="week" />
5250
</div>
53-
<div className="">
54-
<Input loading placeholder="Loading..." />
55-
</div>
5651
<div className="">
5752
<Input disabled placeholder="Disabled" />
5853
</div>
59-
<div className="">
60-
<Input readOnly defaultValue="Read Only" placeholder="Read Only" />
61-
</div>
62-
<div className="">
63-
<Input placeholder="Email" prefix={<MailIcon />} type="email" />
64-
</div>
65-
<div className="">
66-
<Input placeholder="Email" suffix={<MailIcon />} type="email" />
67-
</div>
6854
</GridWrapper>
6955
);
7056
}

0 commit comments

Comments
 (0)