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

# Раскрывающийся список

> Меню действий, средства выбора с поиском и панели форм с единым представлением и взаимодействием.

## Обзор

`Dropdown` объединяет позиционируемое всплывающее окно, визуальные строки, навигацию с клавиатуры, фокус и закрытие. Ваше приложение управляет данными, фильтрацией, получением данных и разбиением на страницы. `SelectionGroup` управляет независимыми значениями выбора внутри всплывающего окна. Импортируйте его из `twenty-ui/components`.

**Light**

[Действия раскрывающегося списка (light)](https://storybook.twenty.com/iframe.html?id=ui-components-dropdown--display\&viewMode=story\&globals=colorScheme:light)

**Dark**

[Действия раскрывающегося списка (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)

Dropdown.Content принимает числовые смещения или функции для `sideOffset` и `alignOffset`. Функции смещения получают размеры якоря и всплывающего окна, сторону и выравнивание. Используйте их, чтобы сохранить перекрытие средства выбора поля, привязанного к ячейке, при масштабировании ячейки.

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

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

export const RecordActions = () => (
  <Dropdown.Root type="menu">
    <Dropdown.Trigger render={<Button>Record actions</Button>} />
    <Dropdown.Content aria-label="Record actions" width={240}>
      <Dropdown.Section>
        <Dropdown.ActionItem startIcon={<IconCopy />}>
          Duplicate
        </Dropdown.ActionItem>
        <Dropdown.Submenu>
          <Dropdown.SubmenuTrigger startIcon={<IconDownload />}>
            Export
          </Dropdown.SubmenuTrigger>
          <Dropdown.Content aria-label="Export formats">
            <Dropdown.Section>
              <Dropdown.ActionItem>CSV</Dropdown.ActionItem>
              <Dropdown.ActionItem>Excel</Dropdown.ActionItem>
            </Dropdown.Section>
          </Dropdown.Content>
        </Dropdown.Submenu>
      </Dropdown.Section>
      <Dropdown.Separator />
      <Dropdown.Section>
        <Dropdown.ActionItem startIcon={<IconArchive />}>
          Archive
        </Dropdown.ActionItem>
        <Dropdown.ActionItem
          render={
            <a href="#dropdown-documentation" aria-label="Documentation" />
          }
        >
          Documentation
        </Dropdown.ActionItem>
      </Dropdown.Section>
    </Dropdown.Content>
  </Dropdown.Root>
);
```

## Выберите тип взаимодействия

Задайте `type` для `Dropdown.Root` в соответствии с содержимым всплывающего окна.

| Тип | Содержимое | Взаимодействие |
| - | - | - |
| `menu` | Команды и ссылки навигации | Семантика меню с навигацией стрелками и поиском по вводу. |
| `picker` | Поиск, выбираемые значения и необязательные команды | Диалоговое окно, содержащее поиск, списки с возможностью выбора и необязательные команды. Клавиши со стрелками перемещаются между строками результатов. |
| `panel` | Поля ввода, формы и вспомогательные действия | Диалоговое окно с нативным поведением ввода и навигацией клавишей Tab. |

Средства выбора позволяют выполнять действия создания и использовать независимые группы выбора на одной странице в любом порядке. Каждая группа средства выбора представляет собой список, а ее параметры предоставляют `aria-selected`. Группы меню используют отмеченные пункты меню с переключателями или флажками. Группы панели используют кнопки с `aria-pressed`. Команды сохраняют семантику действий своего режима. Задайте доступное имя для каждой группы и `Search`. Это пользовательское средство выбора не является нативным Combobox.

`Content` получает доступное имя от `Trigger` или от `SubmenuTrigger` в подменю. Передайте `aria-label` в `Content`, если триггер отображает значение, например выбранный параметр, или если у корневого элемента нет триггера. Явные `aria-label` или `aria-labelledby`, а также `Title` внутри `Header` имеют приоритет над именем триггера.

[Select](https://docs.twenty.com/ru/ui/primitives/input/select.md) и [Popover](https://docs.twenty.com/ru/ui/primitives/surfaces/popover.md) по-прежнему доступны для прямой композиции.

## Структура

```text theme={null}
Dropdown.Root
├── Dropdown.Trigger
└── Dropdown.Content
    ├── Dropdown.Header
    │   ├── Dropdown.Close
    │   └── Dropdown.Title
    ├── Dropdown.Search
    └── Dropdown.Section
        ├── Dropdown.ActionItem
        └── Dropdown.SelectionGroup
            └── Dropdown.OptionItem
```

`Content` включает портал и позиционер. Используйте `width`, `side`, `align`, `sideOffset` и `alignOffset` для управления размещением, а `collisionPadding` — чтобы всплывающее окно оставалось дальше от краёв области просмотра перед сдвигом или переворотом (по умолчанию 5 пикселей). `Section` группирует строки с общими отступами, а `Separator` разделяет разделы. `scrollable` Section ограничивает высоту и прокручивается; вкладывайте в него разделы с метками, чтобы прокручивать их как один список. Для внешнего вида строк используется [ListItem](https://docs.twenty.com/ru/ui/primitives/navigation/list-item.md).

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

export const RecordActions = ({ onDuplicate }: { onDuplicate: () => void }) => (
  <Dropdown.Root type="menu">
    <Dropdown.Trigger render={<Button>Record actions</Button>} />
    <Dropdown.Content>
      <Dropdown.Section>
        <Dropdown.ActionItem startIcon={<IconCopy />} onClick={onDuplicate}>
          Duplicate
        </Dropdown.ActionItem>
      </Dropdown.Section>
    </Dropdown.Content>
  </Dropdown.Root>
);
```

Передавайте пользовательские элементы триггера через `render`, чтобы триггер оставался одним интерактивным элементом. Пользовательские компоненты должны перенаправлять предоставленные props и ref. `ActionItem` также принимает `render` для ссылок.

## Действия с элементом

`ActionItem` и `OptionItem` принимают `actions` для элементов управления в конце, например кнопки редактирования вкладки. Используйте их только на страницах `picker` и `panel`: `menu` может содержать только элементы меню, поэтому в нём нельзя разместить другие элементы управления. Установите `actionsVisibility="always"`, чтобы они оставались видимыми; значение по умолчанию — `"hover"`. Дополнительные элементы управления отображаются рядом с основным элементом управления строки и активируются независимо: они не закрывают всплывающее окно, поэтому при необходимости закройте его из обработчика действия. Свойство `render` и ref по-прежнему применяются к основному элементу управления, поэтому он также может служить ручкой перетаскивания.

Используйте `tabIndex={-1}` для дополнительного действия, доступного только с помощью указателя, для которого предусмотрена отдельная альтернатива с клавиатуры. При навигации с клавиатуры фокусировка и активация по-прежнему выполняются для основного элемента управления.

## Заголовки

`Header` размещает строку в верхней части всплывающего окна. Поместите в него `Title`, чтобы всплывающее окно получило имя по заголовку, а не по триггеру. `Close` закрывает всплывающее окно так же, как нажатие вне него. По умолчанию он отображает кнопку со значком X, поэтому задайте для неё `aria-label` или передайте `render` и дочерние элементы для другого элемента управления. Другие элементы управления, например кнопка возврата к предыдущему шагу, могут находиться в той же строке. Используйте `Dropdown.Back` при навигации по истории страниц корневого элемента.

## Поиск и выбор

`Search` предоставляет поле ввода и навигацию по строкам результатов. Передайте `value` и `onValueChange`; вычисляйте или получайте соответствующие результаты в вашем приложении. Отображайте `Loading`, пока запрос выполняется, и `Empty`, когда нет совпадающих результатов. Оба принимают предоставленный вызывающей стороной текст статуса.

**Light**

[Средство выбора с поиском и встроенным созданием (light)](https://storybook.twenty.com/iframe.html?id=ui-components-dropdown--picker-documentation\&viewMode=story\&globals=colorScheme:light)

**Dark**

[Средство выбора с поиском и встроенным созданием (dark)](https://storybook.twenty.com/iframe.html?id=ui-components-dropdown--picker-documentation\&viewMode=story\&globals=colorScheme:dark)

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

Оберните доступные для выбора параметры в `SelectionGroup` и задайте каждому параметру стабильное значение `value`, уникальное в пределах группы. Неконтролируемой группе также требуется `id`, уникальный в ее дереве выпадающего списка, включая подменю. Независимо вложенные компоненты `Root` хранят собственное хранилище выбора. Одиночный выбор использует строку или `null`, если выбор отсутствует. Множественный выбор использует массив, включая `[]`, если выбор отсутствует.

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

export const PersonPicker = () => {
  const [search, setSearch] = useState('');
  const [selectedPerson, setSelectedPerson] = useState<string | null>(null);
  const people = ['Ada Lovelace', 'Grace Hopper'].filter((person) =>
    person.toLowerCase().includes(search.toLowerCase()),
  );

  return (
    <Dropdown.Root type="picker">
      <Dropdown.Trigger render={<Button>Choose person</Button>} />
      <Dropdown.Content>
        <Dropdown.Search
          aria-label="Search people"
          value={search}
          onValueChange={setSearch}
        />
        <Dropdown.SelectionGroup
          id="person"
          aria-label="Person"
          value={selectedPerson}
          onValueChange={setSelectedPerson}
        >
          {people.map((person) => (
            <Dropdown.OptionItem key={person} value={person}>
              {person}
            </Dropdown.OptionItem>
          ))}
        </Dropdown.SelectionGroup>
      </Dropdown.Content>
    </Dropdown.Root>
  );
};
```

Передайте `value` и `onValueChange` для контролируемого выбора. Если не указывать `value` или передать `undefined`, выбор остается неконтролируемым; `defaultValue` задает его начальное значение. Неконтролируемая группа по умолчанию имеет значение `null` или `[]` при использовании `multiple`. Ее стабильный `id` сохраняет выбор при закрытии и повторном открытии, а также при навигации по страницам. Удаление или фильтрация параметра не очищает его выбранный идентификатор и не вызывает изменение; параметр снова выбирается при его возвращении. Используйте контролируемое значение, когда приложению требуется очистить недоступные варианты выбора.

Каждая группа изменяется независимо. Параметр фиксируется в ближайшей группе, а активная страница предоставляет одну упорядоченную коллекцию для навигации стрелками между группами и строками действий. Повторная активация выбранного одиночного параметра сохраняет его значение без еще одного обратного вызова изменения. Множественная активация переключает параметр в массиве.

**Light**

[Независимый выбор владельца и наблюдателя (light)](https://storybook.twenty.com/iframe.html?id=ui-components-dropdown--selection-groups-documentation\&viewMode=story\&globals=colorScheme:light)

**Dark**

[Независимый выбор владельца и наблюдателя (dark)](https://storybook.twenty.com/iframe.html?id=ui-components-dropdown--selection-groups-documentation\&viewMode=story\&globals=colorScheme:dark)

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

Одиночный выбор по умолчанию закрывает список; множественный выбор оставляет его открытым. `SelectionGroup.closeOnSelect` изменяет значение по умолчанию для группы, а `OptionItem.closeOnSelect` переопределяет его для одного параметра. Строки действий используют `closeOnClick` независимо. Отмененное изменение сохраняет предыдущий выбор и не закрывает всплывающее окно автоматически.

`onValueChange` получает следующее значение и сведения о событии с `event`, `reason`, `trigger`, `cancel()` и `isCanceled`. Причина имеет значение `item-press`, а `event` — это исходное событие активации. `OptionItem.onSelect` получает те же сведения до фиксации владельцем. Вызовите `cancel()` в любом из обратных вызовов, чтобы предотвратить выбор и автоматическое закрытие.

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

<Dropdown.SelectionGroup
  id="watchers"
  aria-label="Watchers"
  multiple
  defaultValue={[]}
  onValueChange={(value, eventDetails) => {
    if (value.length > 3) {
      eventDetails.cancel();
    }
  }}
>
  <Dropdown.OptionItem value="ada">Ada Lovelace</Dropdown.OptionItem>
  <Dropdown.OptionItem value="grace">Grace Hopper</Dropdown.OptionItem>
</Dropdown.SelectionGroup>;
```

Поиск получает фокус при открытии средства выбора. Без поиска фокус получает первый включенный выбранный параметр или первая включенная строка, если выбранного параметра нет. Когда `Search` находится в фокусе и введён непустой запрос, выделяется первый подходящий `OptionItem` среди групп выбора, а клавиша Enter активирует его. Строки действий никогда не выбираются таким способом. ArrowDown перемещает фокус на первую включённую строку, включая действия. При выходе из поиска очищаются предпросмотр и `aria-activedescendant`, даже если всплывающее окно остаётся открытым. При возврате к поиску восстанавливается предпросмотр для текущего запроса.

Enter ничего не делает для пустого запроса или запроса, состоящего только из пробелов, а также если не осталось подходящих вариантов. Ввод текста с помощью метода ввода не активирует вариант и не перемещает фокус клавишами со стрелками. Когда строки закреплены над совпадениями, например строка текущего значения или строка "нет", отображайте их только при совпадении с текстом поиска. Всплывающее окно остаётся открытым, если ни один параметр не совпадает. Фильтрация остаётся под управлением вызывающей стороны.

**Light**

[Множественный выбор (light)](https://storybook.twenty.com/iframe.html?id=ui-components-dropdown--multiple-selection-documentation\&viewMode=story\&globals=colorScheme:light)

**Dark**

[Множественный выбор (dark)](https://storybook.twenty.com/iframe.html?id=ui-components-dropdown--multiple-selection-documentation\&viewMode=story\&globals=colorScheme:dark)

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

Автономный `OptionItem` по-прежнему принимает `selected` и `onSelect` для вызывающих сторон, которые сами управляют выбором. Сгруппированные параметры получают выбор из значения группы; не дублируйте это состояние в параметре. Пользовательские группы выбора не предоставляют нативную отправку формы, сброс, проверку обязательности, поведение только для чтения или интеграцию с Field. Используйте [Select](https://docs.twenty.com/ru/ui/primitives/input/select.md), когда требуются эти нативные контракты формы.

## Сетки значков

**Light**

[Сетка значков со стилем выбранной ячейки (light)](https://storybook.twenty.com/iframe.html?id=ui-components-dropdown--icon-grid-documentation\&viewMode=story\&globals=colorScheme:light)

**Dark**

[Сетка значков со стилем выбранной ячейки (dark)](https://storybook.twenty.com/iframe.html?id=ui-components-dropdown--icon-grid-documentation\&viewMode=story\&globals=colorScheme:dark)

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

Задайте `columns` для `Section`, чтобы расположить элементы в столбцах сетки равной ширины. То же количество определяет навигацию с клавиатуры: Left и Right перемещают в пределах строки, а Up и Down — между строками. Навигация пропускает отключённые параметры и следует направлению чтения. Если в столбце не осталось включённых параметров, Up и Down перемещают к ближайшему включённому параметру следующей строки. Up из первой строки возвращает к полю поиска, если нет предыдущего раздела. Короткая последняя строка использует последний элемент, если запрошенный столбец отсутствует. Внутри подменю стрелка назад закрывает подменю, если слева от неё не осталось включённых параметров.

Отображайте каждый значок как `OptionItem` с доступной меткой и кнопкой значка через `render`. Используйте `indicator="none"`, чтобы отображать выбор через фон кнопки. Обратный вызов `render` получает состояние `{ selected, multiple, disabled }`; используйте его для стилизации выбранной ячейки и передачи предоставленных свойств и ref.

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

export const IconGrid = () => (
  <Dropdown.Root type="picker">
    <Dropdown.Trigger render={<Button>Choose icon</Button>} />
    <Dropdown.Content>
      <Dropdown.SelectionGroup
        id="icon"
        aria-label="Icon"
        defaultValue="calendar"
      >
        <Dropdown.Section columns={5}>
          <Dropdown.OptionItem
            value="calendar"
            aria-label="Calendar"
            indicator="none"
            nativeButton
            render={(props, state) => (
              <LightIconButton
                // oxlint-disable-next-line react/jsx-props-no-spreading
                {...props}
                size="md"
                color={state.selected ? 'accent' : 'neutral'}
                aria-label="Calendar"
              >
                <IconCalendar />
              </LightIconButton>
            )}
          />
        </Dropdown.Section>
      </Dropdown.SelectionGroup>
    </Dropdown.Content>
  </Dropdown.Root>
);
```

## Фокус клавиатуры

На страницах `menu` и `picker` строки образуют единую точку остановки Tab. Клавиши со стрелками перемещают фокус между разделами, действиями и параметрами, а Home и End перемещают его к первой и последней включённым строкам, если фокус не находится в поле поиска. Перемещение фокуса никогда не выбирает параметр; Enter или Space активирует строку в фокусе. При возврате с помощью Tab к строкам фокус возвращается на последнюю строку в фокусе или на первую включённую строку, если этой строки больше нет. Поиск, `Back` рядом с поиском, кнопки заголовка и другие элементы управления внутри всплывающего окна сохраняют собственные точки остановки Tab.

Tab и Shift+Tab закрывают `menu`, а также его родительские меню, когда фокус находится в подменю. В `picker` Tab перемещает фокус по элементам управления всплывающего окна и закрывает его, когда фокус покидает окно. `panel` сохраняет нативный порядок Tab своих элементов управления.

## Страницы и подменю

Используйте `Page` для навигации, которая заменяет содержимое того же всплывающего окна. Оберните первую страницу в `Page id="root"` или выберите другую начальную страницу с помощью `defaultPage`. Задайте `page` для действия, чтобы перейти без закрытия. `Back` возвращает на предыдущую страницу и восстанавливает фокус на вызвавшей его строке.

Страницы монтируются при первом посещении и остаются смонтированными в течение этого открытого сеанса. При возвращении на страницу сохраняются её локальный поиск, черновики форм и прокручиваемые разделы. Неактивные страницы скрыты и инертны: они не участвуют в навигации с клавиатуры, фокусировке или дереве доступности, а их вложенные всплывающие окна Dropdown неактивны.

При повторном открытии начинается новый сеанс на `defaultPage` со свежим содержимым, в том числе когда задан `Content.keepMounted` или всплывающее окно повторно открывается во время перехода закрытия. История страниц, локальный поиск и черновики сбрасываются. Закрываемая страница остаётся смонтированной во время перехода закрытия.

Неконтролируемые значения `SelectionGroup` остаются сохранёнными в `Root` под стабильным `id` каждой группы и сохраняются при повторном открытии. Значения, контролируемые вызывающей стороной, остаются в её ведении. Например, значение поиска, сохранённое выше `Content`, остаётся неизменным, пока вызывающая сторона его не обновит. Размещайте временное состояние поиска или черновика в компоненте внутри `Content` или `Page`, если оно должно сбрасываться вместе с сеансом; сохраняйте долгосрочное состояние приложения выше `Content`.

Страница может переопределить `type` корневого элемента. Например, меню действий может открыть страницу средства выбора с поиском или панель формы. Search получает фокус при переходе на страницу с поиском; другие страницы после `Back` устанавливают фокус на первую строку.

**Light**

[Навигация из меню на страницу средства выбора (light)](https://storybook.twenty.com/iframe.html?id=ui-components-dropdown--pages-documentation\&viewMode=story\&globals=colorScheme:light)

**Dark**

[Навигация из меню на страницу средства выбора (dark)](https://storybook.twenty.com/iframe.html?id=ui-components-dropdown--pages-documentation\&viewMode=story\&globals=colorScheme:dark)

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

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

export const FilterMenu = () => (
  <Dropdown.Root type="menu">
    <Dropdown.Trigger render={<Button>Filters</Button>} />
    <Dropdown.Content>
      <Dropdown.Page id="root">
        <Dropdown.Section>
          <Dropdown.ActionItem page="status">Status</Dropdown.ActionItem>
        </Dropdown.Section>
      </Dropdown.Page>
      <Dropdown.Page id="status" type="picker">
        <Dropdown.Back>Filters</Dropdown.Back>
        <Dropdown.Section>
          <Dropdown.SelectionGroup id="status" aria-label="Status">
            <Dropdown.OptionItem value="active">Active</Dropdown.OptionItem>
            <Dropdown.OptionItem value="archived">Archived</Dropdown.OptionItem>
          </Dropdown.SelectionGroup>
        </Dropdown.Section>
      </Dropdown.Page>
    </Dropdown.Content>
  </Dropdown.Root>
);
```

Для навигации из кода вызовите `useDropdownPage` в компоненте, отрисованном внутри корневого элемента. Он возвращает текущую `page`, `goToPage(page)`, `goBack()`, `canGoBack` и `isActive`. Внутри страницы `isActive` имеет значение true только пока эта страница активна и её выпадающее меню открыто. Используйте `isActive` для отображения пользовательских портальных всплывающих окон страницы, чтобы они исчезали, когда страница становится неактивной или выпадающее меню закрывается. Например, параметр может вернуться на предыдущую страницу после выбора, пока всплывающее окно остаётся открытым:

```tsx theme={null}
import { Dropdown, useDropdownPage } from 'twenty-ui/components/navigation';

export const StatusOptions = ({
  status,
  onStatusChange,
}: {
  status: string | null;
  onStatusChange: (status: string | null) => void;
}) => {
  const { goBack } = useDropdownPage();

  return (
    <Dropdown.SelectionGroup
      id="status"
      aria-label="Status"
      value={status}
      closeOnSelect={false}
      onValueChange={(value) => {
        onStatusChange(value);
        goBack();
      }}
    >
      {['Active', 'Archived'].map((option) => (
        <Dropdown.OptionItem key={option} value={option}>
          {option}
        </Dropdown.OptionItem>
      ))}
    </Dropdown.SelectionGroup>
  );
};
```

Используйте `Submenu` с `SubmenuTrigger` и вложенным `Content` для расположенного рядом меню. Arrow Right открывает подменю; Arrow Left возвращает к родительскому меню. Выбор закрывающего действия закрывает весь раскрывающийся список.

```text theme={null}
Dropdown.Content
└── Dropdown.Submenu
    ├── Dropdown.SubmenuTrigger
    └── Dropdown.Content
        └── Dropdown.ActionItem
```

## Независимые вложенные средства выбора

Поместите другой `Dropdown.Root` внутрь `Content`, когда элемент управления открывает собственное средство выбора, например селектор направления сортировки. Выбор внутреннего параметра закрывает только это средство выбора и восстанавливает фокус на его триггере. Escape и нажатия вне элемента закрывают по одному слою за раз. Используйте `Submenu` для команд, которые при выборе должны закрывать всё дерево меню.

**Light**

[Средство выбора сортировки с вложенным средством выбора направления (light)](https://storybook.twenty.com/iframe.html?id=ui-components-dropdown--nested-documentation\&viewMode=story\&globals=colorScheme:light)

**Dark**

[Средство выбора сортировки с вложенным средством выбора направления (dark)](https://storybook.twenty.com/iframe.html?id=ui-components-dropdown--nested-documentation\&viewMode=story\&globals=colorScheme:dark)

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

## Панели и управляемое состояние

Используйте `type="panel"` для полей ввода формы. Взаимодействие с вводом оставляет панель открытой; действие сохранения может её закрыть. Управляйте `open` и `onOpenChange`, когда другой компонент или сочетание клавиш должны открыть раскрывающийся список. Храните это состояние вместе с функцией, которая координирует взаимодействие.

**Light**

[Управляемая панель формы (light)](https://storybook.twenty.com/iframe.html?id=ui-components-dropdown--panel-documentation\&viewMode=story\&globals=colorScheme:light)

**Dark**

[Управляемая панель формы (dark)](https://storybook.twenty.com/iframe.html?id=ui-components-dropdown--panel-documentation\&viewMode=story\&globals=colorScheme:dark)

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

Escape закрывает всплывающее окно и восстанавливает фокус на его триггере. Взаимодействие вне окна также закрывает его, а клик, который его закрывает, не активирует элемент, на который он попадает. Клавиши, нажатые внутри всплывающего окна, остаются внутри него, кроме сочетаний Ctrl или Cmd, которые раскрывающийся список не обрабатывает, поэтому сочетания на уровне страницы продолжают работать. `Content` принимает параметры фокуса и портала из Popover, включая явную цель возврата фокуса для рабочих процессов редактора.

## Закрытие

Escape, нажатие вне всплывающего окна и выход из него клавишей Tab закрывают раскрывающийся список. Передайте `onEscapeKeyDown` или `onInteractOutside` в `Root`, чтобы отреагировать до закрытия, и вызовите `event.preventDefault()`, чтобы оставить его открытым. `event.target` — это элемент, нажатый за пределами, или `null`, когда фокус уходит с помощью Tab, а `event.type` — тип вызвавшего это события DOM, например `touchmove` при смахивании за пределами всплывающего окна. Предотвращённое нажатие вне окна всё равно достигает элемента, на который оно попадает.

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

export const ViewSettings = ({ isEditing }: { isEditing: boolean }) => (
  <Dropdown.Root
    type="panel"
    onInteractOutside={(event) => {
      if (isEditing) {
        event.preventDefault();
      }
    }}
  >
    <Dropdown.Trigger render={<Button>View settings</Button>} />
    <Dropdown.Content>
      <Dropdown.ActionItem>Save view</Dropdown.ActionItem>
    </Dropdown.Content>
  </Dropdown.Root>
);
```

## Привязка без триггера

Корневой элемент может открываться без `Trigger`, например как контекстное меню. Управляйте им с помощью `open` и `onOpenChange`, а в `Content` передайте `anchor`: элемент, ref или виртуальный элемент, возвращающий прямоугольник в координатах области просмотра. Задайте для `Content` `aria-label`, так как нет триггера, по которому можно задать ему имя. При закрытии фокус возвращается к элементу, который был в фокусе при открытии всплывающего окна.

**Light**

[Контекстное меню, привязанное к указателю (light)](https://storybook.twenty.com/iframe.html?id=ui-components-dropdown--context-menu-documentation\&viewMode=story\&globals=colorScheme:light)

**Dark**

[Контекстное меню, привязанное к указателю (dark)](https://storybook.twenty.com/iframe.html?id=ui-components-dropdown--context-menu-documentation\&viewMode=story\&globals=colorScheme:dark)

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

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

export const RecordContextMenu = ({ recordName }: { recordName: string }) => {
  const [open, setOpen] = useState(false);
  const [point, setPoint] = useState({ x: 0, y: 0 });

  return (
    <>
      <p
        onContextMenu={(event) => {
          event.preventDefault();
          setPoint({ x: event.clientX, y: event.clientY });
          setOpen(true);
        }}
      >
        {recordName}
      </p>
      <Dropdown.Root type="menu" open={open} onOpenChange={setOpen}>
        <Dropdown.Content
          aria-label="Record actions"
          anchor={{
            getBoundingClientRect: () => new DOMRect(point.x, point.y, 0, 0),
          }}
        >
          <Dropdown.ActionItem>Duplicate</Dropdown.ActionItem>
        </Dropdown.Content>
      </Dropdown.Root>
    </>
  );
};
```

Щелчок правой кнопкой в другом месте при открытом меню перемещает его в новую точку.

Вызывайте `useDropdownPlacementOrThrow` внутри `Dropdown.Content`, чтобы считывать определённые для него `side` и `align`, включая перевороты при коллизиях. Используйте определённую сторону, чтобы разместить элементы управления поиском и созданием средства выбора рядом с его триггером. Сохраняйте элементы управления в визуальном порядке DOM, чтобы навигация с клавиатуры соответствовала макету. Поиск под результатами получает фокус при нажатии `ArrowDown` на последнем результате; `ArrowUp` в этом поиске возвращает к последнему результату.

## Метки

Каждая часть управляет своим текстом: укажите `Search.placeholder` и нативные доступные имена, доступные атрибуты `Close`, а также дочерние элементы для `Back`, `Loading` и `Empty`. По умолчанию `Back` имеет текст `Back`; состояния загрузки и пустого результата не имеют встроенного сообщения. Части элементов принимают `shortcutJoinLabel` для замены стандартного `then` между последовательными шагами сочетания клавиш. Нативный `aria-labelledby` имеет приоритет над `aria-label`.

## Свойства

### Dropdown.Root

**Root.defaultOpen** `boolean`

Whether the popup is initially open when uncontrolled.

**Root.defaultPage** `string`

ID of the `Page` shown when the popup opens. Closing the popup resets the page history to it. Defaults to `root`.

**Root.multiple** `boolean`

Default for standalone options. Use `SelectionGroup.multiple` for independently owned selection values.

**Root.onEscapeKeyDown** `((event: DropdownDismissEvent) =\> void)`

Called when Escape is about to close the popup. Call `event.preventDefault()` to keep it open.

**Root.onInteractOutside** `((event: DropdownDismissEvent) =\> void)`

Called when a press outside the popup, or Tab out of it, is about to close it. `event.target` is the element pressed outside, or `null` after Tab, and `event.type` is the type of the DOM event that triggered it. Call `event.preventDefault()` to keep it open.

**Root.onOpenChange** `((open: boolean) =\> void)`

Called with the next open state when the popup opens or closes.

**Root.open** `boolean`

Whether the popup is open. Use with `onOpenChange` to control it.

**Root.type** `"menu" | "panel" | "picker"` *required*

Interaction model: `menu` for commands and links, `picker` for search and selectable options, or `panel` for forms. It sets the ARIA roles, initial focus, and keyboard navigation.

### Dropdown.Trigger

**Trigger.className** `string | ((state: PopoverTriggerState) =\> string | undefined)`

CSS class applied to the element, or a function that
returns a class based on the component's state.

**Trigger.closeDelay** `number` (default: 0)

How long to wait before closing the popover that was opened on hover.
Specified in milliseconds.

Requires the `openOnHover` prop.

**Trigger.delay** `number` (default: 300)

How long to wait before the popover may be opened on hover. Specified in milliseconds.

Requires the `openOnHover` prop.

**Trigger.id** `string`

ID of the trigger. In addition to being forwarded to the rendered element,
it is also used to specify the active trigger for the popover in controlled mode (with the PopoverRoot `triggerId` prop).

**Trigger.nativeButton** `boolean` (default: true)

Whether the component renders a native `<button>` element when replacing it
via the `render` prop.
Set to `false` if the rendered element is not a button (e.g. `<div>`).

**Trigger.openOnHover** `boolean` (default: false)

Whether the popover should also open when the trigger is hovered.

**Trigger.render** `ReactElement\<unknown, string | JSXElementConstructor\<any\>\> | ComponentRenderFn\<HTMLProps, PopoverTriggerState\>`

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.

**Trigger.style** `CSSProperties | ((state: PopoverTriggerState) =\> CSSProperties | undefined)`

Style applied to the element, or a function that
returns a style object based on the component's state.

### Dropdown.Content

**Content.align** `"center" | "end" | "start"` (default: start)

Alignment along the anchor. Defaults to start.

**Content.alignOffset** `number | OffsetFunction` (default: 0)

Offset along the alignment axis. Accepts a number or positioning function.

**Content.anchor** `Element | VirtualElement | RefObject\<Element | null\> | (() =\> Element | VirtualElement | null) | null`

An element to position the popup against.
By default, the popup will be positioned against the trigger.

**Content.className** `string | ((state: PopoverPopupState) =\> string | undefined)`

CSS class applied to the element, or a function that
returns a class based on the component's state.

**Content.collisionPadding** `Padding` (default: 5)

Additional space to maintain from the edge of the collision boundary.

**Content.container** `HTMLElement | ShadowRoot | RefObject\<HTMLElement | ShadowRoot | null\> | null`

Portal destination, using the scoped theme when omitted. Explicit null waits for a target, matching Popover.Portal.

**Content.finalFocus** `boolean | RefObject\<HTMLElement | null\> | ((closeType: InteractionType) =\> boolean | void | HTMLElement | null)`

Determines the element to focus when the popover is closed.

* `false`: Do not move focus.
* `true`: Move focus based on the default behavior (trigger or previously focused element).
* `RefObject`: Move focus to the ref element.
* `function`: Called with the interaction type (`mouse`, `touch`, `pen`, or `keyboard`).
  Return an element to focus, `true` to use the default behavior, `null` to fall back to the default behavior, or `false`/`undefined` to do nothing.

**Content.initialFocus** `boolean | RefObject\<HTMLElement | null\> | ((openType: InteractionType) =\> boolean | void | HTMLElement | null)`

Determines the element to focus when the popover is opened.
By default, focus moves to the first tabbable element inside the popup, except when the popover
is opened by touch — then the popup itself is focused to avoid opening the virtual keyboard.

* `false`: Do not move focus.
* `true`: Move focus based on the default behavior (first tabbable element or popup).
* `RefObject`: Move focus to the ref element.
* `function`: Called with the interaction type (`mouse`, `touch`, `pen`, or `keyboard`).
  Return an element to focus, `true` to use the default behavior, `null` to fall back to the default behavior, or `false`/`undefined` to do nothing.

**Content.keepMounted** `boolean` (default: false)

Keeps the popup mounted while closed.

**Content.render** `ReactElement\<unknown, string | JSXElementConstructor\<any\>\> | ComponentRenderFn\<HTMLProps, PopoverPopupState\>`

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.

**Content.side** `"bottom" | "inline-end" | "inline-start" | "left" | "right" | "top"` (default: bottom)

Preferred side of the anchor. Defaults to bottom, or inline-end in a submenu.

**Content.sideOffset** `number | OffsetFunction` (default: 0)

Distance from the anchor. Defaults to 0. Accepts a number or positioning function.

**Content.style** `CSSProperties | ((state: PopoverPopupState) =\> CSSProperties | undefined)`

Style applied to the element, or a function that
returns a style object based on the component's state.

**Content.width** `Width\<string | number\>` (default: 200)

CSS width of the popup. Numbers are in pixels.

### Dropdown.ActionItem

**ActionItem.actions** `ReactNode`

Trailing controls rendered beside the primary row control. Only supported in picker and panel pages, since a menu may only contain menu items. Secondary actions activate independently of the row.

**ActionItem.actionsVisibility** `"always" | "hover"`

Whether trailing actions appear on hover or remain visible. Defaults to `hover`.

**ActionItem.className** `string`

CSS class applied to the row.

**ActionItem.closeOnClick** `boolean` (default: true)

Closes the dropdown after activation, along with parent menus when inside a submenu. Ignored when `page` is set.

**ActionItem.color** `"danger" | "neutral"`

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

**ActionItem.description** `ReactNode`

Supporting text, placed according to `descriptionPlacement`.

**ActionItem.descriptionPlacement** `"below" | "end" | "inline"`

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

**ActionItem.endIcon** `ReactNode`

Icon rendered after the content.

**ActionItem.focusableWhenDisabled** `boolean` (default: false)

Whether the button should be focusable when disabled.

**ActionItem.hasSubmenu** `boolean`

Shows a chevron indicating that the item opens a submenu.

**ActionItem.nativeButton** `boolean` (default: true when render is omitted; false otherwise)

Whether the component renders a native `<button>` element when replacing it
via the `render` prop.
Set to `false` if the rendered element is not a button (for example, `<div>`).

**ActionItem.page** `string`

ID of the `Page` to show on activation. The popup stays open, and the row shows a chevron by default.

**ActionItem.render** `ReactElement\<unknown, string | JSXElementConstructor\<any\>\>`

Element rendered as the row instead of a native button. Custom components must forward the supplied props and ref.

**ActionItem.shortcut** `ShortcutDefinition`

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

**ActionItem.shortcutJoinLabel** `string`

Text between sequential shortcut steps. Defaults to `then`.

**ActionItem.startIcon** `ReactNode`

Icon rendered before the content.

**ActionItem.style** `CSSProperties`

Inline styles applied to the row.

### Dropdown.OptionItem

**OptionItem.actions** `ReactNode`

Trailing controls rendered beside the primary row control. Only supported in picker and panel pages, since a menu may only contain menu items. Secondary actions activate independently of the row.

**OptionItem.actionsVisibility** `"always" | "hover"`

Whether trailing actions appear on hover or remain visible. Defaults to `hover`.

**OptionItem.className** `string`

CSS class applied to the row.

**OptionItem.closeOnSelect** `boolean`

Overrides the nearest group close policy for this option. A cancelled selection never closes automatically.

**OptionItem.color** `"danger" | "neutral"`

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

**OptionItem.description** `ReactNode`

Supporting text, placed according to `descriptionPlacement`.

**OptionItem.descriptionPlacement** `"below" | "end" | "inline"`

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

**OptionItem.endIcon** `ReactNode`

Icon rendered after the content.

**OptionItem.focusableWhenDisabled** `boolean` (default: false)

Whether the button should be focusable when disabled.

**OptionItem.hasSubmenu** `boolean`

Shows a chevron indicating that the item opens a submenu.

**OptionItem.indicator** `"check" | "checkbox" | "none"`

Selection indicator: a check icon after the content, a checkbox before it, or none. Defaults to `checkbox` when `multiple` is set, otherwise `check`, and to `none` when `selected` is omitted.

**OptionItem.nativeButton** `boolean` (default: true when render is omitted; false otherwise)

Whether the component renders a native `<button>` element when replacing it
via the `render` prop.
Set to `false` if the rendered element is not a button (for example, `<div>`).

**OptionItem.onSelect** `((eventDetails: DropdownSelectionGroupChangeEventDetails) =\> void)`

Called before the nearest group commits selection, with `event`, `reason`, `trigger`, `cancel` and `isCanceled`. Calling `cancel()` prevents the value change and automatic close.

**OptionItem.render** `ReactElement\<unknown, string | JSXElementConstructor\<any\>\> | ComponentRenderFn\<HTMLProps, DropdownOptionItemState\>`

Element or function rendered as the row. Functions receive the supplied props and `{ selected, multiple, disabled }` state. Forward the props and ref to the rendered control.

**OptionItem.selected** `boolean`

Selected state for standalone options. Options inside a `SelectionGroup` derive it from their owner. Grouped picker options expose `aria-selected`, menu options expose `aria-checked`, and panel options expose `aria-pressed`.

**OptionItem.shortcut** `ShortcutDefinition`

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

**OptionItem.shortcutJoinLabel** `string`

Text between sequential shortcut steps. Defaults to `then`.

**OptionItem.startIcon** `ReactNode`

Icon rendered before the content.

**OptionItem.style** `CSSProperties`

Inline styles applied to the row.

**OptionItem.value** `string`

Stable option identifier within its nearest `SelectionGroup`. The group supplies selected state and commits this value on activation.

### Dropdown.SelectionGroup

**SelectionGroup.closeOnSelect** `boolean`

Default close policy for owned options: true for single selection, false for multiple selection. Individual options can override it.

**SelectionGroup.defaultValue** `string | string[] | null`

Initial uncontrolled selection. Defaults to null for single selection and an empty array for multiple selection.

**SelectionGroup.id** `string`

Stable identifier unique within the dropdown root. Required for uncontrolled groups, whose values persist under it across popup close and page navigation. Optional for controlled groups.

**SelectionGroup.multiple** `boolean`

Uses an array of selected identifiers when true. Otherwise the value is one identifier or null.

**SelectionGroup.onValueChange** `((value: string | null, eventDetails: DropdownSelectionGroupChangeEventDetails) =\> void) | ((value: string[], eventDetails: DropdownSelectionGroupChangeEventDetails) =\> void)`

Called with the next value and cancellable event details: `event`, `reason`, `trigger`, `cancel` and `isCanceled`. Calling `cancel()` preserves the value and keeps the popup open. Repeated single selection does not emit another change.

**SelectionGroup.render** `ReactElement\<unknown, string | JSXElementConstructor\<any\>\> | ComponentRenderFn\<HTMLProps, DropdownSelectionGroupState\>`

Element or function rendered as the group. Functions receive supplied props and `{ value, multiple }` state. Forward the props and ref.

**SelectionGroup.value** `string | string[] | null`

Controlled selection: a string or null for single selection, or an array for multiple selection. Undefined leaves selection uncontrolled.

### Dropdown.Search

**Search.className** `string | ((state: InputState) =\> string | undefined)`

CSS class applied to the element, or a function that
returns a class based on the component's state.

**Search.defaultValue** `string | number | readonly string[]`

The default value of the input. Use when uncontrolled.

**Search.hasFocusRing** `boolean` (default: false)

Shows the search input focus outline. Defaults to false for all dropdown searches. Set true to opt in. Error styling remains visible.

**Search.onValueChange** `((value: string) =\> void)`

Called with the search text on every change. The application filters the results.

**Search.render** `ReactElement\<unknown, string | JSXElementConstructor\<any\>\> | ComponentRenderFn\<HTMLProps, InputState\>`

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.

**Search.style** `CSSProperties | ((state: InputState) =\> CSSProperties | undefined)`

Style applied to the element, or a function that
returns a style object based on the component's state.

**Search.textAlign** `"end" | "start"`

Aligns text to the logical start or end of the input. Follows the text direction.

**Search.value** `string | number | readonly string[]`

The value of the input. Use when controlled.

### Dropdown.Header

**Header.render** `ReactElement\<unknown, string | JSXElementConstructor\<any\>\> | ComponentRenderFn\<HTMLProps, \{\}\>`

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.

### Dropdown.Title

**Title.className** `string | ((state: PopoverTitleState) =\> string | undefined)`

CSS class applied to the element, or a function that
returns a class based on the component's state.

**Title.render** `ReactElement\<unknown, string | JSXElementConstructor\<any\>\> | ComponentRenderFn\<HTMLProps, PopoverTitleState\>`

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.

**Title.style** `CSSProperties | ((state: PopoverTitleState) =\> CSSProperties | undefined)`

Style applied to the element, or a function that
returns a style object based on the component's state.

### Dropdown.Close

**Close.aria-label** `string` *required*

Accessible name of the close control. Required because the default control only shows an icon.

**Close.className** `string | ((state: PopoverCloseState) =\> string | undefined)`

CSS class applied to the element, or a function that
returns a class based on the component's state.

**Close.nativeButton** `boolean` (default: true)

Whether the component renders a native `<button>` element when replacing it
via the `render` prop.
Set to `false` if the rendered element is not a button (for example, `<div>`).

**Close.render** `ReactElement\<unknown, string | JSXElementConstructor\<any\>\> | ComponentRenderFn\<HTMLProps, PopoverCloseState\>`

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.

**Close.style** `CSSProperties | ((state: PopoverCloseState) =\> CSSProperties | undefined)`

Style applied to the element, or a function that
returns a style object based on the component's state.

### Dropdown.Page

**Page.id** `string` *required*

Identifier matched by `defaultPage`, the `page` prop of actions, and `goToPage`. The page renders only while it is current.

**Page.type** `"menu" | "panel" | "picker"`

Interaction model while the page is shown. Defaults to the root `type`.

### Dropdown.Back

**Back.className** `string`

CSS class applied to the row.

**Back.color** `"danger" | "neutral"`

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

**Back.description** `ReactNode`

Supporting text, placed according to `descriptionPlacement`.

**Back.descriptionPlacement** `"below" | "end" | "inline"`

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

**Back.endIcon** `ReactNode`

Icon rendered after the content.

**Back.focusableWhenDisabled** `boolean` (default: false)

Whether the button should be focusable when disabled.

**Back.hasSubmenu** `boolean`

Shows a chevron indicating that the item opens a submenu.

**Back.nativeButton** `boolean` (default: true when render is omitted; false otherwise)

Whether the component renders a native `<button>` element when replacing it
via the `render` prop.
Set to `false` if the rendered element is not a button (for example, `<div>`).

**Back.render** `ReactElement\<unknown, string | JSXElementConstructor\<any\>\>`

Element rendered as the row instead of a native button. Custom components must forward the supplied props and ref.

**Back.shortcut** `ShortcutDefinition`

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

**Back.shortcutJoinLabel** `string`

Text between sequential shortcut steps. Defaults to `then`.

**Back.startIcon** `ReactNode`

Icon rendered before the content.

**Back.style** `CSSProperties`

Inline styles applied to the row.

### Dropdown.Submenu

**Submenu.defaultOpen** `boolean`

Whether the popup is initially open when uncontrolled.

**Submenu.defaultPage** `string`

ID of the `Page` shown when the popup opens. Closing the popup resets the page history to it. Defaults to `root`.

**Submenu.multiple** `boolean`

Default for standalone options. Use `SelectionGroup.multiple` for independently owned selection values.

**Submenu.onOpenChange** `((open: boolean) =\> void)`

Called with the next open state when the popup opens or closes.

**Submenu.open** `boolean`

Whether the popup is open. Use with `onOpenChange` to control it.

**Submenu.type** `"menu" | "panel" | "picker"` (default: menu)

Interaction model: `menu` for commands and links, `picker` for search and selectable options, or `panel` for forms. It sets the ARIA roles, initial focus, and keyboard navigation.

### Dropdown.SubmenuTrigger

**SubmenuTrigger.className** `string`

CSS class applied to the row.

**SubmenuTrigger.closeDelay** `number`

Delay in milliseconds before a submenu opened on hover closes. Requires `openOnHover`. Defaults to `0`.

**SubmenuTrigger.color** `"danger" | "neutral"`

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

**SubmenuTrigger.delay** `number`

Delay in milliseconds before the submenu opens on hover. Requires `openOnHover`. Defaults to `300`.

**SubmenuTrigger.description** `ReactNode`

Supporting text, placed according to `descriptionPlacement`.

**SubmenuTrigger.descriptionPlacement** `"below" | "end" | "inline"`

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

**SubmenuTrigger.endIcon** `ReactNode`

Icon rendered after the content.

**SubmenuTrigger.focusableWhenDisabled** `boolean` (default: false)

Whether the button should be focusable when disabled.

**SubmenuTrigger.hasSubmenu** `boolean` (default: true)

Shows a chevron indicating that the item opens a submenu.

**SubmenuTrigger.nativeButton** `boolean` (default: true when render is omitted; false otherwise)

Whether the component renders a native `<button>` element when replacing it
via the `render` prop.
Set to `false` if the rendered element is not a button (for example, `<div>`).

**SubmenuTrigger.openOnHover** `boolean` (default: true)

Also opens the submenu when the row is hovered.

**SubmenuTrigger.render** `ReactElement\<unknown, string | JSXElementConstructor\<any\>\>`

Element rendered as the row instead of a native button. Custom components must forward the supplied props and ref.

**SubmenuTrigger.shortcut** `ShortcutDefinition`

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

**SubmenuTrigger.shortcutJoinLabel** `string`

Text between sequential shortcut steps. Defaults to `then`.

**SubmenuTrigger.startIcon** `ReactNode`

Icon rendered before the content.

**SubmenuTrigger.style** `CSSProperties`

Inline styles applied to the row.

### Dropdown.Section

**Section.columns** `number`

Number of grid columns. Sets the grid layout and enables horizontal arrow navigation and vertical movement by row.

**Section.label** `ReactNode`

Heading displayed above the rows. It also names the group for assistive technologies.

**Section.scrollable** `boolean`

Caps the section height and scrolls its rows. Nest labelled sections inside it to scroll them as one list.

### Dropdown.Separator

**Separator.className** `string`

Class applied to the separator. Native div attributes and refs are also accepted.

### Dropdown.Loading

**Loading.children** `ReactNode`

Loading message announced as a polite, busy status.

**Loading.className** `string`

Class applied to the status. Native div attributes and refs are also accepted.

### Dropdown.Empty

**Empty.children** `ReactNode`

Empty-state message announced as a polite status.

**Empty.className** `string`

Class applied to the status. Native div attributes and refs are also accepted.


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