Theming

Style a form with design tokens, not one-off colours on every element. The theme becomes CSS variables on a single wrapper, and every field reads them.

The theme object

theme
{
  "theme": {
    "colors": { "primary": "#16a34a", "background": "#ffffff", "text": "#111827" },
    "radius": "lg",
    "font": "Georgia",
    "density": "spacious"
  }
}
TokenCSS variableValues
colors.primary--df-primaryAny CSS colour. Used for the button, focus rings and checked states.
colors.background--df-bgForm and input background. Setting it also adds inner padding to the form so text does not touch the coloured edge.
colors.text--df-textText colour.
radius--df-radiusnone (0), sm (4px), md (8px), lg (12px), full (pill).
density--df-gapcompact (0.5rem), comfortable (1rem), spacious (1.5rem) between fields.
font--df-fontA font family name. Load the font yourself; only letters, digits, spaces and hyphens are kept.

Pick a primary colour that keeps the white button text readable. Aim for a contrast ratio of at least 4.5:1 (WCAG AA).

Per-field overrides

A field's style sets variables for that field only: --df-field-text, --df-field-bg, --df-field-border, --df-field-radius and --df-field-font-size. Reach for it as an exception, not the default.

Your own CSS

Every token has a default in styles.css, so you can also just override the variables:

app.css
/* Override any token yourself, for one form or for all of them */
.df-form {
  --df-primary: #7c3aed;
  --df-border: #cbd5e1;
  --df-danger: #be123c;
}

Other tokens you can override: --df-muted, --df-border and --df-danger.

Class names

Stable classes: .df-form, .df-row, .df-field, .df-label, .df-input, .df-description, .df-error, .df-submit. State is exposed through attributes (aria-invalid, data-invalid on the field, data-state on Radix parts), so you can style states without extra classes.

To add your own classes per part, pass classNames. Available slots: form, row, field, label, input, option, description, error, required, submit.

classNames
<FormRenderer
  definition={definition}
  classNames={{ input: "my-input", submit: "my-submit-button" }}
/>