apps/eclipse/content/design-system/components/field.mdx
import { Field, FieldLabel, FieldDescription, FieldError, FieldGroup, Input, Button } from "@prisma/eclipse";
Basic Field
A Field provides structure for form inputs with proper spacing and layout:
import { Field, FieldLabel, Input } from "@prisma/eclipse";
export function BasicField() {
return (
<Field>
<FieldLabel htmlFor="email">Email</FieldLabel>
<Input id="email" type="email" placeholder="Enter your email" />
</Field>
);
}
Live Example:
<div className="max-w-md my-4"> <Field> <FieldLabel htmlFor="email-basic">Email</FieldLabel> <Input id="email-basic" type="email" placeholder="Enter your email" /> </Field> </div>Field with Description
Add helpful context with FieldDescription:
import { Field, FieldLabel, FieldDescription, Input } from "@prisma/eclipse";
export function FieldWithDescription() {
return (
<Field>
<FieldLabel htmlFor="username">Username</FieldLabel>
<FieldDescription>Choose a unique username for your account.</FieldDescription>
<Input id="username" placeholder="Enter username" />
</Field>
);
}
Live Example:
<div className="max-w-md my-4"> <Field> <FieldLabel htmlFor="username-desc">Username</FieldLabel> <Input id="username-desc" placeholder="Enter username" /> <FieldDescription>Choose a unique username for your account.</FieldDescription> </Field> </div>Field with Error
Display validation errors with FieldError:
import { Field, FieldLabel, FieldDescription, FieldError, Input } from "@prisma/eclipse";
export function FieldWithError() {
return (
<Field>
<FieldLabel htmlFor="email-error">Email</FieldLabel>
<Input
id="email-error"
type="email"
defaultValue="invalid-email"
aria-invalid="true"
/>
<FieldDescription>We'll send updates to this address.</FieldDescription>
<FieldError>Please enter a valid email address</FieldError>
</Field>
);
}
Live Example:
<div className="max-w-md my-4"> <Field> <FieldLabel htmlFor="email-error">Email</FieldLabel> <Input id="email-error" type="email" defaultValue="invalid-email" aria-invalid="true" /> <FieldDescription>We'll send updates to this address.</FieldDescription> <FieldError>Please enter a valid email address</FieldError> </Field> </div>Field Group
Group multiple fields together with consistent spacing:
import { Field, FieldLabel, FieldDescription, FieldGroup, Input, Button } from "@prisma/eclipse";
export function FieldGroupExample() {
return (
<FieldGroup>
<Field>
<FieldLabel htmlFor="name">Name</FieldLabel>
<Input id="name" placeholder="Enter your name" />
</Field>
<Field>
<FieldLabel htmlFor="email-group">Email</FieldLabel>
<Input id="email-group" type="email" placeholder="Enter your email" />
<FieldDescription>We'll send updates to this address.</FieldDescription>
</Field>
<div className="flex gap-2">
<Button type="button" variant="default-weaker">Reset</Button>
<Button type="submit">Submit</Button>
</div>
</FieldGroup>
);
}
Live Example:
<div className="max-w-md my-4"> <FieldGroup> <Field> <FieldLabel htmlFor="name-group">Name</FieldLabel> <Input id="name-group" placeholder="Enter your name" /> </Field> <Field> <FieldLabel htmlFor="email-group-live">Email</FieldLabel> <Input id="email-group-live" type="email" placeholder="Enter your email" /> <FieldDescription>We'll send updates to this address.</FieldDescription> </Field> <div className="flex gap-2"> <Button type="button" variant="default-weaker">Reset</Button> <Button type="submit">Submit</Button> </div> </FieldGroup> </div>Horizontal Field
Use horizontal orientation for inline layouts:
import { Field, FieldLabel, Input } from "@prisma/eclipse";
export function HorizontalField() {
return (
<Field orientation="horizontal">
<FieldLabel htmlFor="search">Search</FieldLabel>
<Input id="search" placeholder="Search..." />
</Field>
);
}
Live Example:
<div className="max-w-md my-4"> <Field orientation="horizontal"> <FieldLabel htmlFor="search-horizontal">Search</FieldLabel> <Input id="search-horizontal" placeholder="Search..." /> </Field> </div>Responsive Field
Use responsive orientation to adapt to screen size:
import { Field, FieldLabel, FieldDescription, Input } from "@prisma/eclipse";
export function ResponsiveField() {
return (
<FieldGroup>
<Field orientation="responsive">
<FieldLabel htmlFor="company">Company Name</FieldLabel>
<Input id="company" placeholder="Acme Inc." />
</Field>
<Field orientation="responsive">
<FieldLabel htmlFor="website">Website</FieldLabel>
<Input id="website" type="url" placeholder="https://example.com" />
</Field>
</FieldGroup>
);
}
Live Example:
<div className="max-w-2xl my-4"> <FieldGroup> <Field orientation="responsive"> <FieldLabel htmlFor="company-resp">Company Name</FieldLabel> <Input id="company-resp" placeholder="Acme Inc." /> </Field> <Field orientation="responsive"> <FieldLabel htmlFor="website-resp">Website</FieldLabel> <Input id="website-resp" type="url" placeholder="https://example.com" /> </Field> </FieldGroup> </div>Multiple Errors
Display multiple validation errors:
import { Field, FieldLabel, FieldError, Input } from "@prisma/eclipse";
export function MultipleErrors() {
const errors = [
{ message: "Password must be at least 8 characters" },
{ message: "Password must contain a number" },
{ message: "Password must contain a special character" }
];
return (
<Field>
<FieldLabel htmlFor="password-multi">Password</FieldLabel>
<Input
id="password-multi"
type="password"
defaultValue="abc"
aria-invalid="true"
/>
<FieldError errors={errors} />
</Field>
);
}
Live Example:
<div className="max-w-md my-4"> <Field> <FieldLabel htmlFor="password-multi">Password</FieldLabel> <Input id="password-multi" type="password" defaultValue="abc" aria-invalid="true" /> <FieldError errors={[ { message: "Password must be at least 8 characters" }, { message: "Password must contain a number" }, { message: "Password must contain a special character" } ]} /> </Field> </div>Complete Form Example
A full form using all Field features:
import { Field, FieldLabel, FieldDescription, FieldError, FieldGroup, Input, Button } from "@prisma/eclipse";
export function CompleteForm() {
return (
<form>
<FieldGroup>
<Field>
<FieldLabel htmlFor="full-name">Full Name</FieldLabel>
<Input id="full-name" placeholder="John Doe" required />
</Field>
<Field>
<FieldLabel htmlFor="email-complete">Email</FieldLabel>
<Input id="email-complete" type="email" placeholder="[email protected]" required />
<FieldDescription>We'll never share your email with anyone.</FieldDescription>
</Field>
<Field>
<FieldLabel htmlFor="message-complete">Message</FieldLabel>
<FieldDescription>Tell us how we can help you.</FieldDescription>
<Input id="message-complete" placeholder="Your message..." />
</Field>
<div className="flex gap-2">
<Button type="button" variant="default-weaker">Cancel</Button>
<Button type="submit">Submit</Button>
</div>
</FieldGroup>
</form>
);
}
Live Example:
<div className="max-w-md my-4"> <form> <FieldGroup> <Field> <FieldLabel htmlFor="full-name-live">Full Name</FieldLabel> <Input id="full-name-live" placeholder="John Doe" required /> </Field> <Field>
<FieldLabel htmlFor="email-complete-live">Email</FieldLabel>
<Input id="email-complete-live" type="email" placeholder="[email protected]" required />
<FieldDescription>We'll never share your email with anyone.</FieldDescription>
</Field>
<Field>
<FieldLabel htmlFor="message-complete-live">Message</FieldLabel>
<Input id="message-complete-live" placeholder="Your message..." />
<FieldDescription>Tell us how we can help you.</FieldDescription>
</Field>
<div className="flex gap-2">
<Button type="button" variant="default-weaker">Cancel</Button>
<Button type="submit">Submit</Button>
</div>
</FieldGroup>
Field
orientation - Layout orientation ("vertical" | "horizontal" | "responsive", default: "vertical")className - Additional CSS classes (string, optional)children - Field content (ReactNode, required)FieldLabel
htmlFor - ID of the associated input (string, required for accessibility)className - Additional CSS classes (string, optional)children - Label text (ReactNode, required)FieldDescription
className - Additional CSS classes (string, optional)children - Description text (ReactNode, required)FieldError
children - Error message (ReactNode, optional)errors - Array of error objects with message property (Array, optional)className - Additional CSS classes (string, optional)FieldGroup
className - Additional CSS classes (string, optional)children - Group of Field components (ReactNode, required)htmlFor attribute that matches the input's idThe Field component is perfect for:
The Field component follows accessibility best practices:
htmlFor and idrole="alert"The Field component uses a flexible layout system:
text-destructive design tokentext-muted-foreground design tokenCustomize by passing className props:
<Field className="gap-4">
<FieldLabel className="font-bold">Custom Label</FieldLabel>
<Input />
</Field>