# Choice tiles

Enable users to select a single value from a list of choices that support more complex content than regular radio buttons.

Tabs: [Guidelines](/components/web/choice-tiles/choice-tiles.guidelines.md) · [Code](/components/web/choice-tiles/choice-tiles.code.md)

## Basic usage

Import `ChoiceTiles` and compose each choice from a `ChoiceTiles.Choice`, with a `ChoiceTiles.Title` and a `ChoiceTiles.Description`. Give the group an `aria-label`.

```tsx
import {ChoiceTiles} from '@pleo-io/telescope'

const AccessLevel = () => (
    <ChoiceTiles aria-label="Access level" defaultValue="essential">
        <ChoiceTiles.Choice value="essential" id="essential">
            <ChoiceTiles.Title>Essential</ChoiceTiles.Title>
            <ChoiceTiles.Description>Basic rights to perform bookkeeping</ChoiceTiles.Description>
        </ChoiceTiles.Choice>
        <ChoiceTiles.Choice value="extended" id="extended">
            <ChoiceTiles.Title>Extended</ChoiceTiles.Title>
            <ChoiceTiles.Description>
                All essential rights plus administrator rights
            </ChoiceTiles.Description>
        </ChoiceTiles.Choice>
    </ChoiceTiles>
)
```

Use `value` and `onValueChange` for a controlled group, or `defaultValue` for an uncontrolled one.

## Tag

Pass a `ChoiceTiles.Tag` inside `ChoiceTiles.Title` to highlight a choice, for example as recommended.

```tsx
<ChoiceTiles.Title>
    Extended<ChoiceTiles.Tag variant="green">Recommended</ChoiceTiles.Tag>
</ChoiceTiles.Title>
```

## Expanded content

Pass `expandedContent` to a `ChoiceTiles.Choice` to show more details below it.

```tsx
<ChoiceTiles.Choice
    value="essential"
    id="essential"
    expandedContent={<Text variant="body-s">Extra content for this choice</Text>}
>
    <ChoiceTiles.Title>Essential</ChoiceTiles.Title>
    <ChoiceTiles.Description>Basic rights to perform bookkeeping</ChoiceTiles.Description>
</ChoiceTiles.Choice>
```

## Horizontal orientation

Pass `orientation="horizontal"` to lay the choices out in a row. Use `ChoiceTiles.Separator`, `ChoiceTiles.List` and `ChoiceTiles.ListItem` to add a list of features to each choice.

```tsx
<ChoiceTiles aria-label="Access level" defaultValue="essential" orientation="horizontal">
    <ChoiceTiles.Choice value="essential" id="essential">
        <ChoiceTiles.Title>Essential actions</ChoiceTiles.Title>
        <ChoiceTiles.Description>Basic rights to perform bookkeeping</ChoiceTiles.Description>
        <ChoiceTiles.Separator />
        <ChoiceTiles.List>
            <ChoiceTiles.ListItem>
                <Check size={16} />
                <Text>See and edit expenses</Text>
            </ChoiceTiles.ListItem>
            <ChoiceTiles.ListItem>
                <Close size={16} />
                <Text>Individual spending limits</Text>
            </ChoiceTiles.ListItem>
        </ChoiceTiles.List>
    </ChoiceTiles.Choice>
    {/* more choices */}
</ChoiceTiles>
```

## Disabled

Pass `disabled` to `ChoiceTiles` to disable every choice, or to a single `ChoiceTiles.Choice` to disable only that choice.

```tsx
<ChoiceTiles aria-label="Access level" defaultValue="extended">
    <ChoiceTiles.Choice value="essential" id="essential" disabled>
        <ChoiceTiles.Title>Essential</ChoiceTiles.Title>
    </ChoiceTiles.Choice>
    <ChoiceTiles.Choice value="extended" id="extended">
        <ChoiceTiles.Title>Extended</ChoiceTiles.Title>
    </ChoiceTiles.Choice>
</ChoiceTiles>
```

## Loading state

Use `ChoiceTilesLoadingSkeleton` while the choices are loading. Pass `numberOfChoices` to match the number of choices you expect to render.

```tsx
import {ChoiceTilesLoadingSkeleton} from '@pleo-io/telescope'

const Loading = () => <ChoiceTilesLoadingSkeleton numberOfChoices={3} />
```

## Custom content

You can render your own content inside `ChoiceTiles.Choice`. Everything inside a choice is wrapped in a `label` element, so avoid block-level elements such as `div` to keep the markup valid. The same applies to the children of `ChoiceTiles.Title` and `ChoiceTiles.Description`, which are rendered inside a `Text` component.

## API reference

A group of selectable tiles, for choices that need more context than a regular radio button.

#### `orientation`

Type: `"horizontal" | "vertical" | undefined`

Default: `vertical`

Whether the choices are laid out in a column or in a row

### ChoiceTiles.Choice

#### `children` (required)

Type: `ReactNode`

##### Allowed values

- `null`
- `string`
- `number`
- `bigint`
- `false`
- `true`
- `ReactElement<unknown, string | JSXElementConstructor<any>>`
- `Iterable<ReactNode>`
- `ReactPortal`
- `Promise<AwaitedReactNode>`

Default: -

The title and description of the choice

#### `className`

Type: `string | undefined`

Default: -

No description available

#### `expandedContent`

Type: `ReactNode`

##### Allowed values

- `null`
- `string`
- `number`
- `bigint`
- `false`
- `true`
- `ReactElement<unknown, string | JSXElementConstructor<any>>`
- `Iterable<ReactNode>`
- `ReactPortal`
- `Promise<AwaitedReactNode>`

Default: -

Content shown below the choice, only when passed

#### `id` (required)

Type: `string`

Default: -

Unique id on the page, used to link the label to the radio input

#### `value` (required)

Type: `string`

Default: -

The value submitted when this choice is selected

### ChoiceTiles.Title

#### `children` (required)

Type: `ReactNode`

##### Allowed values

- `null`
- `string`
- `number`
- `bigint`
- `false`
- `true`
- `ReactElement<unknown, string | JSXElementConstructor<any>>`
- `Iterable<ReactNode>`
- `ReactPortal`
- `Promise<AwaitedReactNode>`

Default: -

Short, concise title of the choice

#### `className`

Type: `string | undefined`

Default: -

No description available

### ChoiceTiles.Tag

#### `children` (required)

Type: `ReactNode`

##### Allowed values

- `null`
- `string`
- `number`
- `bigint`
- `false`
- `true`
- `ReactElement<unknown, string | JSXElementConstructor<any>>`
- `Iterable<ReactNode>`
- `ReactPortal`
- `Promise<AwaitedReactNode>`

Default: -

Provide the tag with a label

#### `Icon`

Type: `FC<{ size?: any; color?: any; }> | undefined`

Default: -

Add an icon to the left of the label @deprecated Icons are no longer part of the Tag design and will be removed in a future version.

#### `variant`

Type: `TagVariants | undefined`

##### Allowed values

- `"pink"`
- `"green"`
- `"yellow"`
- `"purple"`
- `"gray"`

Default: -

Choose what color the tag should be.

Only `pink` and `gray` are part of the current design - `yellow`, `green` and `purple` are deprecated (enforced by the `deprecate-component-prop` oxlint rule).

### ChoiceTiles.Description

#### `children` (required)

Type: `ReactNode`

##### Allowed values

- `null`
- `string`
- `number`
- `bigint`
- `false`
- `true`
- `ReactElement<unknown, string | JSXElementConstructor<any>>`
- `Iterable<ReactNode>`
- `ReactPortal`
- `Promise<AwaitedReactNode>`

Default: -

Longer description giving context for the choice

#### `className`

Type: `string | undefined`

Default: -

No description available

### ChoiceTilesLoadingSkeleton

#### `numberOfChoices`

Type: `number | undefined`

Default: `2`

Number of choice tiles to render
