components / 36

marked form

a form is a conversation with consequences. sections pace it, errors point back, and submission leaves one clear trace.

shadcnnpx shadcn@latest add berkantay/cheez/marked-form
live workflow

from first field to server response

submit taken@cheez.dev to reject
form / 01
01 / identitywho should we remember?

try taken@cheez.dev to see a server error.

02 / intentwhat are we making?

short and memorable works best.

ready when the form is.
error ownership

the server speaks through the field

one object, two useful views
01return errors by name{ email: "already used" }
02the field receives it

Base UI associates the external message with the matching named field.

03the summary points back

each message is a real link to the invalid control, not decorative copy.

feedback

one state, one visual sentence

live regions stay concise
ready when the form is.
saving the draft…
saved. the mark is yours.
reference

api

Base UI behavior, Cheez composition
partproptypedefaultpurpose
FormvalidationMode"onSubmit" | "onBlur" | "onChange""onSubmit"when field validation begins
FormerrorsRecord<string, string | string[]>external or server errors by field name
FormonFormSubmit(values, details) => voidvalidated submission callback
FormactionsRefRefObject<FormActions>validate all fields or one field
Formlayout"stack" | "grid""stack"form-level composition
FormtoneMarkedFormTone"orange"action and legend ink
Sectioncolorstring"#35d9ff"section divider ink
LegendeyebrowReactNodesmall section index
Actionsalign"start" | "end" | "between""end"action placement
Statusstate"idle" | "pending" | "success" | "error""idle"live submission feedback
ErrorSummaryerrorsRecord<string, string | string[]>linked error overview

behavior notes

  • onFormSubmit only runs after every registered field is valid
  • native FormData becomes a typed values object without a second form library
  • external errors stay controlled and are cleared deliberately
  • status uses polite announcements except errors, which are assertive
  • fieldset and legend remain native semantic elements
  • submit and reset remain native button types
  • no Framer Motion is shipped