Docs
ComponentsLabel, Help, FieldError
View as Markdown(opens in a new tab)

Label, Help, FieldError

The three text pieces around a control, usable on their own when you compose a field by hand.

Field renders these for you. Import them when you assemble a field yourself, or to change the words without touching the schema.

Preview

Usage

import { Form, Label, Help, FieldControl, FieldError, Submit } from 'kibbleforms';

<Form schema={schema} client={kibble}>
  <div className="flex flex-col gap-1.5">
    <Label name="company">Company name</Label>   {/* children override the schema label */}
    <Help name="company" />
    <FieldControl name="company" />
    <FieldError name="company" />
  </div>
  <Submit />
</Form>

Props

Label

Prop Type Default Description
name string required The field key.
children ReactNode field.label Replaces the label text.
requiredIndicator ReactNode | null from Form/KibbleProvider, else nothing What to append when field.required.
optionalIndicator ReactNode | null from Form/KibbleProvider, else a small muted "Optional" What to append when the field isn't required; null renders nothing.
className string text-sm font-medium leading-none text-kb-fg Merged onto the element.
…<label> attributes Spread on the <label>.

Renders <label for="<control id>" id="<label id>" data-kb="label">. For grouped controls (single_choice, multiple_choice, yes_no, rating) it renders a <span id data-kb="label"> instead, because the group is labelled through aria-labelledby rather than for.

Help

Prop Type Default Description
name string required The field key.
children ReactNode field.help Replaces the help text. Renders nothing when there is none.
className string text-sm text-kb-muted-fg Merged onto the <p>.
…<p> attributes Spread on the <p>.

Renders <p id="<help id>" data-kb="help">; the id is in the control's aria-describedby. Field places it under the label, and under the checkbox row for consent fields.

FieldError

Prop Type Default Description
name string required The field key.
className string text-sm text-kb-error Merged onto the <p>.
…<p> attributes Spread on the <p>.

Renders <p id="<error id>" role="alert" data-kb="error">message</p> while the field has an error, nothing otherwise. Messages come from Kibble's validator (client and server use the same one), e.g. "This field is required", "Enter a valid email address", "Choose at most 2".

Variants and states

Required and optional marks (since 0.1.3): by default optional fields get a small, muted "Optional" after the label and required fields get no mark. Most fields on a short form are required, so a mark on each says little; screen readers hear "Optional" with the label, and required controls carry aria-required. Set either mark once for every form, or per label:

<Form schema={schema} client={kibble}>            // the default
  <Field name="email" />
</Form>

<KibbleProvider
  client={kibble}
  requiredIndicator={<span aria-hidden className="ml-0.5 text-kb-error">*</span>}   // asterisks instead
  optionalIndicator={null}
>
  <Form schema={schema}>…</Form>
</KibbleProvider>

<Label name="company" optionalIndicator={null}>Company</Label>   // one label

Resolution order for each: the Label prop, then the nearest Form/KibbleProvider that set one, then the default (nothing for required, "Optional" for optional). A required consent checkbox uses requiredIndicator; an optional one has no mark.

Customization

  • Tokens: --kb-fg (label), --kb-muted-fg (help and the "Optional" mark), --kb-error (error).
  • className="text-base font-semibold" on Label replaces the size and weight. FieldError with className="text-xs" shrinks the message.
  • CSS hooks: [data-kb="label"], [data-kb="help"], [data-kb="error"].
  • Label and help text are part of the schema (and its hash): changing them is a schema change that kibble push records as a new version; overriding with children is a display-only change.

Accessibility

Label targets the control with for (or labels a group through aria-labelledby). Help and FieldError ids are joined into the control's aria-describedby, so screen readers read help on focus and the error with the control. FieldError is a live region (role="alert"), so a new message is announced when it appears, and Kibble also moves focus to the first invalid control after a failed submit. The default * is aria-hidden; required state is conveyed by aria-required on the control.

Field, KibbleProvider, Consent, Headless: useField