The Basics

What it is

Form is a container that provides a framework for input fields that are typically contained in FormField and MultiField components. Form comes with a default Submit button and provides options for layout density, label placement, and required field styling, which are then applied to the FormField and MultiField components inside it. It does not include input validation; teams must build this code themselves.

How it works

  • Form loads and displays its contents.
  • Users interact with the inputs and enter their necessary data.
  • When the Form has been completed, the user clicks or activates the Submit button to save the data they’ve entered.

When to use

  • For forms that should follow the typical Forge layout and styling
  • To build a form quickly without having to spend time customizing layout and styles

When not to use

  • For forms built with inputs that don’t use FormField or MultiField (it’s technically possible to use them inside Form, but you wouldn’t be able to use Form's layout and style features, which are designed to work with FormField and MultiField)
  • For special form layouts where a lot of effort would be required to work around the Forge styles: consider using the HTML element <form> instead

What to use instead

No suggestions for this component.

How to use

Form is used in the code to organize and lay out form elements. Designers should understand how to create responsive forms based on its framework, but there’s no actual Form component found in the Figma design library. Specific Form features (like required fields styling and input spacing) can be found in Figma; these are described in greater detail below. For more information about form best practices, see Form Design.

Form is a container that provides responsive features based on the Grid component. It should be used mainly with Forge inputs that are wrapped in FormField or MultiField, which add features like labels, error message handling, and hint text. Form can also accept other components, which is useful for grouping content and inputs (e.g., with Heading or ShowHide) and for adding alerts and messages (e.g., with Banner or Signpost).

Input validation

Form does not have built-in input validation (code that checks user-entered data against a set of expectations and flags any errors).

Teams will need to build any validation for their forms, including:

  • Checking that required fields have data in them
  • Confirming that data is in the correct format (e.g., a new password meets system requirements, an email address is formatted correctly)
  • Showing and hiding error messages and styles
  • Blocking form submission until errors are resolved

FormField and MultiField components can be set as required, which marks them for handling by any validation code.

Required field styles

Form offers 3 styles for required fields. These styles are applied to any FormFields that are set as required. MultiField lets you set all inputs as required or just individual fields.

Whichever required field style you choose is applied to all required fields in the Form. You can’t use different required field styles on different fields in a Form.

Forge styles for required fields use one or more of these design elements:

  • A vertical blue bar next to or inside the form field. This bar changes to the Attention alert color (yellow) to indicate an error state.
  • The text “Required” in either the form legend or the form label. This text is necessary for accessibility reasons: indicating required fields with just a visual element like the blue bar isn’t enough.
  • A legend at the top of the form.

Forge’s 3 required field styles combine these design elements. Choose the option that’s the best fit for your use case:

A few required fields

  • Use Option 1: Bar with “- Required” label. This style includes:
    • Vertical blue bar
    • The text “- Required" added to the end of the form label
  • Design notes:
    • This style is good for short forms and forms with only a few required fields.
    • It’s also good in designs where displaying a legend at the top of the form would be difficult (e.g., due to limited space or a complex page design).

Many required fields

  • Use Option 2: Bar with legend. This style includes:
    • Vertical blue bar
    • A legend at the top of the form explaining that a blue bar indicates a required field
    • No change to the form label text
  • Design notes:
    • This style is good for forms with a lot of required fields. The “- Required” text would create visual clutter in this case.
    • This style is also good if the form labels are already long, and you don't want to add “- Required” to them.

All fields are required

  • Use Option 3: “All fields required” legend. This style includes:
    • An “All fields required” legend at the top of the form
    • No vertical blue bar
    • No change to the form label text

Form doesn’t have a style for use cases where all fields are required except for a few optional fields.

Reminder: Form handles only the required field styles. Validation code to check that required fields have values isn’t included; your team must build this.

Layout density

Form includes 3 layout density levels:

  • Medium (default): Best for most use cases. Use this unless your app has special design requirements like those listed below.
  • Compact: Suitable for denser forms with many inputs. Vertical space between inputs is reduced.
  • Super-compact: Use for very dense, data-heavy forms only. Both input field height and vertical space between inputs are reduced. This layout is for highly repetitive workflows, like athenaCollector data entry.

Label position and width

Form field labels are placed to the left of their inputs by default. When the viewport shrinks to a certain breakpoint, the labels switch to being placed above their inputs instead. Form can also be set to always place labels above their inputs.

Label element width is based on Forge Grid columns. In the Grid framework, a horizontal “row” of space on the page is divided into 12 columns. Form’s label element is 3 columns wide by default but can be changed. This width is used if labels are to the left of their inputs, but not if labels are set to always appear above their inputs.

You can set the label position and width for individual FormFields and MultiFields in your Form. This lets you override the overall Form settings for specific labels and inputs only.

Submit button

Form comes with a primary Button for submitting the form when complete. This button appears at the bottom of the Form, left aligned with left side of the inputs (not the labels). Depending on your use case, you can also replace the default button with your own set of buttons or remove the button entirely.

Style

Design details

For help organizing form content using Forge best practices, see Form Design.

Placement and hierarchy

No additional information for this component.

Content

Form’s contents are typically FormField and MultiField components, which bundle form input fields with labels, error message handling, hint text, and responsive layout behavior. You can also add other Forge components and HTML inside Form (e.g., Heading, Banner, custom code).

Labels

When writing form field labels, look for repetitive information that could be moved out of the label and into a Heading instead. For example, the labels “Patient name”, “Patient address”, and “Patient phone” could be changed to “Name”, “Address”, and “Phone” in a section with the heading “Patient Contact Information”. Use sentence case for labels (“Date of service”, not “Date of Service”).

Submit button

The default button text is “Submit”. This can be changed to fit your use case (e.g., “Save Settings”). Button text typically starts with a verb, like “Save” or “Submit”. Use title case (“Save Changes”, not “Save changes”). The Form component also has the option to swap in your own custom buttons, if the single default button doesn’t fit your use case.

Demos

Form Layout Share

Basic Form Share

Form Validation Share

Required Variations Share

Coding

Developer tips

Form provides a wrapper around the native html <form> element. Developers should use Form as a container for FormField and MultiField components.

Input validation and required fields

Form does not have built-in input validation, including checking for values in required fields. Developers must implement this themselves. See the Demos for an example of validation code.

Native browser checking for required fields is suppressed by the Form component. This is done so that users don’t get a mix of browser error messages and Forge-style error messages. If necessary, you can turn it back on by setting the noValidate prop to {false}.

Customizing buttons

Form includes one submit Button by default. Use the buttonText prop to change its text.

You can also swap in your own custom button row, if your use case requires more than one button. To do this:

  1. Set the includeSubmitButton prop to {false} to remove the default button.
  2. Add a FormFieldLayout component to your Form and pass your custom button row component to its inputSlot prop, as in this example:
<Form includeSubmitButton={false}>
<FormFieldLayout inputSlot={<MyButtonRow />} />
</Form>

FormFieldLayout is a subcomponent used for handling layout within Form. Using it here will keep your buttons in alignment with the rest of the Form contents. You will need to import the FormFieldLayout component at the top of your file. See the FormField Props section for import code and documentation.

Form’s default Button has the type 'submit'. For your custom buttons, consider Button’s other 2 types, 'reset' and 'button', which are useful for other form actions.

ReduxForm component

Redux features were removed in Forge 3, including the 3 Redux-based components: ReduxForm, ReduxFormField, and ReduxMultiField (see the FAQ for details). Forge 3 still supports the use of Redux. Teams can use the separate package forge-redux-form.

Layout options

Form provides 3 options for layout: medium, compact, and super-compact.

The documentation lists an extra option for the layout prop: the 'large' layout. This was added to support mobile-friendly form layouts built with the Spark design system, which uses Forge. The large layout is available for Forge use, but it might not look good, and the Forge team doesn’t have UX guidance for it.

Repository

Implementation links

Form directory in Bitbucket

Implementation details

It is strongly recommended to familiarize yourself with the Forge source code. While this documentation is a best effort to document the intent and usage of a component, sometimes some features only become clear when looking at the source code. Also, looking at Forge's source code may help identify and fix bugs in either your application or Forge itself.

Storybook files

Forge maintains at least one storybook file per component. While the primary audience for these files is typically the Forge team, these storybook files may cover usages of the component not covered by a demo. The storybook for the latest version of forge can be found at go/forge-storybook.

Testing library

Forge strongly encourages using testing-library to write tests for your application.

"The more your tests resemble the way your software is used, the more confidence they can give you."

If you're having trouble testing a Forge component using testing-library, it would be a good idea to see how Forge tests its own components. For the most part, Forge tries to use screen.getByRole as much as it can, as that API provides the best feedback on a11y compliance. Forge discourages the use of document.querySelector and screen.getByTestId as both APIs encourage using implementation details to test your component, and discourage adding roles to your component.

With that being said, many of Forge's components were not built with accessability in mind. These components do break the recommendations listed above.

Import statements

In Nimbus applications

athenaOne serves the Forge bundle independently from your application's bundle. Importing Forge components directly from '@athena/forge' takes advantage of this feature.

import { Form } from '@athena/forge'

In standalone applications

Importing components using the exact path to the module takes advantage of webpack's tree shaking feature. Webpack will include only that module and its dependencies.

import Form from '@athena/forge/Form';

To use this import guidance, Typescript applications must use typescript >= 4.7.3, and should add this setting to their tsconfig.json file:

{
"compilerOptions": {
"moduleResolution": "Node16",
}
}

If this setting doesn't work for your application, use this import statement instead:

import Form from '@athena/forge/dist/Form';

Props