import { TextInputArea } from '@uhg-abyss/web/ui/TextInputArea';() => { const [value, setValue] = useState('State Default Value');
return ( <TextInputArea label="TextInputArea Sandbox" value={value} onChange={(e) => setValue(e.target.value)} /> );};useForm (recommended)
Using useForm and FormProvider simplifies form management by providing out-of-the-box validation, form state handling, and performance optimizations, leveraging the power of react-hook-form.
useState
Using the useState hook gets values from the component state.
Label
Use the label prop to display a label above the input. To hide the input label, set hideLabel to true.
Use isRequired and isOptional for further customization.
Note: If using useForm, do not use isRequired. The same functionality can be achieved with required: true in validators.
Helper
Use the helper prop to display a help icon next to the label. Simply passing a string value will render the default helper, a Tooltip containing that string. The helper can be customized by passing in a node. It is recommended to use either a Tooltip or a Popover. See When should I use a Tooltip vs. a Popover? for more information on best practices regarding the two.
Subtext
Use the subText prop to display helpful information related to the input field. The prop accepts either a string or an object of the form:
{ text: string; position: 'above' | 'below';}The position property determines where the subtext will be displayed in relation to the input field. The default value is 'below'.
Disabled
Set the isDisabled prop to true to disable the input field so users cannot enter a value.
Validation
Validators (useForm)
Use the validators prop to set validation rules for the field when using useForm. See the examples below for implementation on various types of validation.
Note: The default error message when required is true is minimally acceptable for accessibility. It is highly recommended to customize it to be more specific to the use of the field and form.
Error message (useState)
Use the errorMessage prop to display a custom error message below the input field when using useState.
Success message
Use the successMessage prop to display a custom success message below the input field. To provide a single success message across all form input components using useForm/FormProvider, you can provide successMessage to FormProvider as shown here.
Highlighted
Use the highlighted prop to enable a distinct background color when fields are required. To supply this across all form input components using useForm/FormProvider, you can provide highlighted to FormProvider as shown here.
Max length
Use the maxLength prop to limit the number of characters allowed in the input field. The default is 500.
Max length threshold messages
To minimize excessive and unwanted screen reader announcements about characters remaining, an alternate configurable approach is available using the alertThresholds prop (for more details see accessibility tab). Use alertThresholds to specify an array of percentage thresholds (as decimals) at which to announce the percentage of characters used to screen readers. For example, passing [0.25, 0.5, 0.75] will announce when 25%, 50%, and 75% of the max length has been used.
Note: If not defined, by default the only announcements are at
- "10 characters remaining"
- "### characters maximum limit reached"
Preserve whitespace
To preserve leading or trailing whitespace in your inputs, set prop preserveWhitespace to true.
TextInputArea Props
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
alertThresholds | number[] | - | - | List of decimal thresholds for character count alerts when maxLength is used (ex: [.75] for an alert of 75% of characters used). |
className | string | - | - | CSS class name to apply to each element within the component |
clearButtonRef | React.RefObject<HTMLButtonElement> | - | - | Use to pass a ref to the clear input button |
css | Abyss.CSSProperties | Partial<Record<`abyss-${T}`, Abyss.CSSProperties>> | - | - | Object containing CSS styling to apply; uses the classes listed in the "Integration" tab of the component's documentation |
data-testid | string | - | - | Suffix used to create a unique ID used for automated testing |
disableDefaultProviderProps | boolean | false | - | If set to true, the component will not use the DefaultPropsProvider values. If you aren’t using the DefaultPropsProvider, this prop can be ignored. |
errorMessage | string | never | - | - | Error message to display for the input. Only used when not in a FormProvider. errorMessage should not exist in useForm mode. |
helper | React.ReactNode | - | - | Helper element next to label |
hideLabel | boolean | false | - | If true, the label will be visually hidden |
highlighted | boolean | false | - | If true, the input field will be highlighted |
isClearable | boolean | - | - | If true, the input will display a clear button |
isDisabled | boolean | false | - | If true, the input will be disabled |
isOptional | boolean | false | - | If true, the label will be appended with "(Optional)" |
isReadOnly | boolean | false | - | If true, the input will be read-only |
isRequired | boolean | never | - | - | Whether the input is required. Only used when not in a FormProvider. isRequired should not exist in useForm mode. |
label | string | - | The label for the input | |
model | never | string | - | - | model should not exist in useState mode. Model name for form validation. Only used when in a FormProvider. |
onBlur | React.FocusEventHandler<HTMLInputElement> | - | - | Callback function executed when the input is blurred |
onChange | React.ChangeEventHandler<HTMLInputElement> | - | - | Callback function executed when the input value changes |
onClear | () => void | - | - | Callback function executed when the input is cleared |
onFocus | React.FocusEventHandler<HTMLInputElement> | - | - | Callback function executed when the input is focused |
preserveWhitespace | boolean | false | - | Whether to preserve leading and trailing whitespace |
subText | string | { text: string; position: SubTextPosition; } | - | - | Additional descriptive text for the input |
successMessage | string | - | - | Success message to display for the input |
validators | never | RegisterOptions | - | - | validators should not exist in useState mode. Validators for the input. Only used when in a FormProvider. |
value | ValueType | never | - | - | The value of the input. Only used when not in a FormProvider. value should not exist in useForm mode. |
Below are the link(s) to the relevant GitHub type files:
Abyss.d.tsTextInputArea Classes
| Class Name | Description |
|---|---|
| .abyss-text-input-area-root | TextInputArea root container |
| .abyss-text-input-area-container-wrapper | TextInputArea container wrapper |
| .abyss-text-input-area-label | TextInputArea label |
| .abyss-text-input-area | TextInputArea input field |
| .abyss-text-input-area-sub-text | TextInputArea subtext |
| .abyss-text-input-area-clear | TextInputArea clear button |
| .abyss-text-input-area-character-count | TextInputArea character count |
| .abyss-text-input-area-descriptors | TextInputArea descriptors |
"Characters remaining not announced" - screen reader implementation details
Unlike most fields in Abyss, the visible "character remaining" is not automatically announced as part of TextInputArea receiving focus. If it was, (using aria-describedby) it would be triggered on every keystroke entering data in many BrATs (such as JAWS & Chrome, NVDA & Firefox).
To provide a more appropriate and configurable screen reader experiences use the max length threshold messages feature covered on the overview tab.
Known BrAT issues
- JAWS (prior to 2024)
- ARIA settings, including aria-describedby, aria-required, and aria-invalid, are not announced on textarea
Component Tokens
Note: Click on the token row to copy the token to your clipboard.
TextInputArea Tokens
| Token Name | Value | |
|---|---|---|
| text-input-area.color.text.character-count | #4B4D4F | |
| text-input-area.spacing.padding.vertical.clear-button | 4px | |
| text-input-area.spacing.padding.vertical.field | 12px | |
| text-input-area.spacing.gap.horizontal.character-count | 16px |
Header Tokens
| Token Name | Value | |
|---|---|---|
| input-header.color.text.label | #4B4D4F | |
| input-header.color.text.hint | #4B4D4F | |
| input-header.color.icon.info.rest | #196ECF | |
| input-header.color.icon.info.hover | #004BA0 | |
| input-header.color.icon.info.active | #002677 | |
| input-header.sizing.all.icon | 24px | |
| input-header.spacing.gap.horizontal.container | 4px | |
| input-header.spacing.gap.horizontal.label | 4px | |
| input-header.spacing.gap.vertical.content | 4px | |
| input-header.spacing.padding.top.content | 2px |
Validation Tokens
| Token Name | Value | |
|---|---|---|
| input-validation.color.surface.container | #FFFFFF | |
| input-validation.color.text.error | #990000 | |
| input-validation.color.text.success | #007000 | |
| input-validation.color.icon.error | #990000 | |
| input-validation.color.icon.success | #007000 | |
| input-validation.sizing.all.icon | 20px | |
| input-validation.spacing.gap.horizontal.container | 4px |
Input Tokens
| Token Name | Value | |
|---|---|---|
| input.color.surface.field.default | #FFFFFF | |
| input.color.surface.field.highlighted | #E5F8FB | |
| input.color.surface.field.disabled | #F3F3F3 | |
| input.color.border.field.rest | #4B4D4F | |
| input.color.border.field.hover.default | #196ECF | |
| input.color.border.field.hover.error | #990000 | |
| input.color.border.field.hover.success | #007000 | |
| input.color.border.field.active.default | #004BA0 | |
| input.color.border.field.active.error | #990000 | |
| input.color.border.field.active.success | #007000 | |
| input.color.text.input | #4B4D4F | |
| input.color.text.hint | #4B4D4F | |
| input.color.text.required | #990000 | |
| input.color.icon.utility.rest | #4B4D4F | |
| input.color.icon.utility.hover | #323334 | |
| input.color.icon.utility.active | #000000 | |
| input.color.icon.content | #323334 | |
| input.border-radius.all.field | 4px | |
| input.border-width.all.field.default | 1px | |
| input.border-width.all.field.active | 3px | |
| input.sizing.all.icon | 20px | |
| input.spacing.gap.vertical.container | 8px | |
| input.spacing.gap.horizontal.field | 12px | |
| input.spacing.gap.horizontal.input-indicator | 2px | |
| input.spacing.gap.horizontal.prefix-input | 2px | |
| input.spacing.gap.horizontal.suffix-clear | 2px | |
| input.spacing.padding.all.focus-container | 2px | |
| input.spacing.padding.horizontal.field | 12px | |
| input.spacing.padding.left.field | 12px | |
| input.spacing.padding.right.focus-field | 44px |