# Tile

> Slug: `tile` · Category: Selection

## When to use

- Selecting one option from a small set where each option needs a tappable card-like surface, but content is simpler than `StyledRadioGroup` (no body, status, action).
- Sizes (`Small / Medium / Large`), color/material variants, capacity choices, simple yes/no card pickers.

## When NOT to use

- Rich content per option (icon + body + price + status) — use `StyledRadioGroup`.
- Plain text radio list — use `RadioGroup`.
- Pill-shaped tag selection — use `Chips`.
- Multi-select grid — use a `Checkbox` list or `Chips variant="toggle"`.

## Variants & decision tree

| `type` | When |
|---|---|
| `'primary'` | Default, larger surface for headline-style choices. |
| `'secondary'` | Smaller, denser tiles for size-style choices. |

`Tile` is a SINGLE radio option; render multiple `Tile`s sharing the same `groupName` to form a group.

## States

Default, hover, focused, pressed, selected (`selected`), inverse.

## Props

| Prop | Type | Default | Description |
|---|---|---|---|
| `id` | `string` | — | Required. Radio input id. |
| `groupName` | `string` | — | Required. Shared `name` for grouping. |
| `type` | `'primary' \| 'secondary'` | — | Required. Visual variant. |
| `content` | `ReactNode` | — | Content rendered inside the label. |
| `selected` | `boolean` | `false` | Whether this tile is the chosen one. |
| `onChange` | `ChangeEventHandler` | — | Fires when this tile is chosen. |
| `inverse` | `boolean` | `false` | Dark-background styling. |
| `disabled` | `boolean` | `false` | Disable. (Inherited from div HTMLAttributes — apply via the inner radio if needed.) |

## Usage examples

```tsx
const [size, setSize] = useState('md');

<div style={{ display: 'flex', gap: 8 }}>
  <Tile
    id="size-sm"
    groupName="size"
    type="secondary"
    selected={size === 'sm'}
    onChange={() => setSize('sm')}
    content={<span>Small</span>}
  />
  <Tile
    id="size-md"
    groupName="size"
    type="secondary"
    selected={size === 'md'}
    onChange={() => setSize('md')}
    content={<span>Medium</span>}
  />
  <Tile
    id="size-lg"
    groupName="size"
    type="secondary"
    selected={size === 'lg'}
    onChange={() => setSize('lg')}
    content={<span>Large</span>}
  />
</div>
```

## Composition

Render Tiles as a flex/grid of options under a heading or `<legend>` so the group's purpose is announced. Combine with `Title` or a section header for context.

## Accessibility

Tile is a real `<input type="radio">` with `<label htmlFor={id}>` — it inherits keyboard semantics (arrow keys cycle within the group, space activates). Always provide visible `content` (text), or wrap the group in a `<fieldset>` with a `<legend>` if the visual context isn't enough.

## Do / Don't

- DO share one `groupName` across all Tiles in a group.
- DO drive `selected` from your component state and update it in `onChange`.
- DON'T mix tile groups with the same `groupName` in different sections.
- DON'T use Tile for rich card content — switch to `StyledRadioGroup`.
