Skip to main content
react-md
Form - Demos

#Form

This package exposes a few components to help render accessible forms:

  • Checkbox
  • Radio
  • InputToggle
  • Switch
  • AsyncSwitch
  • FileInput
  • TextField
  • TextArea
  • Password
  • NativeSelect
  • Label
  • Form
  • Fieldset

There are also some hooks available for controlling the state of these components:

  • useChecked
  • useChoice

#Text Field Example

Text fields are a wrapper for the <input type="text" /> with some general themes and styles applied. There are four different themes available by default:

  • "unstyled" - removes all the default borders, background colors, etc.
  • "underline" - adds an underline to the text field that animates in when the input gains focus as well as including a floating label
  • "filled" - an extension of the "underline" theme that also adds a background color to it
  • "outline" - adds a outline to the text field and animates a floating label with it.
Text field theme
Text field options
Underline Directionleft

#Text Field Types

The TextField component also has some limited support for rendering as other text input tyes:

  • password
  • number
  • tel
  • email
  • date
  • time
  • datetime-local
  • month
  • week
  • url

When you set the type prop to one of these values, no additional functionality or validation will be built in. The only support out of the box is to be styled correctly with some of the different types.

The "password" type is sort of an exception for this as there is a helper component: Password that allows the user to conditionally show the password in plain text.

Text field theme

#Text Area Example

The TextArea component is a general wrapper for the <textarea> element with most of the same styles as the TextField. The TextArea will default to have a minimal starting height and animates as the user types. This behavior can be updated so that the transition for height changes is disabled and happens immediately. The default behavior is to allow the textarea to infinitely grow, but specific limits can be set by using the maxRows prop. The textarea will grow until the row limit and then allow native scrolling behavior within the textarea.

If this behavior is undesired, the resize prop can be changed to allow the user to manually resize instead with one of:

  • horizontal
  • vertical
  • both (native behavior)

Note: When the resize prop is set to "horizontal" or "both", the TextArea will be forced to render inline so that it can be resized horizontally.

Text field theme
Text field options
Underline Directionleft
Textarea options

#File Input Example

A file input is just a simple wrapper of the <input type="file" /> that adds some default styles to look like a button. This means that all the themes available for a button are also available for this component. The file input has some reasonable defaults by showing a download file icon and a screen reader only accessible label of Upload. Unlike buttons, the file input is defaulted to render as an icon button with the primary theme color and the contained styles.

To use this component, you must provide:

  • an id for accessibility and making the button clickable
  • an onChange event handler
Last selected file:
None
Theme
Theme type

#Native Select Example

The NativeSelect component is a simple wrapper for the <select> element with TextField styles. Just like native <select> elements, this wrapper does not support:

  • placeholder text
  • enabling readOnly (it can almost manually be done by disabiling each option yourself, but it'll make it impossible to close on mobile devices if it there are so many options that it covers the entire viewport)

That being said, the demo below will show you some patterns you can use to fake placeholder text using the floating label and an empty <option> element as well as a read-only view by disabling all <option>s.

Text field theme
Text field options
Underline Directionleft
Select options

#Select Example

The Select component is a custom widget that allows you to have additional styling controls for a native <select> element while still being accessible. This component inherits all the TextField styles just like the NativeSelect, but also allows each option to be rendered like a ListItem from the @react-md/list and @react-md/menu packages.

Note: Even though the Select component supports the inline prop, it does not behave the same was as the NativeSelect or a native <select> component since it will not automatically update it's width to be the longest renderable option. The size will update whenever the value of the select changes.

This component is fully controlled, so you will need to provide the current value, an onChange handler, and a list of options. An option can be:

  • a number
  • a string
  • or an object of props to pass to a ListItem (see the next example for more details here)

The onChange handler will not be a native change event since there are no <input> or <select> elements being rendered. Instead, the onChange handler will be provided the next value string as the first argument and the option as the second: onChange(nextValue: string, option: object | string | number).

Just like a native <select> component, the list of options can be shown by clicking, pressing the space key, or using the up and down arrow keys. Once the list of options are shown, the user can:

  • type letters to find a match starting with the same letters
  • use the up and down arrow keys to focus the previous and next items
  • use the home and end keys to focus the first and last items
  • press the escape key to close the listbox
  • use the space or enter key to select and close the listbox

Check out the next example for some better examples of the typeahead feature

Text field theme
Text field options
Underline Directionleft
Select options
LabelPlaceholder

#Customizing Select Options

The default behavior for the Select component is to just render any number or string options as the children within the ListItem. Since it is sometimes helpful to be able to add additional information, styling, or icons with the options, an option can also be an object of props to pass to the ListItem instead.

When the option is an object, the default behavior will be to:

  • use option.label || option.children as the displayable children
  • use the option.value as the value for this option
  • remove the option.label and option.value keys from the object before passing it as props to the ListItem

The label will be displayed in the option itself as well as in the select button when the option's value matches the select's value. This simplest way to add customization is to transform your list of options to follow this pattern.

However, this might not match all use-cases and customizations required, so the select also has the following props to help with rendering and accessibility:

  • labelKey - A key on the object that should be considered the label
  • valueKey - A key on the object that should be considered the value
  • getOptionLabel - A function that is called for each option to extract a label
  • getOptionValue - A function that is called for each option to extract a value
  • getDisplayLabel - A function that is called for the selected option that should return a renderable ode to display within the Select's button.

You probably won't need all this additional functionality other than the labelKey and valueKey props, but it might be useful for virtualization libraries or other stuff like that.

The examples below will show some use-cases for these props to add some more style to your select fields:

  • using the labelKey and valueKey props converting a list of states that have the format of interface State { name: string; abbreviation: string; } without needing to transform the list yourself
  • rendering custom children within each option and still being search accessible
  • displaying icons/avatars along with the selected option in the Select's button
Using Keys
StateColorado
Custom Children
StateFrozen yogurt (159 kcal)
Icons and Avatars
StateColorado

#Checkbox and Radio Examples

Checkboxes and radios have been implemented to behave exactly like their native counterparts and add a slight animation when the selection state changes. Unlike v1 of react-md, all checkboxes and radios can be fully uncontrolled and will also reset correctly if a form reset button is clicked.

Checkboxes and radios can be created by either using the Checkbox and Radio components or the InputToggle component. The Checkbox and Radio components are just simple wrappers that will provide the correct type attribute and a reasonable default icon to use (a material icon for the checkbox/radio as an outline).

#Indeterminate Checkboxes

The Checkbox component also supports an indeterminate state to help indicate that it controls the checked state for other checkboxes as well. To use this feature:

  • enable the indeterminate prop when all the checkboxes are not checked
  • set the aria-checked="mixed" when at least one checkbox is checked but not all
  • provide a space-delimited string of all the checkboxes it controls as the aria-controls attribute

The aria-controls part is a bit iffy since it might not actually do anything for screen readers and Lighthouse might also flag it as an invalid aria- attribute.

Sandwich Condiments

#Custom Checkboxes

The Checkbox and Radio components use a little css trick with the ::before and ::after pseudo elements to animate the toggled states based on the :checked state. It is does this way so that each checkbox and radio can act like a native toggle input and not be fully controlled to swap out icons.

Unfortunately, this makes it a bit more difficult if you want to use custom icons that don't line up with the existing material icons' checkbox and radio outlines. When this happens, you'll want to use a new prop: disableIconOverlay to disable this behavior and implement your own icon swapping instead by either:

  • handling icon swaps all in CSS
  • make your checkboxes fully controlled
  • make your entire radio group fully controlled

You can also increase or decrease the size of the checkbox and radio components by updating the used CSS Variables for the toggle. Just add a custom class name and use the following mixins:

  • @include rmd-button-theme-update-var(icon-size, NEW_SIZE)
  • @include rmd-icon-theme-update-var(size, NEW_SIZE)
  • @include rmd-form-theme-update-var(icon-size, NEW_SIZE)

#Switch Examples

A switch is another version of the Checkbox component that allows the user to toggle between distinct on and off states. Just like a checkbox, the switch can be toggled with a spacebar press and trigger a form submit when the enter key is pressed.

#Async Switch Example

You can also use the AsyncSwitch component that will update the behavior of the Switch. When the loading prop is enabled, the Switch will gain a circular progress indicator and prevent the switch from being toggled again until the loading prop is set to false . This sort of switch is useful if you are trying to send an API request to update some behavior, but it fails due to some error.

#Simple Help and Error Messages

The form package also exports a FormMessage component to add custom help text, error text, and a counter to a form elements but generally used alongside TextField components. The FormMessage component is mostly an accessibility helper that will ensure that help text and/or error text will be correctly read to screen readers if the contents change.

All that is required for this component is an id and matching the theme prop for the TextField component to get correct styling behavior. The example below will showcase a few simple examples.

Help Text

Error Text

0 / 20

Max 20 characters

0 / 20

#Example Form

This package also exports an extremely simple Form component that just prevents default behavior when it is submitted. This is super nice since the majority of the time you'll want to use ajax on form submit instead of the default behavior. Check out the example below for an extended usage of the Form component and some of the other components together to make a "New Contact" form.

Theme options
Example
Full Address

#With React Hook Form

react-md does not come with any form validation so you'll want to choose your favorite form library instead. This example will show how you can use react-hook-form along with react-md to create a simple form with error states, some validation, and the ability to reset the form.

TitleTitle
Are you a developer?