> ## Documentation Index
> Fetch the complete documentation index at: https://docs.twenty.com/llms.txt
> Use this file to discover all available pages before exploring further.

# ListItem

> Compose consistent rows with icons, descriptions, indicators, and actions.

export const StoryEmbed = ({storyId, title, height = 240}) => <>
    <Tabs>
      <Tab title="Light">
        <iframe title={`${title} (light)`} src={`https://storybook.twenty.com/iframe.html?id=${storyId}&viewMode=story&globals=colorScheme:light`} width="100%" height={height} loading="lazy" style={{
  border: 0
}} />
      </Tab>
      <Tab title="Dark">
        <iframe title={`${title} (dark)`} src={`https://storybook.twenty.com/iframe.html?id=${storyId}&viewMode=story&globals=colorScheme:dark`} width="100%" height={height} loading="lazy" style={{
  border: 0
}} />
      </Tab>
    </Tabs>
    <a href={`https://storybook.twenty.com/?path=/story/${storyId}`}>
      Open in Storybook
    </a>
  </>;

`ListItem` supplies the visual layout shared by list and menu rows. Use [Menu](/ui/primitives/surfaces/menu) or [Select](/ui/primitives/input/select) when you need their selection and keyboard behavior.

<StoryEmbed storyId="ui-navigation-listitem--default" title="ListItem example" height={240} />

## Anatomy

`ListItem` exposes content slots through props. These slots arrange content inside one row; they are not separately exported components.

```text theme={null}
ListItem
├── startIcon
├── children
├── description
├── actions
└── endIcon
```

| Slot                                 | Requirement                      | Purpose                                                                         |
| ------------------------------------ | -------------------------------- | ------------------------------------------------------------------------------- |
| `children`                           | Required for a visible row label | Supplies the main text.                                                         |
| `startIcon`, `endIcon`               | Optional                         | Add supporting icons at either end of the row content.                          |
| `description`                        | Optional                         | Adds supporting text inline or at the end, according to `descriptionPlacement`. |
| `actions`                            | Optional                         | Adds trailing content, such as a separately focusable action.                   |
| `indicator`, `hotkeys`, `hasSubmenu` | Optional                         | Configure built-in selection marks, shortcut hints, and the submenu indicator.  |

The row supplies layout. Use `render` to choose its element and semantics. For a row with independent action buttons, keep the row itself non-interactive so those buttons remain separate controls.

## Action row

```tsx theme={null}
import { IconCopy } from 'twenty-ui/icon';
import { ListItem } from 'twenty-ui/primitives/navigation';

type DuplicateActionProps = { onDuplicate: () => void };

export const DuplicateAction = ({ onDuplicate }: DuplicateActionProps) => (
  <ListItem
    render={<button type="button" />}
    startIcon={<IconCopy aria-hidden />}
    description="Create a copy"
    onClick={onDuplicate}
  >
    Duplicate
  </ListItem>
);
```

The default element is a `div`. Use `render` to give an interactive row appropriate semantics, such as a button or link. `hotkeys` displays shortcut hints; your application must register the shortcuts.

## Selection indicator

```tsx theme={null}
import { useState } from 'react';
import { ListItem } from 'twenty-ui/primitives/navigation';

export const ShowArchivedToggle = () => {
  const [selected, setSelected] = useState(false);

  return (
    <ListItem
      render={<button type="button" aria-pressed={selected} />}
      selected={selected}
      indicator="check"
      onClick={() => setSelected(!selected)}
    >
      Show archived records
    </ListItem>
  );
};
```

`selected`, `focused`, and `disabled` control row styling. The `check` and `checkbox` indicators are visual; use a real [Checkbox](/ui/primitives/input/checkbox) for a form control. When using a disabled button or link through `render`, also supply the element's appropriate disabled behavior and semantics.

## Slots

Use `startIcon` and `endIcon` for icons, `description` for supporting text, `actions` for trailing content, and `hasSubmenu` for a submenu indicator. `descriptionPlacement` accepts `inline` or `end`. `color="danger"` styles a destructive action. Avoid nesting interactive controls inside a row rendered as a button.

```tsx theme={null}
import { Button } from 'twenty-ui/primitives/input';
import { ListItem } from 'twenty-ui/primitives/navigation';

type ContactRowProps = { onOpen: () => void };

export const ContactRow = ({ onOpen }: ContactRowProps) => (
  <ListItem
    description="Account owner"
    actions={
      <Button
        type="button"
        title="Open"
        ariaLabel="Open Alex Morgan's profile"
        variant="tertiary"
        size="small"
        onClick={onOpen}
      />
    }
  >
    Alex Morgan
  </ListItem>
);
```

## Props

The reference is generated from the public component types. Native attributes, including accessible names and event handlers, are also accepted on parts that render elements.

<ParamField body="actions" type="ReactNode">
  Trailing content, such as buttons, rendered after the content.
</ParamField>

<ParamField body="color" type="&#x22;neutral&#x22; | &#x22;danger&#x22;" default="neutral">
  Color of the text and icons. `danger` marks a destructive action.
</ParamField>

<ParamField body="description" type="ReactNode">
  Supporting text, placed according to `descriptionPlacement`.
</ParamField>

<ParamField body="descriptionPlacement" type="&#x22;inline&#x22; | &#x22;end&#x22;" default="inline">
  Where the description renders: inline after the content or at the end of
  the row.
</ParamField>

<ParamField body="disabled" type="boolean" default="false">
  Prevents clicks and applies the disabled style.
</ParamField>

<ParamField body="endIcon" type="ReactNode">
  Icon rendered after the content.
</ParamField>

<ParamField body="focused" type="boolean" default="false">
  Applies the highlighted style, for example to the focused item of a list.
</ParamField>

<ParamField body="hasSubmenu" type="boolean" default="false">
  Shows a chevron indicating that the item opens a submenu.
</ParamField>

<ParamField body="hotkeys" type="string[]">
  Keyboard shortcut keys displayed at the end of the row. Registering the
  shortcut is up to the application.
</ParamField>

<ParamField body="indicator" type="&#x22;none&#x22; | &#x22;checkbox&#x22; | &#x22;check&#x22;" default="none">
  Selection indicator: a check icon after the content or a checkbox before
  it.
</ParamField>

<ParamField body="render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, ListItemState>">
  Allows you to replace the component's HTML element
  with a different tag, or compose it with another component.

  Accepts a `ReactElement` or a function that returns the element to render.
</ParamField>

<ParamField body="selected" type="boolean" default="false">
  Whether the item is selected. Shows the check or checkbox indicator when
  `indicator` is set.
</ParamField>

<ParamField body="startIcon" type="ReactNode">
  Icon rendered before the content.
</ParamField>
