No Preview

Sorry, but you either have no stories or none are selected somehow.

If the problem persists, check the browser console, or the terminal you've run Storybook from.

The component failed to render properly, likely due to a configuration issue in Storybook. Here are some common causes and how you can address them:

  1. Missing Context/Providers: You can use decorators to supply specific contexts or providers, which are sometimes necessary for components to render correctly. For detailed instructions on using decorators, please visit the Decorators documentation.
  2. Misconfigured Webpack or Vite: Verify that Storybook picks up all necessary settings for loaders, plugins, and other relevant parameters. You can find step-by-step guides for configuring Webpack or Vite with Storybook.
  3. Missing Environment Variables: Your Storybook may require specific environment variables to function as intended. You can set up custom environment variables as outlined in the Environment Variables documentation.

This is a pre-release version and is not production ready. For new and ongoing projects, please refer to the latest Design System version.

How to forms

All things need to be contained inside a container. The container limits the size of the content and centers it on the page.

<div class="container">...</div>

For accessibility reasons, form fields should always have a label linked via the id/for attributes. Screen-readers will announce the label when the input gets the focus. If there is no label, screen-reader users have no idea what the input should be, even if there is other text next to the field.

<label class="form-label" for="firstname">Firstname</label> <input type="text" id="firstname" class="form-control" />

To add space between input, you can use margin utilities.

<div class="mb-16"> <label for="firstname">Firstname</label> <input type="text" id="firstname" class="form-control" /> </div> <div class="mb-16"> <label for="lastname">Lastname</label> <input type="text" id="lastname" class="form-control" /> </div>

If you want a form field to span the whole available width, you don't need a row nor a col. You only need those, if you want to place two things next to each other.

Simply use .row and .col to have the width distributed evenly between all inputs. To make it responsive, you can add .row-cols-* classes to the row (see Grid page).

<div class="row row-cols-1 row-cols-md-2"> <div class="col"> <label class="form-label" for="firstname">Firstname</label> <input type="text" id="firstname" class="form-control" /> </div> <div class="col"> <label class="form-label" for="lastname">Lastname</label> <input type="text" id="lastname" class="form-control" /> </div> </div>

For finer adjustment, you can also use the .col-* classes (see Columns page) on your columns. For example for a 2/1 ratio, given that a row has twelve columns in total, just add .col-8 and .col-4 to you two columns respectively.

<div class="row"> <div class="col-8"> <label class="form-label" for="city">City</label> <input type="text" id="city" class="form-control" /> </div> <div class="col-4"> <label class="form-label" for="state">State</label> <input type="text" id="state" class="form-control" /> </div> </div>

Some fields may not fit into the twelve row schema, they need a custom width. The PLZ field may be one of those cases. Two .col next to each other will have equal width. If one of the cols has the .col-auto class, this col is sized based on it's content. The other row is stretched to the container width. With this setup, we can define a max-width on the input field to shrink it.

<div class="row"> <div class="col-auto"> <label class="form-label" for="zip">Zip</label> <input type="number" id="zip" class="form-control" style="max-width: 11ch" /> </div> <div class="col"> <label class="form-label" for="city">City</label> <input type="text" id="city" class="form-control" /> </div> </div>

Buttons, often at the end of the form are right aligned. We can achieve this with the classes d-flex flex-row-reverse. This will ensure that the primary button is focused first (because of the markup order) but is still aligned to the right. To get some margin between the button we can use the .gap-8 class. Note that for the buttons, we don't need any row/col structure.

<div class="mb-16"> <label for="firstname">Firstname</label> <input type="text" id="firstname" class="form-control" /> </div> <div class="d-flex flex-row-reverse gap-8"> <button class="btn btn-primary">Send</button> <button class="btn btn-secondary">Cancel</button> </div>

For internet applications, bigger input fields with floating labels are the Post way of creating forms. The particularity of these fields, is that the <label> and <input> elements are inverted and wrapped in a .form-floating div. In addition, the input field needs a placeholder attribute, preferably equal to a single space.

<div class="row"> <div class="col"> <div class="form-floating"> <input type="text" id="firstname" class="form-control" placeholder=" " /> <label class="form-label" for="firstname">Firstname</label> </div> </div> <div class="col"> <div class="form-floating"> <input type="text" id="lastname" class="form-control" placeholder=" " /> <label class="form-label" for="lastname">Lastname</label> </div> </div> </div>

Validation messages are placed directly after the <input> (or after the <label> in the case of floating label). Showing and hiding of these messages is typically controlled by adding and removing validation classes on the input:

  • The message needs the class .invalid-feedback/.valid-feedback
  • The form needs the class .was-validated. With this class you can manage when to display errors. Usually, errors should not be shown on untouched fields.

Or

The input field needs the class .is-invalid/.is-valid

Error message

Success message (optional)

Error message

Success message (optional)

Error message

Success message (optional)

Error message

Success message (optional)

Error message

Success message (optional)

Error message

Success message (optional)

Error message

Success message (optional)

Error message

Success message (optional)

Error message

Success message (optional)

<form action="/"> <!-- Form Control --> <div class="row mb-16"> <div class="col-md-6"> <div class="form-floating"> <input id="formControlInvalid" type="text" class="form-control is-invalid" placeholder=" " required="" /> <label class="form-label" for="formControlInvalid">Invalid Input</label> <p class="invalid-feedback">Error message</p> </div> </div> <div class="col-md-6"> <div class="form-floating"> <input id="FormControlValid" type="text" class="form-control is-valid" placeholder=" " value="Value" /> <label class="form-label" for="FormControlValid">Valid Input</label> <p class="valid-feedback">Success message (optional)</p> </div> </div> </div> <!-- Form Select --> <div class="row mb-16"> <div class="col-md-6"> <div class="form-floating"> <select id="FormSelectInvalid" class="form-select is-invalid" required=""></select> <label class="form-label" for="FormSelectInvalid">Invalid Select</label> <p class="invalid-feedback">Error message</p> </div> </div> <div class="col-md-6"> <div class="form-floating"> <select id="FormSelectValid" class="form-select is-valid"> <option disabled="">Select one..</option> <option value="1">Value 1</option> <option value="2">Value 2</option> </select> <label class="form-label" for="FormSelectValid">Valid Select</label> <p class="valid-feedback">Success message (optional)</p> </div> </div> </div> <!-- Form Select Multiple--> <div class="row mb-16"> <div class="col-md-6"> <div class="form-floating"> <select id="FormSelectMultipleInvalid" class="form-select is-invalid" multiple="" required="" ></select> <label class="form-label" for="FormSelectMultipleInvalid"> Invalid Select Multiple </label> <p class="invalid-feedback">Error message</p> </div> </div> <div class="col-md-6"> <div class="form-floating"> <select id="FormSelectMultipleValid" class="form-select is-valid" multiple=""> <option value="1">Value 1</option> <option value="2">Value 2</option> </select> <label class="form-label" for="FormSelectMultipleValid">Valid Select Multiple</label> <p class="valid-feedback">Success message (optional)</p> </div> </div> </div> <!-- Form File --> <div class="row mb-16"> <div class="col-md-6"> <div class="form-floating"> <input id="FormFileInvalid" type="file" class="form-control is-invalid" required="" /> <label class="form-label" for="FormFileInvalid">Invalid File</label> <p class="invalid-feedback">Error message</p> </div> </div> <div class="col-md-6"> <div class="form-floating"> <input id="FormFileValid" type="file" class="form-control is-valid" /> <label class="form-label" for="FormFileValid">Valid File</label> <p class="valid-feedback">Success message (optional)</p> </div> </div> </div> <!-- Form Textarea --> <div class="row mb-16"> <div class="col-md-6"> <div class="form-floating"> <textarea id="FormTextareaInvalid" type="text" class="form-control is-invalid" placeholder=" " required="" ></textarea> <label class="form-label" for="FormTextareaInvalid">Invalid Textarea</label> <p class="invalid-feedback">Error message</p> </div> </div> <div class="col-md-6"> <div class="form-floating"> <textarea id="FormTextareaValid" type="text" class="form-control is-valid" placeholder=" "> Value </textarea > <label class="form-label" for="FormTextareaValid">Valid Textarea</label> <p class="valid-feedback">Success message (optional)</p> </div> </div> </div> <!-- Form Checkbox --> <div class="row mb-16"> <div class="col-md-6"> <div class="form-check"> <input class="form-check-input is-invalid" id="FormCheckboxInvalid" type="checkbox" /> <label class="form-check-label" for="FormCheckboxInvalid">Invalid Checkbox</label> <p class="invalid-feedback">Error message</p> </div> </div> <div class="col-md-6"> <div class="form-check"> <input class="form-check-input is-valid" id="FormCheckboxValid" type="checkbox" checked="" /> <label class="form-check-label" for="FormCheckboxValid">Valid Checkbox</label> <p class="valid-feedback">Success message (optional)</p> </div> </div> </div> <!-- Form Radio --> <div class="row mb-16"> <div class="col-md-6"> <div class="form-check"> <input class="form-check-input is-invalid" id="FormRadioInvalid" type="radio" /> <label class="form-check-label" for="FormRadioInvalid">Invalid Radio</label> <p class="invalid-feedback">Error message</p> </div> </div> <div class="col-md-6"> <div class="form-check"> <input class="form-check-input is-valid" id="FormRadioValid" type="radio" checked="" /> <label class="form-check-label" for="FormRadioValid">Valid Radio</label> <p class="valid-feedback">Success message (optional)</p> </div> </div> </div> <!-- Form Range --> <div class="row mb-16"> <div class="col-md-6"> <div class=""> <label class="form-label" for="FormRangeInvalid">Invalid Range</label> <input class="form-range is-invalid" id="FormRangeInvalid" type="range" /> <p class="invalid-feedback">Error message</p> </div> </div> <div class="col-md-6"> <div class=""> <label class="form-label" for="FormRangeValid">Valid Range</label> <input class="form-range is-valid" id="FormRangeValid" type="range" /> <p class="valid-feedback">Success message (optional)</p> </div> </div> </div> <!-- Form Switch --> <div class="row mb-16"> <div class="col-md-6"> <div class="form-check form-switch"> <input id="FormSwitchInvalid" class="form-check-input is-invalid" type="checkbox" role="switch" /> <label class="form-check-label" for="FormSwitchInvalid">Invalid Switch</label> <p class="invalid-feedback">Error message</p> </div> </div> <div class="col-md-6"> <div class="form-check form-switch"> <input id="FormSwitchValid" class="form-check-input is-valid" type="checkbox" role="switch" checked="" /> <label class="form-check-label" for="FormSwitchValid">Valid Switch</label> <p class="valid-feedback">Success message (optional)</p> </div> </div> </div> </form>

Hints can help users better understand the type of information they need to provide. Hints, like validation messages, must be placed after the <input> (or <label> in the case of floating label) and after validation messages if there are some.

Hints use the class .form-hint.

To enable screen-readers to detect and read your hints, link the <input> with the aria-describedby attribute to the hint via id.

Also provide any middle names in this field

<div class="form-floating"> <input type="text" id="firstname" aria-describedby="firstname-hint" class="form-control" placeholder=" " /> <label class="form-label" for="firstname">Firstname</label> <p id="firstname-hint" class="form-hint">Also provide any middle names in this field</p> </div>

The form footer is placed at the end/bottom of a form or a form step, in case the form is splitted with a stepper. It provides workflow-related actions to the form or form step.

<div class="form-footer"> <div class="form-footer-primary-actions"> <button class="btn btn-primary"> Send<post-icon aria-hidden="true" name="3020"></post-icon> </button> <button class="btn btn-secondary">Cancel</button> </div> <button class="btn btn-tertiary px-0"> <post-icon aria-hidden="true" name="3024"></post-icon>Back </button> </div>