Axon 911 Frontend DocsAxon 911 Frontend Docs
Axon 911 Frontend Docs
    Loading navigation…
U
User
Switch to light mode
  1. Blocks
  2. Form Layout Drawer
  3. Usage

Form Layout Drawer

Usage

FormLayoutDrawer is the page pattern for a form in a side drawer: a header with the title and a close button, a body of fields that scrolls, and a footer with Cancel and Submit that stays in view. Give it the fields, the copy, and an onSubmit that validates and saves. Do not assemble a Drawer, a form layout and a discard prompt in a page. For record detail that is not a form, use DetailDrawer. Coming from ui-forms DrawerForm? packages/ui/docs/migrating-from-ui-forms.md covers returning Saved or Invalid from a react-hook-form submit, dirty, and resetting the form when the drawer closes.
Fields
children are the fields (Field, Fieldset, Select, Combobox, NumberField, TextArea, DateInput, Checkbox (or CheckboxGroup), CheckboxCards, RadioGroup, RadioCards, SegmentedControl, DurationField, FileUpload, or Slider; not a Switch, ADR 0023 decision 5), stacked in a column in the drawer's scrolling body on the FormLayoutStandard layout. Give each field a name: the form data and the unsaved-edits check read named controls only. description and requiredHint sit above the fields; say what the required marker means once, in requiredHint.
Actions
Cancel and Submit sit in the drawer footer, outside the scrolling body, so they stay in view. The Submit Button is linked to the form with the native form attribute, so Enter in a single-line field still submits. Focus starts on the first field, not on the header close button.
Submit
onSubmit(event) runs on a native submit. The block prevents the native navigation and ignores a repeat submit. Read the values with new FormData(event.currentTarget) and validate there.
  • Return nothing, or FormLayoutDrawerSubmitResult.Saved: the drawer closes.
  • Return FormLayoutDrawerSubmitResult.Invalid after a failed validation: the drawer stays open. Set invalid (and errorSummary for a form-level message) in the same handler, and focus moves to the first invalid field.
  • Return a promise: the Submit Button shows its loading state, Cancel is unavailable, and a close request does nothing until the promise settles. A fulfilled promise closes the drawer, or keeps it open when it resolves to Invalid. A rejected promise keeps it open and is not rethrown; report the failure from the handler and pass errorSummary.
Unsaved edits
Closing a form with unsaved edits, by Cancel, the header close button or Escape, opens a discard prompt (a ConfirmDialog) instead of closing. "Keep editing" returns to the form with its values and focus; "Discard" closes both. A pristine form closes at once. The edits are the named controls' data compared with their data when the form opened. Pass dirty to say so yourself, for edits the controls do not carry or a control that fills in after open.
The footer
The footer has two ends. At the inline start, summary is one line of status text: a count, a save state, or a validation that spans the form ("Apply at least 1 permission"). It is never a button or a link. At the inline end the actions run tertiary, Cancel, primary. The only tertiary action is Reset, which you pass as reset for a record that has defaults to return to; a blank new record has none. Reset confirms with reset.discard when the form has edits, then returns the fields to the values they had when the form opened and calls reset.onReset so you can clear your own error state. The primary stays enabled for a pristine form, and a failed submit reports through errorSummary (ADR 0023, decisions 12 and 13).
Open state
Uncontrolled, the trigger opens the drawer and defaultOpen opens it on mount. Controlled, pass open and onOpenChange. onOpenChange(false, details) is called for a pristine close (close-press or close-request), a discard (close-press) and a saved submit (form-submit); details.cancel() keeps it open. It is not called for a close that is held or confirmed away.
Modality
The drawer is always modal: a scrim, a focus trap and an inert page. A backdrop press does not close a modal drawer, so edits cannot be lost to a stray click. A non-modal Drawer closes on an outside press with a light-dismiss that cannot be vetoed, so this block does not offer it.
Styles
Load the stylesheets of what it composes: drawer/styles.css, form/styles.css, field/styles.css, button/styles.css, box/styles.css, blocks/form-layout-standard/styles.css, and blocks/confirm-dialog/styles.css with its own list, plus the stylesheet of each control you pass. The block's own blocks/form-layout-drawer/styles.css too.
Previous
Form Dialog / Accessibility
Next
Form Layout Drawer / API and Development
On this page
Fields
Actions
Submit
Unsaved edits
The footer
Open state
Modality
Styles