0.1.0-rc.2

Form

Forms coordinate validation, default values, and submission across RuiField children without external form libraries.

Try it

Usage

Wrap fields in RuiForm and handle validated values with onSubmit. Choose mode to control when validation runs.

import { RuiForm } from '@ecopages/radiant-ui/form';
import { RuiField } from '@ecopages/radiant-ui/field';
import { RuiLabel } from '@ecopages/radiant-ui/label';
import { RuiInput } from '@ecopages/radiant-ui/input';
import { RuiButton } from '@ecopages/radiant-ui/button';
 
<RuiForm mode="onSubmit" onSubmit={handleSubmit}>
  <RuiField name="name" rules={{ required: 'Name is required' }}>
    <RuiLabel>Full name</RuiLabel>
    <RuiInput />
  </RuiField>
  <RuiButton type="submit">Create account</RuiButton>
</RuiForm>

Load @ecopages/radiant-ui/styles.css once in your app to style the form and every composed control. When bundling styles per component, import @ecopages/radiant-ui/form/styles.css plus the stylesheet for every component used inside the form, such as field/styles.css, textarea/styles.css, or number-field/styles.css.

Validation timing

onSubmit validates once on submit and is best for short forms. Use onBlur or onChange when immediate feedback helps data entry.

Compose with Radiant controls

Every RuiField child should be a Radiant control (RuiInput, RuiSelect, RuiDateField, …). The form store discovers values through the Field control protocol, unmarked native inputs are not registered.

Default values

Pass defaultValues to pre-populate edit forms. Fields read their initial state from the form store.

Theming

Form surfaces map to semantic surface roles, never Tailwind palette steps:

PartCSS roles
Root (.rui-form)space-stack gap

The form itself carries no color roles; fields, labels, and controls inside keep their own surface / control tokens. Override at the theme layer, not in component CSS.

API

RuiForm is a custom element (<rui-form>). The RuiForm view is a passthrough that maps defaultValues / resolver to prop: bindings.

Attributes

AttributeTypeDefaultDescription
modeonSubmit · onBlur · onChange · onTouched · allonSubmitWhen validation runs.
revalidate-modeonSubmit · onBlur · onChange · onTouched · allonChangeWhen fields re-validate after a failed submit.
data-default-valuesstringJSON-serialized default values for SSR / JSX attribute channel.
actionstringNative form destination when onSubmit is not provided.
methodstringNative form HTTP method when onSubmit is not provided.

Props

PropTypeDescription
defaultValuesPartial<FieldValues>Initial values; fields read their state from the form store.
resolverResolver<T>Custom validation resolver (e.g. from createRulesResolver).
onSubmit(values: T) => void | Promise<void>Receives validated values. When omitted, an action or method submits the native form after validation passes.

Context

formContext exposes the current errors map to custom consumers. RuiField reads the matching field state and applies it to its control as aria-invalid; use fieldContext for a control's local error and invalid values.

Events

EventDetailDescription
rui-submit{ values: T }Emitted when validation passes.
rui-invalid{ errors: Record<string, { message?: string }> }Emitted when validation fails on submit.

CSS classes

Public BEM classes (documented via @cssclass):

ClassDescription
.rui-formRoot form surface (<form noValidate>).

Theme roles

PartCSS variables consumed
Root--space-stack

Accessibility

  • Submit buttons should use type="submit" inside the form for keyboard submission.
  • Announce form-level errors at the top when multiple fields fail validation.
  • Focus the first invalid field after a failed submit attempt.