> ## 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

> Создавайте согласованные строки со значками, описаниями, индикаторами и действиями.

## Обзор

`ListItem` предоставляет визуальную структуру, общую для строк списков и меню. По умолчанию он отображает `div` для пассивного содержимого. Используйте [ListItemButton](https://docs.twenty.com/ru/ui/components/navigation/list-item-button.md) для обычных строк действий. При необходимости используйте `ListItem` с якорем для навигации или с пользовательским семантическим владельцем. Используйте [Dropdown](https://docs.twenty.com/ru/ui/components/navigation/dropdown.md) или [Select](https://docs.twenty.com/ru/ui/primitives/input/select.md), когда вам нужен полноценный владелец всплывающего окна или выбора.

**Light**

[Пример ListItem (light)](https://storybook.twenty.com/iframe.html?id=ui-navigation-listitem--display\&viewMode=story\&globals=colorScheme:light)

**Dark**

[Пример ListItem (dark)](https://storybook.twenty.com/iframe.html?id=ui-navigation-listitem--display\&viewMode=story\&globals=colorScheme:dark)

[Open in Storybook](https://storybook.twenty.com/?path=/story/ui-navigation-listitem--display)

## Использование

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

export const NotificationRow = () => (
  <ListItem startIcon={<IconBell />}>Notifications</ListItem>
);
```

## Анатомия

`ListItem` предоставляет слоты содержимого через props. Эти слоты размещают содержимое в одной строке; они не являются отдельно экспортируемыми компонентами.

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

| Слот | Требование | Назначение |
| - | - | - |
| `children` | Требуется для видимой метки строки | Предоставляет основной текст. |
| `startIcon`, `endIcon` | Необязательно | Добавляйте значки, аватары, метаданные или независимые элементы управления с любого конца. |
| `description` | Необязательно | Добавляет дополнительное содержимое в строке, под меткой или в конце. |
| `действия` | Необязательно | Добавляет завершающее содержимое, например отдельно фокусируемое действие. |
| `indicator`, `shortcut`, `hasSubmenu` | Необязательно | Настройте встроенные метки выбора, подсказки сочетаний клавиш и индикатор подменю. |

Строка предоставляет компоновку. `render` принимает элемент или обратный вызов, получающий нативные props и визуальное состояние. При использовании обратного вызова распределите эти props по фактическому корневому элементу. Нативные атрибуты, обработчики событий, `className`, `style` и `ref` передаются этому корневому элементу. Для строки с независимыми кнопками действий оставьте саму строку неинтерактивной, чтобы эти кнопки оставались отдельными элементами управления.

## Многострочные строки

Установите `descriptionPlacement="below"`, чтобы разместить дополнительное содержимое под меткой. Заголовок сохраняет существующее поведение усечения, а дополнительное содержимое переносится в пределах доступной ширины. Стандартное размещение `inline` и размещение `end` сохраняют существующий внешний вид.

**Light**

[Пример многострочного ListItem (light)](https://storybook.twenty.com/iframe.html?id=ui-navigation-listitem-multiline--display\&viewMode=story\&globals=colorScheme:light)

**Dark**

[Пример многострочного ListItem (dark)](https://storybook.twenty.com/iframe.html?id=ui-navigation-listitem-multiline--display\&viewMode=story\&globals=colorScheme:dark)

[Open in Storybook](https://storybook.twenty.com/?path=/story/ui-navigation-listitem-multiline--display)

```tsx theme={null}
import { Avatar } from 'twenty-ui/primitives/data-display';
import { ListItem } from 'twenty-ui/primitives/navigation';
import { Text } from 'twenty-ui/primitives/typography';

export const PlanningRow = () => (
  <ListItem
    descriptionPlacement="below"
    startIcon={<Avatar name="Alex Morgan" size="md" imageProps={{ alt: '' }} />}
    description="Review the proposed timeline and confirm the next steps with the team."
    endIcon={
      <Text render={<span />} size="sm" color="secondary">
        09:48
      </Text>
    }
  >
    Quarterly planning
  </ListItem>
);
```

Для более коротких предварительных просмотров передайте компонент [Text](https://docs.twenty.com/ru/ui/primitives/typography/text.md) с `truncate` или `lineClamp` в качестве `description`. Пользовательское содержимое самостоятельно управляет своей компоновкой и доступными метками.

### Независимые визуальные состояния

Все визуальные состояния принадлежат вызывающему коду. `active` определяет открытую или текущую строку, не выбирая её. `selected` обозначает выбор, а `focused` — подсветку навигации с клавиатуры без перемещения фокуса DOM. `active` применяет фон текущей строки. Установите `selectionAppearance="accent"`, чтобы добавить акцентную заливку выбранным строкам независимо от размещения описания. Внешний вид по умолчанию сохраняет существующее оформление выбора на основе индикатора. `focused` применяет общий подсвеченный фон, в том числе когда владелец использует его для подсветки указателем. Контур фокуса следует за фактическим фокусом с клавиатуры на корневом элементе или его элементах управления.

Эти свойства не добавляют доступных состояний. Укажите `aria-current`, `aria-selected` или состояние `checked` элемента управления на соответствующем семантическом владельце. Фактический фокус с клавиатуры также сохраняет нативный контур фокуса.

### Независимые элементы управления

Сохраняйте корневой `div` по умолчанию, если строка содержит настоящий флажок или независимые кнопки действий. Используйте `startIcon` для флажка, а `actions` — для кнопок. Декоративный `indicator` не нужен, если настоящий флажок уже отображает выбор.

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

type SelectablePlanningRowProps = {
  active?: boolean;
  disabled?: boolean;
  onOpen: () => void;
};

export const SelectablePlanningRow = ({
  active = false,
  disabled = false,
  onOpen,
}: SelectablePlanningRowProps) => {
  const [selected, setSelected] = useState(false);

  return (
    <ListItem
      active={active}
      selected={selected}
      selectionAppearance="accent"
      disabled={disabled}
      descriptionPlacement="below"
      description="Review the proposed timeline and confirm the next steps with the team."
      startIcon={
        <Checkbox
          aria-label="Select quarterly planning"
          checked={selected}
          onCheckedChange={setSelected}
          disabled={disabled}
        />
      }
      actions={
        <Button variant="ghost" size="sm" onClick={onOpen} disabled={disabled}>
          Open
        </Button>
      }
    >
      Quarterly planning
    </ListItem>
  );
};
```

Выбор и открытие — отдельные взаимодействия. Приложение управляет распространением событий, а также любой активацией строк и политикой клавиатуры. `ListItem.disabled` изменяет только внешний вид; передайте `disabled` каждому настоящему элементу управления, чтобы предотвратить его активацию.

Существующее поведение видимости действий применяется к многострочным строкам: `actionsVisibility="hover"` показывает действия при наведении или фокусе внутри строки и сохраняет их видимыми на сенсорных устройствах. Установите значение `always` для постоянно отображаемых действий, в том числе когда открыто всплывающее окно, принадлежащее вызывающему коду. При ширине строки 480px или менее многострочные действия перемещаются на отдельную строку и переносятся по мере необходимости.

## Строка действия

Используйте [ListItemButton](https://docs.twenty.com/ru/ui/components/navigation/list-item-button.md), чтобы сочетать стилизацию строки с нативным взаимодействием кнопки. Передайте `disabled` один раз, чтобы управлять и внешним видом, и активацией.

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

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

export const DuplicateAction = ({
  onDuplicate,
  disabled = false,
}: DuplicateActionProps) => (
  <ListItemButton
    disabled={disabled}
    startIcon={<IconCopy />}
    description="Create a copy"
    onClick={onDuplicate}
  >
    Duplicate
  </ListItemButton>
);
```

Пользовательский владелец кнопки по-прежнему может компоновать `ListItem` через `render`. Этот владелец предоставляет нативный фокус, активацию клавишами Enter и Space, а также поведение disabled. `ListItem.disabled` предоставляет только соответствующий визуальный стиль. `shortcut` отображает подсказки; сочетания клавиш регистрирует ваше приложение.

**Light**

[Пользовательская композиция кнопки (light)](https://storybook.twenty.com/iframe.html?id=ui-navigation-listitem--button-owner\&viewMode=story\&globals=colorScheme:light)

**Dark**

[Пользовательская композиция кнопки (dark)](https://storybook.twenty.com/iframe.html?id=ui-navigation-listitem--button-owner\&viewMode=story\&globals=colorScheme:dark)

[Open in Storybook](https://storybook.twenty.com/?path=/story/ui-navigation-listitem--button-owner)

## Навигация и явные ссылки

Передайте якорь через `render`, если навигация выполняется по всей строке. Разместите атрибуты якоря, включая `href`, `target` и `rel`, на этом элементе.

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

export const DocumentationLink = () => (
  <ListItem render={<a href="https://twenty.com/developers" />}>
    Typography documentation
  </ListItem>
);
```

**Light**

[Строка ссылки (light)](https://storybook.twenty.com/iframe.html?id=ui-navigation-listitem--link-owner\&viewMode=story\&globals=colorScheme:light)

**Dark**

[Строка ссылки (dark)](https://storybook.twenty.com/iframe.html?id=ui-navigation-listitem--link-owner\&viewMode=story\&globals=colorScheme:dark)

[Open in Storybook](https://storybook.twenty.com/?path=/story/ui-navigation-listitem--link-owner)

Строковые метки остаются текстом, включая строки в формате URL. ListItem не создаёт ссылки. Чтобы добавить ссылку в часть неинтерактивной строки, предоставьте якорь как содержимое, принадлежащее вызывающей стороне. Сохраните эту строку как `div`, чтобы избежать вложенных ссылок или кнопок. Строковые метки сохраняют усечение и всплывающую подсказку при переполнении; для пользовательского содержимого можно использовать [OverflowingTextWithTooltip](https://docs.twenty.com/ru/ui/primitives/typography/overflowing-text-with-tooltip.md) с явно отрисованным якорем.

У ссылок нет нативного атрибута `disabled`. Если назначение недоступно, владелец ссылки должен обеспечить соответствующую семантику, порядок перехода по Tab и политику навигации. Одна лишь стилизация с помощью `ListItem.disabled` не предотвращает навигацию.

## Владелец элемента всплывающего меню

Используйте `Dropdown.ActionItem` или `Dropdown.OptionItem` внутри их владельца всплывающего окна. Эти части уже компонуют макет ListItem и предоставляют его визуальные слоты. Владелец всплывающего меню предоставляет роли, фокус, навигацию с клавиатуры, активацию и поведение disabled.

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

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

export const RecordActions = ({ onDuplicate }: RecordActionsProps) => (
  <Dropdown.Root type="menu">
    <Dropdown.Trigger render={<Button>Record actions</Button>} />
    <Dropdown.Content>
      <Dropdown.ActionItem onClick={onDuplicate}>
        Duplicate record
      </Dropdown.ActionItem>
      <Dropdown.ActionItem disabled>Unavailable action</Dropdown.ActionItem>
    </Dropdown.Content>
  </Dropdown.Root>
);
```

**Light**

[Владелец элемента Dropdown (light)](https://storybook.twenty.com/iframe.html?id=ui-components-dropdown--display\&viewMode=story\&globals=colorScheme:light)

**Dark**

[Владелец элемента Dropdown (dark)](https://storybook.twenty.com/iframe.html?id=ui-components-dropdown--display\&viewMode=story\&globals=colorScheme:dark)

[Open in Storybook](https://storybook.twenty.com/?path=/story/ui-components-dropdown--display)

## Политика нативных событий

ListItem перенаправляет нативные объекты событий и обработчики. Щелчки всплывают обычным образом, включая щелчки по элементам управления завершающих действий. Установите любое намеренное ограничение на интерактивном владельце или в обработчике вызывающей стороны.

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

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

export const OpenRecord = ({ onOpen }: OpenRecordProps) => (
  <ListItem
    render={<button type="button" />}
    onClick={(event) => {
      event.stopPropagation();
      onOpen();
    }}
  >
    Open record
  </ListItem>
);
```

Вызывающей стороне также принадлежит любая политика `preventDefault()`, например предотвращение навигации по ссылке. Передача `onClick` не добавляет роль, не делает `div` доступным для управления с клавиатуры и не изменяет распространение событий.

## Перетаскивание и навигация редактора, управляемые приложением

Создавайте строки с возможностью изменения порядка с помощью `ListItem` внутри хоста перетаскивания вашего приложения. Разместите атрибуты и слушатели перетаскивания хоста на его рукоятке и передайте рукоятку или захват через `startIcon`. Сохраняйте отдельные элементы управления видимостью, редактированием и удалением в `actions`. Хост перетаскивания управляет изменением порядка с помощью указателя и клавиатуры, отключением перетаскивания и доступными метками рукоятки.

Для предложений редактора сохраните существующий listbox редактора и владельца активного варианта. Отрисовывайте каждый `ListItem` с `role="option"` и `aria-selected`, а для внешнего вида активной строки используйте `focused`. Редактор управляет навигацией стрелками и активацией клавишей Enter, пока фокус остается в области редактирования. Предотвращайте изменения фокуса при нажатии указателем, когда этого требует редактор, и обрабатывайте выбор указателем в обработчике строки приложения.

Для предложений на странице Dropdown используйте `Dropdown.OptionItem` или `Dropdown.ActionItem`, чтобы эта страница управляла навигацией и активацией. Не добавляйте второй обработчик Enter или Space владельцу, который уже активируется с клавиатуры.

## Строка настроек

Используйте [SettingsRow](https://docs.twenty.com/ru/ui/components/settings/settings-row.md) для строки переключателя с меткой. Он объединяет `ListItem` и `Switch`, управляет их доступной связью и использует отключенное состояние переключателя для внешнего вида строки.

## Индикатор выбора

```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>
  );
};
```

`active`, `selected`, `focused` и `disabled` независимо управляют оформлением строки. Они не регистрируют действия, не перемещают DOM-фокус, не добавляют доступные роли или состояния и не подавляют события. Индикаторы `check` и `checkbox` являются декоративными; для элемента управления формы используйте настоящий [Checkbox](https://docs.twenty.com/ru/ui/primitives/input/checkbox.md). Установите `aria-pressed`, `aria-selected` или семантику другого состояния на владельце, которому они нужны.

## Строки выбора

Выбор принадлежит родительскому элементу. У `ListItem` нет неконтролируемого состояния выбора: передайте `selected` и обновляйте его из `onClick`. Используйте `indicator="check"` для одного варианта и `indicator="checkbox"` для нескольких вариантов. Оба индикатора декоративные; интерактивный владелец обрабатывает активацию.

В существующем listbox передайте `role="option"` и `aria-selected`, а управление фокусом и клавишами со стрелками оставьте в listbox. Для полноценного виджета выбора используйте [Select](https://docs.twenty.com/ru/ui/primitives/input/select.md). Автономные кнопки выбора могут использовать `aria-pressed`, как в этих примерах.

### Одиночный выбор

Поместите [Avatar](https://docs.twenty.com/ru/ui/primitives/data-display/avatar.md) в `startIcon`, чтобы обозначить запись. Используйте `description` для вспомогательного текста и `descriptionPlacement="end"` для значения в конце.

**Light**

[Строки с одиночным выбором (light)](https://storybook.twenty.com/iframe.html?id=ui-navigation-listitem-picker--single-selection\&viewMode=story\&globals=colorScheme:light)

**Dark**

[Строки с одиночным выбором (dark)](https://storybook.twenty.com/iframe.html?id=ui-navigation-listitem-picker--single-selection\&viewMode=story\&globals=colorScheme:dark)

[Open in Storybook](https://storybook.twenty.com/?path=/story/ui-navigation-listitem-picker--single-selection)

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

export const AssigneeButtons = () => {
  const [assignee, setAssignee] = useState<string | null>(null);

  return (
    <div role="group" aria-label="Assignee">
      {['Alex Morgan', 'Sam Taylor'].map((name) => (
        <ListItem
          key={name}
          render={<button type="button" />}
          aria-pressed={assignee === name}
          selected={assignee === name}
          indicator="check"
          startIcon={<Avatar name={name} size="md" imageProps={{ alt: '' }} />}
          onClick={() => setAssignee(name)}
        >
          {name}
        </ListItem>
      ))}
    </div>
  );
};
```

### Множественный выбор

Используйте [Tag](https://docs.twenty.com/ru/ui/primitives/data-display/tag.md) в качестве содержимого строки для значений с тегами или поместите [ColorSample](https://docs.twenty.com/ru/ui/primitives/data-display/color-sample.md) в `startIcon` для выбора цвета. Строка также может содержать обычный текст или аватар.

**Light**

[Строки с множественным выбором (light)](https://storybook.twenty.com/iframe.html?id=ui-navigation-listitem-picker--multiple-selection\&viewMode=story\&globals=colorScheme:light)

**Dark**

[Строки с множественным выбором (dark)](https://storybook.twenty.com/iframe.html?id=ui-navigation-listitem-picker--multiple-selection\&viewMode=story\&globals=colorScheme:dark)

[Open in Storybook](https://storybook.twenty.com/?path=/story/ui-navigation-listitem-picker--multiple-selection)

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

export const TeammateButtons = () => {
  const [teammates, setTeammates] = useState<string[]>([]);

  const toggleTeammate = (name: string) => {
    setTeammates((current) =>
      current.includes(name)
        ? current.filter((teammate) => teammate !== name)
        : [...current, name],
    );
  };

  return (
    <div role="group" aria-label="Teammates">
      {['Alex Morgan', 'Sam Taylor'].map((name) => (
        <ListItem
          key={name}
          render={<button type="button" />}
          aria-pressed={teammates.includes(name)}
          selected={teammates.includes(name)}
          indicator="checkbox"
          onClick={() => toggleTeammate(name)}
        >
          <Tag color="blue">{name}</Tag>
        </ListItem>
      ))}
    </div>
  );
};
```

Индикатор флажка не является элементом управления формы и не отправляет значение. Используйте [Checkbox](https://docs.twenty.com/ru/ui/primitives/input/checkbox.md), если вам нужно участие в форме. Установите нативный `disabled` на отрисованной кнопке, чтобы предотвратить активацию и удалить её из порядка перехода по Tab. Также передайте `ListItem.disabled` для её визуального оформления.

## Слоты

Используйте `startIcon` и `endIcon` для значков или содержимого, принадлежащего вызывающему коду, `description` — для вспомогательного текста, `actions` — для конечного содержимого, а `hasSubmenu` — для индикатора подменю. `descriptionPlacement` принимает значения `inline`, `end` или `below`. `color="danger"` задаёт стиль для деструктивного действия. Не вкладывайте интерактивные элементы управления в строку, отрисованную как кнопка.

```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"
        aria-label="Open Alex Morgan's profile"
        variant="ghost"
        size="sm"
        onClick={onOpen}
      >
        Open
      </Button>
    }
  >
    Alex Morgan
  </ListItem>
);
```

## Метки

Используйте `shortcutJoinLabel`, чтобы настроить текст между последовательными шагами сочетания клавиш. По умолчанию используется `then`; пустая строка удаляет текст-соединитель. То же свойство доступно в частях элемента `Dropdown`.

## Свойства

Справочник создаётся на основе публичных типов компонента. Поддерживаются нативные атрибуты и обработчики `div`, включая доступные имена и нативные события. Разместите специфичные для кнопки или якоря атрибуты на элементе, предоставленном через `render`. И `ref`, и ref отрисованного элемента указывают на фактический корневой элемент DOM.

**actions** `ReactNode`

Trailing content, such as buttons, rendered after the content.

**actionsPlacement** `"auto" | "end"` (default: auto)

Keeps actions beside the content at every width when set to `end`. The default `auto` preserves responsive wrapping. Hidden end actions do not reserve width on devices without touch.

**actionsVisibility** `"always" | "hover"` (default: hover)

When trailing actions are visible: on hover and focus, or always.

**active** `boolean` (default: false)

Marks the open or current item independently of selection and focus. Does not add accessible state or activate the item.

**color** `"danger" | "neutral"` (default: neutral)

Color of the text and icons. `danger` marks a destructive action.

**description** `ReactNode`

Supporting text, placed according to `descriptionPlacement`.

**descriptionPlacement** `"below" | "end" | "inline"` (default: inline)

Places supporting content inline after the label, at the end, or below it with wrapping. Inline is the default.

**disabled** `boolean` (default: false)

Applies disabled styling only. Set native disabled behavior and accessible semantics on the button, link, or popup item owner.

**endIcon** `ReactNode`

Icon rendered after the content.

**focused** `boolean` (default: false)

Applies highlighted styling without moving DOM focus or handling keyboard navigation.

**hasSubmenu** `boolean` (default: false)

Shows a chevron indicating that the item opens a submenu.

**indicator** `"check" | "checkbox" | "none"` (default: none)

Selection indicator: a check icon after the content or a checkbox before
it.

**ref** `Ref\<HTMLElement\>`

Ref to the actual DOM root, including a composed native button or link.

**render** `ReactElement\<unknown, string | JSXElementConstructor\<any\>\> | ComponentRenderFn\<HTMLProps, ListItemState\>`

Composes the row with an element or render callback. The owner supplies interaction semantics, native attributes, and behavior.

**selected** `boolean` (default: false)

Applies selected styling and the configured decorative indicator. Selection state and accessible semantics belong to the owner.

**selectionAppearance** `"accent" | "default"` (default: default)

Selection styling independent of description placement. `default` preserves indicator-based styling; `accent` fills selected rows with the accent background.

**shortcut** `ShortcutDefinition`

Keyboard shortcut keys displayed at the end of the row. Registering the
shortcut is up to the application.

**shortcutJoinLabel** `string`

Text between sequential shortcut steps. Defaults to `then`; pass an empty string to omit it.

**startIcon** `ReactNode`

Icon rendered before the content.

Передайте `shortcut={['Mod', 'Enter']}` для одновременного нажатия клавиш или `shortcut={[['G'], ['P']]}` для последовательных нажатий. См. [Shortcut](https://docs.twenty.com/ru/ui/primitives/typography/shortcut.md) для вложенных комбинаций и общего форматировщика строк.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.