Import
import { Field } from "@kuzenbo/core";
Usage
The Field component wraps a form input with label, description, error messaging, and validation state. It’s built on Base UI’s Field primitive and integrates with the Form component.
import { Field } from "@kuzenbo/core";
const validBillingEmail = (value: unknown) => {
if (typeof value !== "string" || !value.includes("@")) {
return "Enter a valid billing email";
}
return null;
};
export default function BillingForm() {
return (
<Field name="billingEmail" validate={validBillingEmail}>
<Field.Label htmlFor="billing-email">Billing contact email</Field.Label>
<Field.Control
id="billing-email"
placeholder="[email protected]"
type="email"
/>
<Field.Description>
Invoices and delinquency notices are sent to this inbox.
</Field.Description>
<Field.Error />
<Field.Validity>
{(state) =>
state.validity.valid ? (
<span className="text-success-foreground text-sm">
Ready for invoice routing.
</span>
) : null
}
</Field.Validity>
</Field>
);
}
Sizes
Field controls support five size variants: xs, sm, md, lg, and xl.
import { Field, Input } from "@kuzenbo/core";
export default function FieldSizes() {
return (
<div className="grid gap-4">
<Field name="approvalCodeXs">
<Field.Label htmlFor="approval-code-xs">XS approval code</Field.Label>
<Field.Control
render={<Input id="approval-code-xs" size="xs" />}
/>
</Field>
<Field name="approvalCodeSm">
<Field.Label htmlFor="approval-code-sm">SM approval code</Field.Label>
<Field.Control
render={<Input id="approval-code-sm" size="sm" />}
/>
</Field>
<Field name="approvalCodeMd">
<Field.Label htmlFor="approval-code-md">MD approval code</Field.Label>
<Field.Control
render={<Input id="approval-code-md" size="md" />}
/>
</Field>
</div>
);
}
Props
Field
The name of the field. Used for form data and validation.
validate
(value: unknown) => string | null
Validation function. Return an error message string or null if valid.
When true, disables the entire field and all its controls.
Additional CSS classes for the field container.
Field.Label
Associates the label with a control element by ID.
Field.Control
ID for the input element, should match the label’s htmlFor.
Placeholder text for the input.
HTML input type (text, email, password, number, etc.).
size
'xs' | 'sm' | 'md' | 'lg' | 'xl'
default:"md"
Visual size of the control.
Custom control element to render instead of the default input.
Field.Description
Helper text displayed below the control.
Field.Error
Automatically displays validation error messages. No props required.
Field.Validity
children
(state: FieldState) => ReactNode
Render function that receives the field’s validation state.
Composition
import { Field } from "@kuzenbo/core";
<Field.Root name="apiKey">
<Field.Label>API Key</Field.Label>
<Field.Control type="password" />
<Field.Description>Your production API key</Field.Description>
<Field.Error />
</Field.Root>
Types
export type FieldProps = FieldRootProps;
export type FieldControlProps = ComponentProps<typeof BaseField.Control>;
export type FieldDescriptionProps = ComponentProps<typeof BaseField.Description>;
export type FieldErrorProps = ComponentProps<typeof BaseField.Error>;
export type FieldLabelProps = ComponentProps<typeof BaseField.Label>;
export type FieldValidityProps = ComponentProps<typeof BaseField.Validity>;
Accessibility
- Label is properly associated with the control via
htmlFor/id
- Error messages are announced to screen readers via
aria-describedby
- Invalid state is communicated via
aria-invalid
- Disabled state prevents interaction and is announced
- Description text is linked to the control for context