# Form group

> A vertical cluster for a single control plus its label, help, and error text. Pairs with `<FormControl>` and `<HelpBlock>`.

- Category: form
- Status: stable (since 0.1.0)
- Tokens: --space-3, --space-4
- Playground: https://design.freecodecamp.org/playground#form-group
- npm dependencies: `react@>=18 <20`
- Registry dependencies: [theme](https://design.freecodecamp.org/registry/theme.md)
- Files:
  - `FormGroup.tsx` → `src/ui/form-group/FormGroup.tsx` (raw: https://design.freecodecamp.org/registry/form-group/FormGroup.tsx)
  - `form-group.css` → `src/ui/form-group/form-group.css` (raw: https://design.freecodecamp.org/registry/form-group/form-group.css)

## Install (copy source)

1. Ensure the theme is installed once per project - tokens.css + base.css imported globally, fonts available. See https://design.freecodecamp.org/registry/theme.md and https://design.freecodecamp.org/registry/starter.md.
2. Copy the files below into `src/ui/form-group/` (adjust to your project layout) and import the CSS once from your global stylesheet, e.g. `@import './ui/form-group/form-group.css';`.
3. Colors, spacing and type come from tokens - tailor the component by editing the copied source; recolour by editing tokens.css, not the component CSS.

## Usage

`<FormGroup>` is the spacing wrapper for one form field. It owns the
vertical rhythm between a label, control, and help/error block so
consumers don't fight margins.

## Accessibility

Adds no ARIA on its own - rely on nested `<FormControl>` for
`label ↔ input` wiring, and `<HelpBlock>` for descriptive text
(`aria-describedby`). When grouping multiple related inputs, use
`as="fieldset"` and include a `<legend>` child.

## Example

```tsx
import { FormGroup } from './ui/form-group/FormGroup';
import { Input } from './ui/input/Input';
import { HelpBlock } from './ui/help-block/HelpBlock';

<FormGroup>
  <label htmlFor="username">Username</label>
  <Input id="username" defaultValue="camper-42" />
  <HelpBlock>Letters, numbers, and dashes. Public.</HelpBlock>
</FormGroup>
```

## Props

No component-specific props - accepts standard HTML attributes. See the TypeScript source below.

## Source: FormGroup.tsx

```tsx
import React, { forwardRef } from 'react';

export interface FormGroupProps extends React.HTMLAttributes<HTMLDivElement> {}

export const FormGroup = forwardRef<HTMLDivElement, FormGroupProps>(
  ({ className = '', children, ...rest }, ref) => {
    const classes = ['form-group', className].filter(Boolean).join(' ');
    return (
      <div ref={ref} className={classes} {...rest}>
        {children}
      </div>
    );
  }
);
FormGroup.displayName = 'FormGroup';
```

## Source: form-group.css

```css
.form-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 20px;
}
```

## HTML / vanilla variant

```html
<div class="form-group">
  <label class="form-label" for="username">Username</label>
  <input class="input" id="username" value="camper-42" />
  <p class="form-help">Letters, numbers, and dashes. Public.</p>
</div>
```

Interactive behaviours for plain HTML come from the vanilla runtime (data-uikit-* attributes): https://design.freecodecamp.org/registry/vanilla.md - or download https://design.freecodecamp.org/cdn/uikit.global.js once and self-host it (do not hotlink).

## For coding agents

This library is distributed as copyable source, not an npm package. Start at https://design.freecodecamp.org/registry/starter.md, discover components via https://design.freecodecamp.org/llms.txt, and copy files into the consuming project. Keep token names intact; recolour by editing the copied tokens.css.
