Field

The field component exposes the elements around form inputs, and an API to compose them.

Quick Start

Installation
npm install @adaptavant/eds-core
Import
import { Field } from '@adaptavant/eds-core';

Label

Each field must be accompanied by a label. Effective form labelling helps users understand what information to enter into an input.

Using placeholder text in lieu of a label is sometimes employed as a space-saving method. However, this is not recommended because it hides context and presents accessibility issues.

<Field label="First name">
  <TextInput />
</Field>

Label visibility

The label must always be provided for assistive technology, but you may hide it from sighted users when the intent can be inferred from context.

<Field label="First name" labelVisibility="hidden">
  <TextInput />
</Field>

Secondary label

Provide additional context, typically used to indicate that the field is optional.

<Field label="First name" secondaryLabel="(Optional)">
  <TextInput />
</Field>

Size

Customize the size of the field using size prop.

Use standard in applications where space is a premium.

Use large in customer-facing experiences, such as the booking page, where accessibility is a priority.

{/* standard */}
<Field label="First name" size="standard">
  <TextInput />
</Field>

{/* large */}
<Field label="First name" size="large">
  <TextInput />
</Field>

Description

Provides relevant information that assists the user in completing a field. Description text is always visible and appears underneath the label. Use sentence-style capitalisation, and in most cases, write the text as full sentences with punctuation.

We take your privacy seriously. We will never give your email to a third party.
<Field
  label="Email"
  description="We take your privacy seriously. We will never give your email to a third party."
>
  <TextInput type="email" />
</Field>

Error messages

The errorMessage prop is used to provide users with more context as to why the field is invalid. This will be announced on focus.

The errorMessage prop is  ⚠️ deprecated and will be removed in a future release, please check the FieldMessage section to add error state.

<Field
  label="Email"
  secondaryLabel="(Optional)"
  errorMessage="Enter an email address in the correct format, like name@example.com"
>
  <TextInput type="email" />
</Field>

Status

Use the status prop to indicate whether a field is in an error or warning state.

<Stack className="gap-4">
  <Field
    label="Email"
    secondaryLabel="(Optional)"
    status="error"
  >
    <TextInput type="email" />
  </Field>
  <Field
    label="Email"
    secondaryLabel="(Optional)"
    status="warning"
  >
    <TextInput type="email" />
  </Field>
</Stack>

Field Message

Use the status and fieldMessage props to convey why the field is in an error or warning state. The message is announced on focus for screen readers.

<Stack className="gap-4">
  <Field
    label="Email"
    secondaryLabel="(Optional)"
    fieldMessage="Enter an email address in the correct format, like name@example.com"
    status="error"
  >
    <TextInput type="email" />
  </Field>
  <Field
    label="Email"
    secondaryLabel="(Optional)"
    fieldMessage="Enter an email address in the correct format, like name@example.com"
    status="warning"
  >
    <TextInput type="email" />
  </Field>
</Stack>

Counter

Use the counter prop to display a character count indicator beneath any input component (e.g., TextInput, Textarea). The counter accepts value, maxValue, and isAlwaysVisible parameters.

The counter shows the difference between the current value and maxValue, along with a circular progress indicator. When the value exceeds maxValue, it displays a negative number.

By default, the counter appears when input reaches 50% of maxValue. Use isAlwaysVisible: true to show it at all times.

40
const [textInputValue, setTextInputValue] = React.useState('');
const [textareaValue, setTextareaValue] = React.useState('');
const maxLength = 40;

return (
<Box className="flex flex-col gap-4 w-[300px]">
  {/* Counter with TextInput - appears at 50% threshold */}
  <Field label="Characters counter demo" counter={{ value: textInputValue.length, maxValue: maxLength }}
    errorMessage={textInputValue.length> maxLength ? 'Max length exceeded' : undefined}
    >
    <TextInput placeholder="Enter 20 characters or more to view counter" defaultValue={textInputValue} onChange={(e)=>
      setTextInputValue(e.target.value)}
      />
  </Field>

  {/* Counter with Textarea - always visible */}
  <Field label="Characters counter demo" counter={{ value: textareaValue.length, maxValue: maxLength, isAlwaysVisible:
    true }} errorMessage={textareaValue.length> maxLength ? 'Max length exceeded' : undefined}
    >
    <Textarea placeholder="Enter text" defaultValue={textareaValue} onChange={(e)=> setTextareaValue(e.target.value)}
      />
    </Field>
  </Box>
)

Disabled

Use the isDisabled prop to show that a Field isn't usable.

{/* isDisabled */}
<Field
  label="First name"
  isDisabled
>
  <TextInput />
</Field>

Required

Use the isRequired prop if user input is required on the field before form submission.

{/* isRequired */}
<Field
  label="First name"
  isRequired
>
  <TextInput />
</Field>

API Reference

Field

PropsTypeDescriptionDefault
childrenReact.ReactNodeInput component like TextInput, Textarea.
description?React.ReactNodeProvide additional information that will aid user input._
errorMessage?React.ReactNodeMessage to show when the field is invalid._
status?error | warningUse the status prop to indicate whether a field is in an error or warning state._
fieldMessage?stringUse the status and fieldMessage props to convey why the field is in an error or warning state. The message is announced on focus for screen readers.
controlId?stringSpecifies the unique identifier for the form control within the component. This ID is used to associate the input, textarea, select, button etc with its label or other descriptive elements._
isDisabled?booleanWhether the field is disabled.false
isRequired?booleanWhether user input is required on the field before form submission.false
labelReact.ReactNodeLabel for the field._
labelVisibility?'hidden' | 'visible'A label must always be provided for assistive technology, but you may hide it from sighted users when the intent can be inferred from context.'visible'
secondaryLabel?React.ReactNodeAdditional context, typically used to indicate that the field is optional._
size?'standard' | 'large'The size of the field.'standard'
counter?CounterObjPropsCounter object containing maxValue, value and isAlwaysVisible._
counter.maxValue?numberMaximum value the counter can reach._
counter.value?numberCurrent value of the counter._
counter.isAlwaysVisible?booleanWhether the counter is always visible.false

Style API

Our design system components include style props that allow you to easily customize different parts of each component to match your design needs.

Please refer to the Style API documentation for more insights.

Field parts

Enter your username
90
{/* Styling the Label and Description parts */}
<Field
  label="Username"
  description="Enter your username"
  secondaryLabel="(Optional)"
  className="p-4 border border-positive"
  classNames={{
    label: 'text-positive font-stronger',
    description: 'text-positive-secondary',
    secondaryLabel: 'text-link'
  }}
>
  <TextInput />
</Field>

{/* Styling the Error state parts */}
<Field
  label="Email"
  errorMessage="Invalid email format"
  classNames={{
    errorTrack: 'mt-3',
    errorIcon: 'fill-caution',
    errorMessage: 'text-caution'
  }}
>
  <TextInput />
</Field>

{/* Styling the counter */}
<Field
  label="Message"
  counter={{ value: 10, maxValue: 100, isAlwaysVisible: true }}
  classNames={{
    counter: 'text-caution-secondary'
  }}
>
  <Textarea />
</Field>
Stylable PartsDescription
rootThe container that wraps the entire field component, including the label, input, description, and error states.
labelThe main label element that identifies the field's purpose.
secondaryLabelA supplementary label element that can be used to display additional information next to the main label.
descriptionThe helper text element below the input that provides additional guidance or context to the user.
errorTrackThe container element that holds both the error icon and error message when validation fails.
errorIconThe visual indicator (icon) that appears when the field is in an error state.
errorMessageThe text element that displays validation error messages or feedback when the field is invalid.
counterThe text element that displays the character count and limit information (e.g., "10/100").