# List item

A versatile element that can display information in a clear and organized manner.

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

## Purpose

`ListItem` is a clickable row for lists of entities, such as expenses, invoices, reimbursements, purchase orders or bank accounts. Each row shows an avatar, a title with a subtitle, an amount or other secondary details, and optional badges. Rows can be selected with a checkbox and marked as active.

`ListItem` renders a single row. Render rows yourself, or use it as the item renderer of a list component. For a plain bulleted or numbered list of text, use [List](/components/web/list/list.guidelines) and `List.Item` instead.

## Basic usage

```tsx
import {ListItem} from '@pleo-io/telescope'
;<ListItem onClick={openExpense}>
    <ListItem.Avatar name="Jenny Lindh" />
    <ListItem.PrimaryColumn>
        <ListItem.PrimaryTitle headingLevel="h3">Jenny Lindh</ListItem.PrimaryTitle>
        <ListItem.Subtitle>Mileage · 244.3 km</ListItem.Subtitle>
    </ListItem.PrimaryColumn>
    <ListItem.SecondaryColumn>
        <ListItem.SecondaryTitle>728,00 DKK</ListItem.SecondaryTitle>
        <ListItem.Subtitle>For review: 58,00 DKK</ListItem.Subtitle>
    </ListItem.SecondaryColumn>
</ListItem>
```

`onClick` is wired to `ListItem.PrimaryTitle`, which stretches its click area over the whole row. Always render a `ListItem.PrimaryTitle` when you pass `onClick`.

## Layout and hover

The row's background extends `24px` beyond its container on the left and right, so its content lines up with the content around it. Give the container at least `24px` of horizontal padding, so the hover and active states don't overflow or get clipped. Check the hover state at all screen sizes when you use `ListItem` in a custom layout.

Text in the primary column wraps on narrow rows and is truncated with an ellipsis once the row is at least `360px` wide. The row is a CSS container named `list-item`.

Set `hasNoBackground` to show the background only on hover.

## Avatar and badge

`ListItem.Avatar` is a 48px [Avatar](/components/web/avatar/avatar.guidelines) and accepts its props, except `size`. Add a `ListItem.AvatarBadge` inside it to show a small icon in the corner.

```tsx
<ListItem.Avatar name="NeoTech Hypervalentix">
    <ListItem.AvatarBadge Icon={ArrowCircleLeft} />
</ListItem.Avatar>
```

## Status

Set `statusVariant="negative"` to colour the avatar badge and the primary column subtitle with the negative colour, for example for a cancelled transaction.

```tsx
<ListItem statusVariant="negative" onClick={openTransaction}>
    <ListItem.Avatar name="InnovaTech">
        <ListItem.AvatarBadge Icon={CircleClose} />
    </ListItem.Avatar>
    <ListItem.PrimaryColumn>
        <ListItem.PrimaryTitle headingLevel="h3">InnovaTech</ListItem.PrimaryTitle>
        <ListItem.Subtitle>Transaction cancelled</ListItem.Subtitle>
    </ListItem.PrimaryColumn>
    <ListItem.SecondaryColumn>
        <ListItem.SecondaryTitle strikethrough>728,00 DKK</ListItem.SecondaryTitle>
    </ListItem.SecondaryColumn>
</ListItem>
```

## Badges

Put [Badges](/components/web/badge/badge.guidelines) in `ListItem.BadgeContainer`. They're shown below the title, across both columns.

```tsx
<ListItem.BadgeContainer>
    <Badge variant="warning" Icon={Calendar}>
        Overdue since 4 May
    </Badge>
</ListItem.BadgeContainer>
```

## Selection and active state

Pass `checkboxProps` to show a checkbox at the start of the row. Clicking the checkbox doesn't trigger the row's `onClick`. `label` is visually hidden and names the checkbox for screen readers. When the checkbox is disabled, use `tooltipContent` to explain why.

```tsx
<ListItem
    onClick={openInvoice}
    isActive={isInvoiceOpen}
    checkboxProps={{
        label: 'Select invoice',
        checked: isSelected,
        onChange: toggleSelected,
    }}
>
    {/* … */}
</ListItem>
```

Set `isActive` to highlight the row whose details are open, for example in a drawer.

## Subcomponents

| Component                  | Description                                                                                          |
| -------------------------- | ---------------------------------------------------------------------------------------------------- |
| `ListItem.Avatar`          | A 48px [Avatar](/components/web/avatar/avatar.guidelines).                                           |
| `ListItem.AvatarBadge`     | An icon in the corner of the avatar. Coloured by `statusVariant`.                                    |
| `ListItem.PrimaryColumn`   | The main column, aligned to the start.                                                               |
| `ListItem.PrimaryTitle`    | The row's heading. Set `headingLevel` to fit the page. Triggers `onClick`. Supports `strikethrough`. |
| `ListItem.SecondaryColumn` | The column aligned to the end, for example for amounts.                                              |
| `ListItem.SecondaryTitle`  | A title for the secondary column. Supports `strikethrough` and `color`.                              |
| `ListItem.Subtitle`        | Smaller, quiet text below a title.                                                                   |
| `ListItem.BadgeContainer`  | A wrapping row of badges below the columns.                                                          |

## Accessibility

- `ListItem.PrimaryTitle` renders a heading with a button inside. Pick a `headingLevel` that fits the page structure, so screen reader users can jump between rows.
- The row is reachable with the keyboard through that button, which shows the focus ring around the whole row.
- Give the checkbox a meaningful `label`, for example "Select invoice from NeoTech".
- Give icon-only avatars an `aria-label` on the icon.

## API reference

A clickable row for lists of entities, such as expenses, invoices or accounts. Compose it with `ListItem.Avatar`, `ListItem.PrimaryColumn`, `ListItem.SecondaryColumn` and `ListItem.BadgeContainer`. The whole row is clickable through `ListItem.PrimaryTitle`. For a plain bulleted or numbered list use `List` and `List.Item` instead.

#### `checkboxProps`

Type: `ListItemCheckboxProps | undefined`

Default: -

Props for the select checkbox. Renders a checkbox at the start of the row when set.

#### `children` (required)

Type: `ReactNode`

##### Allowed values

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

Default: -

The contents of the ListItem

#### `hasNoBackground`

Type: `boolean`

Default: `false`

Whether the ListItem has no background without hover

#### `isActive`

Type: `boolean`

Default: `false`

Whether the ListItem is active, for example when its details are open

#### `onClick`

Type: `(() => void) | undefined`

##### Allowed values

- `() => void`

Default: -

Action performed when the ListItem is clicked on. Wired to `ListItem.PrimaryTitle`.

#### `statusVariant`

Type: `ListItemStatusVariant | undefined`

##### Allowed values

- `"neutral"`
- `"negative"`

Default: `neutral`

The status variant of the Avatar badge and Primary column Subtitle

#### `testId`

Type: `string | undefined`

Default: -

Test ID for the ListItem
