Aura Design System

Form Field Composition

FormFieldSelect, FormFieldCombobox, FormFieldEditor, FormFieldSignaturePad, FormFieldSortableList — composed form fields that use field.setValue.

Form Field Composition

These components wrap non-native controls (Select, Combobox, Editor, SignaturePad, Sortable) and connect them to useFormDynamic via the same field prop used by FormField. They all accept field?: FieldProps and errors?: ErrorObject[] (typically injected by Form), and they update state with field.setValue.

Overview

ComponentPurposeValue typeHow it uses field
FormFieldSelectDropdown selectstringDoes not pass field.value to Select (uncontrolled); onValueChangefield.setValue(newValue).
FormFieldComboboxSearchable single/multistring or string[]field.setValue(value) in handler.
FormFieldEditorRich/text block editorstringfield.value → editor state; onChange(editorState)field.setValue(editorState).
FormFieldSignaturePadSignature capturestring (e.g. base64)onChange(signature)field.setValue(signature || "").
FormFieldSortableListDrag-and-drop ordered listarrayfield.value normalized to array; onValueChangefield.setValue.

FormFieldSelect

Dropdown select built on the Select UI component.

PropTypeDescription
fieldFieldPropsFrom hook.
labelReact.ReactNodeOptional.
optionsSelectOption[]{ label: string; value: string }.
placeholderstringPlaceholder when empty.
disabledbooleanDefault false.
defaultValuestringOptional.
valuestringOptional controlled value.
errorsErrorObject[]Usually from Form.
classNamestringOptional.

The Select is used without passing field.value as its controlled value; it updates the form via onValueChangefield.setValue(newValue).

<FormFieldSelect
  field={country}
  label="Country *"
  options={[
    { label: "United States", value: "us" },
    { label: "United Kingdom", value: "uk" },
  ]}
  placeholder="Select a country"
/>

FormFieldCombobox

Searchable single- or multi-select (Combobox).

PropTypeDescription
fieldFieldPropsFrom hook; multi mode uses array value (cast).
labelReact.ReactNodeOptional.
optionsComboboxOption[]Options for the combobox.
multiplebooleanDefault false; when true, value is string[].
placeholderstringOptional.
disabledbooleanDefault false.
errorsErrorObject[]Usually from Form.
classNamestringOptional.

Single: field.setValue(value: string). Multiple: field.setValue(value: string[]) (typed as string | boolean on FieldProps, cast in the component).

<FormFieldCombobox
  field={country}
  label="Country *"
  options={comboboxOptions}
  placeholder="Select a country"
/>
<FormFieldCombobox
  field={interests}
  label="Interests"
  options={interestsOptions}
  multiple
  placeholder="Select one or more"
/>

FormFieldEditor

Rich or block text editor. Value is a string (e.g. HTML or editor-specific JSON).

PropTypeDescription
fieldFieldPropsFrom hook.
labelReact.ReactNodeOptional.
errorsErrorObject[]Usually from Form.
classNamestringOptional.

Uses field.value as the editor state and field.setValue(editorState) on change.

<FormFieldEditor field={content} label="Content *" />

FormFieldSignaturePad

Signature capture; value is a string (e.g. base64 image).

PropTypeDescription
fieldFieldPropsFrom hook.
labelReact.ReactNodeRequired.
errorsErrorObject[]Usually from Form.
onSave(signature: Base64URLString) => voidOptional; called when signature is saved in addition to updating the field.
(others)SignaturePad propse.g. variant, size, penColor, lineWidth, showButtons.

Calls field.setValue(signature || "") when the signature changes.

<FormFieldSignaturePad
  field={signature}
  label="Signature *"
  variant="default"
  size="md"
/>

FormFieldSortableList

Drag-and-drop ordered list. Value is an array (stored via field.setValue; FieldProps.value is typed as string | boolean, so the component casts to array).

PropTypeDescription
fieldFieldPropsFrom hook; value treated as array.
labelReact.ReactNodeOptional.
errorsErrorObject[]Usually from Form.
renderItem(item: T, index: number) => ReactNodeRender each item. Default shows String(item).
getItemValue(item: T) => UniqueIdentifierRequired when items are objects; used for keys and drag id.
orientation"vertical" | "horizontal" | "mixed"Default "vertical".
showOverlaybooleanDefault true.
showHandlebooleanDefault true.
itemClassNamestringOptional.
contentClassNamestringOptional.

Initial value should be an array. You can set it once in an effect if the hook type is "text":

React.useEffect(() => {
  if (!Array.isArray(priorities.value)) {
    priorities.setValue(["High", "Medium", "Low"] as any);
  }
}, []);
<FormFieldSortableList
  field={priorities}
  label="Priorities *"
  renderItem={(item) => <span className="text-gray-12 flex-1">{String(item)}</span>}
/>

Composition pattern

Each of these components:

  1. Reads field.name – Used for FormRadix.Field name and for error matching when Form injects errors.
  2. Uses field.touch and errors – Sets serverInvalid and renders FormRadix.Message when field.touch && errors?.length > 0.
  3. Updates state via field.setValue – Non-native controls don’t use field.onChange; they call field.setValue(value) in their own change handlers.

For multi-value components (FormFieldCombobox with multiple, FormFieldSortableList), the hook’s FieldProps.value is typed as string | boolean, but the component treats or casts it to the correct type (e.g. string[] or any[]).

Example: mixed composed fields

const formRef = useRef<HTMLFormElement>(null);
const formData = useFormDynamic({
  country: "text",
  signature: "text",
});

const { country, signature } = formData.getFields();
const { isValid, errors } = validateFormData(schema, formData.getValues());

return (
  <Form ref={formRef} onSubmit={handleSubmit} errors={errors ?? undefined} id="demo">
    <FormAlert formData={{ fetchStatus: formData.fetchStatus, error: formData.error }} />
    <FormFieldSelect
      field={country}
      label="Country *"
      options={countryOptions}
      placeholder="Select country"
    />
    <FormFieldSignaturePad field={signature} label="Signature *" variant="default" size="md" />
    <FormSubmit fetchStatus={formData.fetchStatus} buttonProps={{ children: "Submit" }} form="demo" />
  </Form>
);