Styling
Style forms with CSS on the class hooks, the shadcn registry, or your own renderers.
The renderer is headless by design. Pick the lightest path that fits your project.
Path 1: CSS on the class hooks
The built-in renderers emit stable classes. Write CSS against them and change nothing else:
| Class | Element |
|---|---|
fb-field | Wrapper div around the entire field |
fb-field__label | label |
fb-field__required | Required asterisk span (aria-hidden) |
fb-field__messages | Description + errors region |
fb-field__description | Description line |
fb-field__errors | Error group (role="alert", aria-atomic) |
fb-field__error | Individual error messages |
fb-input / fb-textarea / fb-select / fb-checkbox | The controls |
The field wrapper carries data-invalid when the field has errors:
.fb-field[data-invalid] .fb-input {
border-color: red;
}For the optional grid, import the stylesheet and use FormLayout + widthProps (Rendering); the grid uses fb-form--grid on the container and data-width on each slot.
Path 2: the shadcn registry
For projects on shadcn, a registry block installs styled field renderers and a preconfigured <FormBuilderForm> into your codebase. You own the copied files.
The registry JSON builds to registry/r/form.json in the package source; hosting it is a follow-up. Until then, point the CLI at the raw file:
npx shadcn@latest add <registry-url>/r/form.jsonInstalled: the @10x-media/form-builder dependency, shadcn input/textarea/label primitives, components/form-builder/form-builder-form.tsx, a shadcnRenderers map, and a styled renderer for every built-in field type under components/form-builder/fields/.
import { FormBuilderForm } from '@/components/form-builder/form-builder-form'
<FormBuilderForm form={form} onSuccess={(id) => console.log('submitted', id)} /><FormBuilderForm> is <Form> preconfigured with the styled renderers; any renderers prop you pass merges on top. The shipped styling is a baseline to edit, not an API.
Path 3: your own renderers or markup
Replace renderers per type with defineFieldRenderer + resolveRenderers, or take full markup control with children + useField. Both are covered in Rendering, including the a11y contract custom renderers must uphold.
Choosing
- Existing design system with CSS conventions: Path 1.
- shadcn project that wants a working styled form now: Path 2.
- Component library with its own inputs, or exact markup requirements: Path 3.
The paths compose: shadcn for most fields plus one custom renderer for a bespoke type is a normal setup.