Agriculture Design System
Beta
Design System for the Export Service

Grouped fields

The Grouped fields component allows two closely related form inputs to be grouped together.

View in FigmaView in StorybookView in Github
import { ... } from '@ag.ds-next/react/grouped-fields';
Open in Playroom, opens in a new tab
<GroupedFields legend="Item weight">
	{({ field1Props, field2Props }) => (
		<>
			<TextInput label="Weight" {...field1Props} />
			<Select
				label="Unit"
				options={[
					{ value: 'mg', label: 'mg' },
					{ value: 'g', label: 'g' },
					{ value: 'kg', label: 'kg' },
					{ value: 't', label: 't' },
					{ value: 'Mt', label: 'Mt' },
				]}
				hideOptionalLabel
				maxWidth="sm"
				{...field2Props}
			/>
		</>
	)}
</GroupedFields>

Grouped fields allows two related form inputs to be composed together while providing the ability to present and describe this relationship and any invalid input errors.

It uses the render props pattern to spread a series of necessary attributes to the children form inputs.

Do

  • group two related inputs, such as weight and unit, and date and time
  • always provide a meaningful legend, regardless if it is visible or visually hidden
  • use the group’s optional label instead of the inputs’ labels when both fields are optional.
  • provide hint text for instruction

Don’t

  • group unrelated inputs to save space or reduce the length of a form

Hide optional label

When both inputs are required or one input is optional and the other has no empty state, hide the group’s optional label with the hideOptionalLabel prop.

<FormStack>
	<GroupedFields legend="Item weight" hideOptionalLabel>
		{({ field1Props, field2Props }) => (
			<>
				<TextInput label="Weight" {...field1Props} required />
				<Select
					label="Unit"
					options={[
						{ value: 'mg', label: 'mg' },
						{ value: 'g', label: 'g' },
						{ value: 'kg', label: 'kg' },
						{ value: 't', label: 't' },
						{ value: 'Mt', label: 'Mt' },
					]}
					maxWidth="sm"
					placeholder="Choose"
					required
					{...field2Props}
				/>
			</>
		)}
	</GroupedFields>

	<GroupedFields legend="Item weight" hideOptionalLabel>
		{({ field1Props, field2Props }) => (
			<>
				<TextInput label="Weight" {...field1Props} />
				<Select
					label="Unit"
					options={[
						{ value: 'mg', label: 'mg' },
						{ value: 'g', label: 'g' },
						{ value: 'kg', label: 'kg' },
						{ value: 't', label: 't' },
						{ value: 'Mt', label: 'Mt' },
					]}
					maxWidth="sm"
					hideOptionalLabel
					{...field2Props}
				/>
			</>
		)}
	</GroupedFields>
</FormStack>

Visually hide legend

When a group’s relationship is clear to the average sighted user, you can choose to visually hide the legend to reduce cognitive load with the visuallyHideLegend prop.

When both fields are required, remember to also use hideOptionalLabel so screen reader users are not informed that required fields are optional.

<GroupedFields legend="Item weight" hideOptionalLabel visuallyHideLegend>
	{({ field1Props, field2Props }) => (
		<>
			<TextInput label="Weight" {...field1Props} required />
			<Select
				label="Unit"
				options={[
					{ value: 'mg', label: 'mg' },
					{ value: 'g', label: 'g' },
					{ value: 'kg', label: 'kg' },
					{ value: 't', label: 't' },
					{ value: 'Mt', label: 'Mt' },
				]}
				maxWidth="sm"
				placeholder="Choose"
				required
				{...field2Props}
			/>
		</>
	)}
</GroupedFields>

Hint

Use the hint prop to provide help that’s relevant to the majority of users, like how their information will be used, or where to find it.

Don’t use long paragraphs and lists in hint text. Screen readers read out the entire text when users interact with the form element. This could frustrate users if the text is long.

Don’t include links within hint text. While screen readers will read out the link text when describing the field, they will not tell users that the text is a link.

<GroupedFields legend="Item weight" hint="Example hint text">
	{({ field1Props, field2Props }) => (
		<>
			<TextInput label="Weight" {...field1Props} required />
			<Select
				label="Unit"
				options={[
					{ value: 'mg', label: 'mg' },
					{ value: 'g', label: 'g' },
					{ value: 'kg', label: 'kg' },
					{ value: 't', label: 't' },
					{ value: 'Mt', label: 'Mt' },
				]}
				maxWidth="sm"
				placeholder="Choose"
				{...field2Props}
			/>
		</>
	)}
</GroupedFields>

Invalid

Use the field1Invalid, field2Invalid and message props to indicate if the user input is invalid.

The message should be helpful but generic enough to apply and make sense to both inputs.

<FormStack>
	<GroupedFields
		legend="Item weight"
		hideOptionalLabel
		message="Enter a valid item weight"
		field1Invalid
	>
		{({ field1Props, field2Props }) => (
			<>
				<TextInput label="Weight" {...field1Props} required />
				<Select
					label="Unit"
					options={[
						{ value: 'mg', label: 'mg' },
						{ value: 'g', label: 'g' },
						{ value: 'kg', label: 'kg' },
						{ value: 't', label: 't' },
						{ value: 'Mt', label: 'Mt' },
					]}
					maxWidth="sm"
					placeholder="Choose"
					required
					value="kg"
					{...field2Props}
				/>
			</>
		)}
	</GroupedFields>

	<GroupedFields
		legend="Item weight"
		hideOptionalLabel
		message="Enter a valid item weight"
		field2Invalid
	>
		{({ field1Props, field2Props }) => (
			<>
				<TextInput label="Weight" {...field1Props} required value="10" />
				<Select
					label="Unit"
					options={[
						{ value: 'mg', label: 'mg' },
						{ value: 'g', label: 'g' },
						{ value: 'kg', label: 'kg' },
						{ value: 't', label: 't' },
						{ value: 'Mt', label: 'Mt' },
					]}
					maxWidth="sm"
					placeholder="Choose"
					required
					{...field2Props}
				/>
			</>
		)}
	</GroupedFields>

	<GroupedFields
		legend="Item weight"
		hideOptionalLabel
		message="Enter a valid item weight"
		field1Invalid
		field2Invalid
	>
		{({ field1Props, field2Props }) => (
			<>
				<TextInput label="Weight" {...field1Props} required />
				<Select
					label="Unit"
					options={[
						{ value: 'mg', label: 'mg' },
						{ value: 'g', label: 'g' },
						{ value: 'kg', label: 'kg' },
						{ value: 't', label: 't' },
						{ value: 'Mt', label: 'Mt' },
					]}
					maxWidth="sm"
					placeholder="Choose"
					required
					{...field2Props}
				/>
			</>
		)}
	</GroupedFields>
</FormStack>
  • Autocomplete Autocomplete, also known as type-ahead, uses predictive text to help select options as a user types.
  • Combobox This component allows users to select from a list of options. It’s especially useful when there are many options to choose from.
  • Date picker The Date picker component allows users to select a single date via a calendar or text input.
  • Password input The password input component allows users to securely enter a password. The text is obscured by default, but can be revealed by pressing the ‘Show password’ checkbox.
  • Search input Search input enables users to enter a word or phrase to find relevant content.
  • Select Select provides a way for users to choose one item from a collapsible list. It helps reduce input errors and screen space.
  • Text input This component allows users to enter free-form text.
  • Textarea A text area lets users enter long-form, plain text over multiple lines and is commonly found in forms.