# Form group

Wraps a form control with its label, hint text and error message.

## Preview

```html title="Form group with hint text"
<div class="govbb-form-group">
  <label class="govbb-label" for="nis-number">NIS number</label>
  <span class="govbb-hint" id="nis-number-description">
    Your National Insurance number, for example 123456
  </span>
  <input
    class="govbb-input"
    id="nis-number"
    name="nis-number"
    type="text"
    aria-describedby="nis-number-description"
  />
</div>
```

```tsx
import { FormGroup, Hint, Input, Label } from '@govtech-bb/react';

<FormGroup>
  <Label htmlFor="nis-number">NIS number</Label>
  <Hint id="nis-number-description">
    Your National Insurance number, for example 123456
  </Hint>
  <Input
    id="nis-number"
    name="nis-number"
    aria-describedby="nis-number-description"
  />
</FormGroup>;
```

The Form group is the shared scaffolding around every form control: a wrapper
(`.govbb-form-group`) that stacks the label (`.govbb-label`), optional hint
text (`.govbb-hint`), optional error message (`.govbb-error-message`) and the
control itself with consistent spacing. It holds no state: compose the pieces
you need.

For rules shared by every kind of control, including labels, hint text, width,
states and validation, see the [Form fields foundation](/styles/form-fields/).

## Usage

<div class="govbb-usage-guidance">
  <section class="govbb-usage-guidance__item" aria-labelledby="form-when-to-use">
    <h3 id="form-when-to-use">
      <span class="govbb-usage-guidance__icon govbb-usage-guidance__icon--do" aria-hidden="true">✓</span>
      When to use
    </h3>
    <ul>
      <li>Use a form group to keep one control with its label, hint and error message.</li>
      <li>Use a fieldset and legend when several controls answer one question.</li>
    </ul>
  </section>
  <section class="govbb-usage-guidance__item" aria-labelledby="form-when-not-to-use">
    <h3 id="form-when-not-to-use">
      <span class="govbb-usage-guidance__icon govbb-usage-guidance__icon--dont" aria-hidden="true">×</span>
      When not to use
    </h3>
    <ul>
      <li>Do not use a form group as a general page layout wrapper.</li>
      <li>Do not put essential instructions in placeholder text or inside a label.</li>
    </ul>
  </section>
</div>

## Best practices

### Keep supporting text in a predictable order

Show the label first, then either hint text or an error message, followed by the
control. When invalid, the error replaces the hint and `aria-describedby`
points at the error.

### Ask only what the service needs

Prefer one clear question per page for complex services. Mark optional fields
explicitly rather than relying on an unexplained asterisk, and preserve user
answers when validation fails.

## Error messages

When a field fails validation, add an error message between the label (or
hint) and the control. Give it `role="alert"` so it is announced, mark the
control with `aria-invalid="true"`, and point `aria-describedby` at the error
message id. Keep messages specific and actionable, such as "Enter your NIS
number".

```html title="Form group with error message"
<div class="govbb-form-group">
  <label class="govbb-label" for="licence-number">Licence number</label>
  <span class="govbb-error-message" id="licence-number-error" role="alert">
    Enter your driver's licence number
  </span>
  <input
    class="govbb-input"
    id="licence-number"
    name="licence-number"
    type="text"
    aria-invalid="true"
    aria-describedby="licence-number-error"
  />
</div>
```

```tsx
import { ErrorMessage, FormGroup, Input, Label } from '@govtech-bb/react';

<FormGroup>
  <Label htmlFor="licence-number">Licence number</Label>
  <ErrorMessage id="licence-number-error" role="alert">
    Enter your driver's licence number
  </ErrorMessage>
  <Input
    id="licence-number"
    name="licence-number"
    aria-invalid
    aria-describedby="licence-number-error"
  />
</FormGroup>;
```

## Grouping related fields with a fieldset

When several controls answer a single question (radios, checkboxes, or the
parts of a date), wrap them in a fieldset (`.govbb-fieldset`) with a legend
(`.govbb-fieldset__legend`) inside the form group. The React `Fieldset`
component supplies the form-group wrapper. The legend acts as the question;
each control keeps its own label.

```html title="Fieldset with legend and hint"
<div class="govbb-form-group">
  <fieldset class="govbb-fieldset" aria-describedby="collection-description">
    <legend class="govbb-fieldset__legend">
      Where do you want to collect your passport?
    </legend>
    <span class="govbb-hint" id="collection-description">
      Choose the office closest to you
    </span>
    <div class="govbb-radio-item">
      <input
        class="govbb-radio"
        id="collect-bridgetown"
        type="radio"
        name="collection"
      />
      <label class="govbb-radio-item__label" for="collect-bridgetown">
        Bridgetown
      </label>
    </div>
    <div class="govbb-radio-item">
      <input
        class="govbb-radio"
        id="collect-holetown"
        type="radio"
        name="collection"
      />
      <label class="govbb-radio-item__label" for="collect-holetown">
        Holetown
      </label>
    </div>
  </fieldset>
</div>
```

```tsx
import { Fieldset, Hint, Radio } from '@govtech-bb/react';

<Fieldset
  legend="Where do you want to collect your passport?"
  aria-describedby="collection-description"
>
  <Hint id="collection-description">Choose the office closest to you</Hint>
  <Radio id="collect-bridgetown" name="collection" label="Bridgetown" />
  <Radio id="collect-holetown" name="collection" label="Holetown" />
</Fieldset>;
```
