Components
Loading preview...
HeroUI v3 Fieldset — groups related form fields with a legend, description and actions, including an on-surface variant.
npx shadcn@latest add https://21st.dev/r/hero_ui/heroui-fieldset"use client"
import { Save } from "lucide-react"
import {
Button,
Description,
FieldError,
Form,
Input,
Label,
Surface,
TextArea,
TextField,
} from "@heroui/react"
import { Fieldset } from "@/components/ui/heroui-fieldset"
export function OnSurface() {
const onSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
const formData = new FormData(e.currentTarget)
const data: Record<string, string> = {}
// Convert FormData to plain object
formData.forEach((value, key) => {
data[key] = value.toString()
})
alert("Form submitted successfully!")
}
return (
<div className="flex items-center justify-center rounded-3xl bg-surface p-6">
<Surface className="w-full min-w-[380px]">
<Form onSubmit={onSubmit}>
<Fieldset className="w-full">
<Fieldset.Legend>Profile Settings</Fieldset.Legend>
<Description>Update your profile information.</Description>
<Fieldset.Group>
<TextField
isRequired
name="name"
validate={(value) => {
if (value.length < 3) {
return "Name must be at least 3 characters"
}
return null
}}
>
<Label>Name</Label>
<Input placeholder="John Doe" variant="secondary" />
<FieldError />
</TextField>
<TextField isRequired name="email" type="email">
<Label>Email</Label>
<Input placeholder="john@example.com" variant="secondary" />
<FieldError />
</TextField>
<TextField
isRequired
name="bio"
validate={(value) => {
if (value.length < 10) {
return "Bio must be at least 10 characters"
}
return null
}}
>
<Label>Bio</Label>
<TextArea placeholder="Tell us about yourself..." variant="secondary" />
<Description>Minimum 10 characters</Description>
<FieldError />
</TextField>
</Fieldset.Group>
<Fieldset.Actions>
<Button type="submit">
<Save />
Save changes
</Button>
<Button type="reset" variant="tertiary">
Cancel
</Button>
</Fieldset.Actions>
</Fieldset>
</Form>
</Surface>
</div>
)
}
export default OnSurface