FormControl

FormControl is a wrapper component to enhance layout with input label, help text, counter or validation message.

Import

import { FormControl } from '@contentful/f36-components';
// or
import { FormControl } from '@contentful/f36-forms';

How to use FormControl

  • FormControl provides context to form elements: isRequired, isDisabled, isInvalid, isReadOnly
  • Compound components of FormControl are: Label, HelpText, ValidationMessage, Counter. These components provide additional visual context and hints for users.
  • For more information on how to use FormControl in Form, check the guide for Form.

Design guidelines

To uphold a consistent look and experience for your application, we recommend following the same design layout guidelines for all inputs:

  • Label is a required element that all your inputs should have to pass the a11y requirements. It should be placed on top of the input, so it would be first in your HTML structure.
  • An input component should follow the label
  • HelpText should appear under the input, when you need to display some additional information to the user
  • ValidationMessage should be appearing directly under the input or under HelpText if displayed, to clearly indicate that it is invalid
  • TextInput and Textarea components can have an option of counting characters. In that case, we recommend aligning HelpText and Counter by using the Flex component and placed them right below the input. Have a look on the example over here

Examples

Basic

With invalid input

Select component with FormControl

Radio Group component with FormControl

Checkbox Group component with FormControl

With character count

Props (API reference)

Open in Storybook

FormControl

Name

Type

Default

children
required
ReactNode

as
HTML Tag or React Component (e.g. div, span, etc)

className
string

CSS class to be appended to the root element

id
string

inputValue
string

value from text input and textarea to used for counting characters

isDisabled
false
true

If `true` set the form control to the disabled state.

isInvalid
false
true

If `true` set the form control to the invalid state.

isReadOnly
false
true

If `true` set the form control to the read only state.

isRequired
false
true

If `true` set the form control to be required.

margin
"none"
"spacing2Xs"
"spacingXs"
"spacingS"
"spacingM"
"spacingL"
"spacingXl"
"spacing2Xl"
"spacing3Xl"
"spacing4Xl"

sets margin to one of the corresponding spacing tokens

marginBottom
"none"
"spacing2Xs"
"spacingXs"
"spacingS"
"spacingM"
"spacingL"
"spacingXl"
"spacing2Xl"
"spacing3Xl"
"spacing4Xl"

sets margin-bottom to one of the corresponding spacing tokens

marginLeft
"none"
"spacing2Xs"
"spacingXs"
"spacingS"
"spacingM"
"spacingL"
"spacingXl"
"spacing2Xl"
"spacing3Xl"
"spacing4Xl"

sets margin-left to one of the corresponding spacing tokens

marginRight
"none"
"spacing2Xs"
"spacingXs"
"spacingS"
"spacingM"
"spacingL"
"spacingXl"
"spacing2Xl"
"spacing3Xl"
"spacing4Xl"

sets margin-right to one of the corresponding spacing tokens

marginTop
"none"
"spacing2Xs"
"spacingXs"
"spacingS"
"spacingM"
"spacingL"
"spacingXl"
"spacing2Xl"
"spacing3Xl"
"spacing4Xl"

sets margin-top to one of the corresponding spacing tokens

maxLength
number

Max length of characters used for the text input and textarea

setInputValue
Dispatch<SetStateAction<string>>

Set input value function

setMaxLength
Dispatch<SetStateAction<number>>

Set max length function

testId
string

A [data-test-id] attribute used for testing purposes

Label

Name

Type

Default

children
required
ReactNode

Label value to show

as
HTML Tag or React Component (e.g. div, span, etc)

Defines how the element will be rendered

label
className
string

CSS class to be appended to the root element

isRequired
false
true

Whether or not the associated input element is required

false
margin
"none"
"spacing2Xs"
"spacingXs"
"spacingS"
"spacingM"
"spacingL"
"spacingXl"
"spacing2Xl"
"spacing3Xl"
"spacing4Xl"

sets margin to one of the corresponding spacing tokens

marginBottom
"none"
"spacing2Xs"
"spacingXs"
"spacingS"
"spacingM"
"spacingL"
"spacingXl"
"spacing2Xl"
"spacing3Xl"
"spacing4Xl"

sets margin-bottom to one of the corresponding spacing tokens

marginLeft
"none"
"spacing2Xs"
"spacingXs"
"spacingS"
"spacingM"
"spacingL"
"spacingXl"
"spacing2Xl"
"spacing3Xl"
"spacing4Xl"

sets margin-left to one of the corresponding spacing tokens

marginRight
"none"
"spacing2Xs"
"spacingXs"
"spacingS"
"spacingM"
"spacingL"
"spacingXl"
"spacing2Xl"
"spacing3Xl"
"spacing4Xl"

sets margin-right to one of the corresponding spacing tokens

marginTop
"none"
"spacing2Xs"
"spacingXs"
"spacingS"
"spacingM"
"spacingL"
"spacingXl"
"spacing2Xl"
"spacing3Xl"
"spacing4Xl"

sets margin-top to one of the corresponding spacing tokens

requiredText
string

Custom text to show in parentheses that gets rendered if the associated input is required

"required"
testId
string

A [data-test-id] attribute used for testing purposes

HelpText

Name

Type

Default

children
required
ReactNode

className
string

CSS class to be appended to the root element

css
string
number
false
true
ComponentSelector
Keyframes
SerializedStyles
ArrayInterpolation<undefined>
ObjectInterpolation<undefined>
(theme: any) => Interpolation<undefined>

margin
"none"
"spacing2Xs"
"spacingXs"
"spacingS"
"spacingM"
"spacingL"
"spacingXl"
"spacing2Xl"
"spacing3Xl"
"spacing4Xl"

sets margin to one of the corresponding spacing tokens

marginBottom
"none"
"spacing2Xs"
"spacingXs"
"spacingS"
"spacingM"
"spacingL"
"spacingXl"
"spacing2Xl"
"spacing3Xl"
"spacing4Xl"

sets margin-bottom to one of the corresponding spacing tokens

marginLeft
"none"
"spacing2Xs"
"spacingXs"
"spacingS"
"spacingM"
"spacingL"
"spacingXl"
"spacing2Xl"
"spacing3Xl"
"spacing4Xl"

sets margin-left to one of the corresponding spacing tokens

marginRight
"none"
"spacing2Xs"
"spacingXs"
"spacingS"
"spacingM"
"spacingL"
"spacingXl"
"spacing2Xl"
"spacing3Xl"
"spacing4Xl"

sets margin-right to one of the corresponding spacing tokens

marginTop
"none"
"spacing2Xs"
"spacingXs"
"spacingS"
"spacingM"
"spacingL"
"spacingXl"
"spacing2Xl"
"spacing3Xl"
"spacing4Xl"

sets margin-top to one of the corresponding spacing tokens

testId
string

A [data-test-id] attribute used for testing purposes

cf-ui-help-text

ValidationMessage

Name

Type

Default

children
required
ReactNode

className
string

CSS class to be appended to the root element

css
string
number
false
true
ComponentSelector
Keyframes
SerializedStyles
ArrayInterpolation<undefined>
ObjectInterpolation<undefined>
(theme: any) => Interpolation<undefined>

margin
"none"
"spacing2Xs"
"spacingXs"
"spacingS"
"spacingM"
"spacingL"
"spacingXl"
"spacing2Xl"
"spacing3Xl"
"spacing4Xl"

sets margin to one of the corresponding spacing tokens

marginBottom
"none"
"spacing2Xs"
"spacingXs"
"spacingS"
"spacingM"
"spacingL"
"spacingXl"
"spacing2Xl"
"spacing3Xl"
"spacing4Xl"

sets margin-bottom to one of the corresponding spacing tokens

marginLeft
"none"
"spacing2Xs"
"spacingXs"
"spacingS"
"spacingM"
"spacingL"
"spacingXl"
"spacing2Xl"
"spacing3Xl"
"spacing4Xl"

sets margin-left to one of the corresponding spacing tokens

marginRight
"none"
"spacing2Xs"
"spacingXs"
"spacingS"
"spacingM"
"spacingL"
"spacingXl"
"spacing2Xl"
"spacing3Xl"
"spacing4Xl"

sets margin-right to one of the corresponding spacing tokens

marginTop
"none"
"spacing2Xs"
"spacingXs"
"spacingS"
"spacingM"
"spacingL"
"spacingXl"
"spacing2Xl"
"spacing3Xl"
"spacing4Xl"

sets margin-top to one of the corresponding spacing tokens

testId
string

A [data-test-id] attribute used for testing purposes

cf-ui-validation-message

Density support

This component supports multiple densities thanks to the useDensity hook and automatically adjusts its styling for each density (when wrapped with the DensityProvider).