Skip to content

CdsMenu

Меню всплывает рядом с элементом-активатором и показывает список действий или разделов: «ещё» в строке таблицы, меню пользователя в шапке, контекстное меню по правому клику. Позиционируется само — разворачивается в сторону свободного места и держится у активатора при скролле.

Storybook GitLab Figma
Покрытие тестами: 87% — частичное покрытие
API в спеках
56 / 56 пропсы, события, слоты и exposed, у которых есть тест
Тест-кейсы
51 юнит · 8 браузерных
Известные баги
5 зафиксированы тестом it.fails
Покрытие кода
87% строк · 83.8% ветвей замер v4.0.0-alpha.13
A11y (axe)
7 рекомендаций в 12 историях замер v4.0.0-alpha.11

Для выбора значения в форме возьмите CdsSelect — оно останется видимым и попадёт в отправку. Короткая подсказка при наведении — CdsTooltip, а диалог, требующий ответа, — CdsModal. Содержимое меню обычно собирают из CdsList.

Внутри меню работает CdsOverlay: он считает координаты, переворачивает панель, когда до края экрана не хватает места, и пересчитывает позицию при скролле. Поэтому пропсы позиционирования и открытия у меню общие с оверлеем.

Вариации ​

Активаторы ​

Меню открывает элемент-активатор — задать его можно тремя способами:

  1. Через слот activator — пропсы из слота (v-bind="props") вешают на элемент обработчики и aria-атрибуты. Способ по умолчанию: активатор виден рядом с меню.
  2. Через родителя — activator="parent" берёт элемент, внутри которого лежит CdsMenu. Удобно, когда активатор уже собран и его не хочется оборачивать.
  3. Через селектор — activator="#id" связывает меню с любым элементом страницы, даже далёким по разметке.
Sandbox Storybook

Способ открытия ​

По умолчанию меню открывается кликом. Проп open-on-hover переводит его на наведение — так ведут себя навигационные меню; клик тогда панель не открывает. Задержки open-delay и close-delay (300 и 250 мс) не дают меню мигать, когда курсор проходит мимо. Вместе с open-on-hover включается и открытие по фокусу — отключите его :open-on-focus="false", если меню должно реагировать только на мышь.

Sandbox Storybook

Положение ​

Проп location задаёт, с какой стороны от активатора появится меню: bottom по умолчанию, top, end, bottom end — сторона и выравнивание. Если места не хватает, меню само перевернётся к противоположному краю. Расстояние до активатора настраивает offset, а viewport-margin — минимальный отступ от края экрана.

Sandbox Storybook

Размеры ​

Ширина меню равна ширине содержимого. Пропсы min-width, max-width и max-height задают рамки: минимальная ширина не даёт панели схлопнуться на коротких пунктах, а ограниченная высота включает прокрутку вместо меню во весь экран.

Sandbox Storybook

Закрытие ​

Меню закрывается кликом по содержимому, кликом мимо и клавишей Esc. Проп :close-on-content-click="false" оставляет панель открытой — это нужно, когда внутри чекбоксы, поля или несколько шагов подряд. Проп persistent игнорирует клик мимо и Esc: тогда закрыть меню можно только своей кнопкой через v-model.

Sandbox Storybook

Вложенные меню ​

Меню можно вкладывать друг в друга: каждый пункт списка становится активатором (activator="parent") для дочернего CdsMenu с пропом submenu — он смещает панель вбок и переводит навигацию на стрелки влево-вправо. Раскрытие по наведению включает open-on-hover, а :open-on-focus="false" не даёт подменю раскрываться при переходе по табу.

Sandbox Storybook

Анимация ​

Проп transition меняет анимацию появления панели.

Sandbox Storybook

Слоты ​

СлотОписание
activatorЭлемент, открывающий меню. Пропсы слота (props) вешают на него обработчики
defaultСодержимое панели. Обычно CdsList, CdsCard или CdsSurface

Рекомендации ​

Сценарии использования ​

Действия над записью ​

Редкие действия над строкой таблицы или карточкой собирают в меню за кнопкой «⋮»: строка остаётся чистой, а действия не соревнуются с главной кнопкой. location="bottom end" прижимает панель к правому краю активатора, slim у списка убирает лишние отступы, а aria-label называет, к какой записи относится меню.

Sandbox Storybook

Контекстное меню ​

Меню можно открыть в точке клика: обработчик contextmenu кладёт координаты курсора в target, а показом управляет v-model — активатор здесь не нужен. Новый клик двигает открытую панель на новое место. Анимация по умолчанию рассчитана на активатор-элемент, поэтому меню по координатам задайте css-анимацию — например, transition="scale-transition".

Sandbox Storybook

Меню в шапке ​

В шапке приложения меню решает две задачи: раскрывает разделы навигации и собирает всё про аккаунт за аватаром. Активатор пользовательского меню — CdsAvatar в кнопке с aria-label, location="bottom end" прижимает панель к правому краю, а min-width не даёт ей прыгать по ширине. Первый пункт списка показывает, чей это аккаунт, CdsListItemDivider отбивает разделы от выхода.

Sandbox Storybook

Фильтр с несколькими значениями ​

Когда внутри меню выбирают несколько значений, панель не должна закрываться на первом же клике: :close-on-content-click="false" оставляет её открытой, а v-model даёт закрыть меню кнопкой «Применить». Выбор копится в черновике и применяется целиком — до нажатия кнопки список записей не меняется.

Sandbox Storybook

API ​

Пропсы

ИмяТипПо умолчаниюОписание
activator(string & {}) | Element | "parent" | ComponentPublicInstance | undefined—Элемент, который будет активировать компонент
activatorPropsRecord<string, any> | undefined{}Свойства для элемента активатора
attachstring | boolean | Element | undefined—Указывает, в какой элемент DOM следует переместить содержимое overlay. Может быть прямой ссылкой на элемент, строкой querySelector или значением true для отключения перемещения. По умолчанию используется элемент body. Как правило, не рекомендуется изменять это свойство, за исключением крайних случаев: алгоритм позиционирования по умолчанию должен справляться с большинством сценариев лучше, чем это возможно без перемещения, и может возникнуть непредвиденное поведение, если меню окажется дочерним элементом своего активатора.
captureFocusboolean | undefinedtrueВозвращает фокус внутрь контента, если он ушёл за его пределы — например, по Tab с конца страницы. Клик мышью фокус не перехватывает.
closeDelaystring | number | undefined250Время ожидания в миллисекундах перед закрытием компонента. Работает только с параметром open-on-hover.
closeOnBackboolean | undefinedtrueЗакрывает содержимое оверлея при нажатии кнопки «Назад» в браузере или вызове $router.back(), отменяя исходную навигацию. persistent оверлеи отменяют навигацию и анимируются так, как будто по ним щелкнули за пределами оверлея, вместо того чтобы закрываться.
closeOnContentClickboolean | undefinedtrueСкрыть компонент по клику на контент
containedboolean | undefined—Ограничивает размер компонента и сетки в соответствии с его смещенным родительским элементом. Подразумевает использование свойств absolute и attach. (Примечание: родительский элемент должен иметь свойство position: relative.)
contentClassany—Применяет пользовательский класс к отдельному элементу. Это удобно, поскольку содержимое перемещается в начало компонента cds-app (если не указан параметр attach) и не может быть выделено с помощью классов, переданных непосредственно в компонент.
contentPropsany—Применяет кастомные свойства (props) к перемещаемому контенту
disabledboolean | null | undefinednullЗаблокированное состояние
eagerboolean | undefined—Принудительно рендерит содержимое компонента при его использовании. Это полезно, если у вас есть контент, который не отображается в DOM, но который необходимо проиндексировать для SEO.
heightstring | number | undefined—Высота компонента
idstring | undefined—Уникальный идентификатор для связывания меню с его активатором. Если не указано, будет сгенерирован автоматически.
locationAnchor | undefined'bottom'Указывает точку привязки для позиционирования компонента с использованием ориентиров для выравнивания по горизонтали, по вертикали или по обоим направлениям
locationStrategy"static" | "connected" | LocationStrategyFunction | undefined'connected'Определяет способ позиционирования содержимого оверлея. По умолчанию используется значение static, при котором содержимое центрируется в контейнере. Используйте connected для привязки к элементу-активатору.
maxHeightstring | number | undefined—Максимальная высота компонента
maxWidthstring | number | undefined—Максимальная ширина компонента
minHeightstring | number | undefined—Минимальная высота компонента
minWidthstring | number | undefined—Минимальная ширина компонента
modelValueboolean | undefined—Значение компонента v-model. Если компонент поддерживает свойство multiple, по умолчанию используется пустой массив.
noClickAnimationboolean | undefined—Отключает эффект bounce при нажатии за пределами элемента контента при использовании атрибута persistent.
offsetstring | number | number[] | undefined4Увеличивает расстояние до цели. Если передать два числа, второе значение смещает анкер вбок и в сторону от цели.
opacitystring | number | undefined—Прозрачность элемента «scrim». Применяется только в том случае, если св-во scrim=true.
openDelaystring | number | undefined300Время ожидания в миллисекундах перед открытием компонента. Работает только с параметром open-on-hover.
openOnClickboolean | undefined—Показать компонент по клику на активатор
openOnFocusboolean | undefined—Показать компонент по фокусу на активатор
openOnHoverboolean | undefined—Показать компонент по наведению на активатор
originAnchor | "auto" | "overlap" | undefined'auto'Устанавливает точку привязки для содержимого наложения, которая выравнивается по точке привязки «location» на объекте-цели. При значении «auto» используется противоположная сторона точки «location». При значении «overlap» используется та же точка привязки, в результате чего наложение перекрывает объект-цель. Также задает значение CSS-свойства transform-origin для transitions enter/leave.
persistentboolean | undefined—Клик за пределами элемента или нажатие клавиши Esc не приведет к его закрытию.
retainFocusboolean | undefined—Замыкает Tab-навигацию внутри контента: с последнего фокусируемого элемента фокус переходит на первый и наоборот.
scrimstring | boolean | undefinedfalseФон при активации overlay. Принимает значения true/false для включения фона и строку для определения цвета.
scrollStrategy"none" | "close" | "block" | "reposition" | ScrollStrategyFunction | undefined'none'Стратегия, применяемая при активации компонента и прокрутке страницы пользователем.
stickToTargetboolean | undefined—Позволяет контенту наложения выходить за пределы экрана при прокрутке.
submenuboolean | undefined—Открывает/закрывает меню с помощью клавиш со стрелками left/right, а не up/down (для вложенных меню).
target(string & {}) | Element | "parent" | ComponentPublicInstance | "cursor" | [x: number, y: number] | undefined—Если для параметра locationStrategy задано значение «connected», необходимо указать элемент или массив координат x, y, относительно которых должен располагаться оверлей. По умолчанию в качестве такого элемента используется элемент-активатор.
themestring | undefined—Тема компонента
transitionstring | boolean | (TransitionProps & { component?: Component | undefined; }) | { component: Component; } | null | undefined{ component: CdsModalTransition }Анимация перехода
viewportMarginstring | number | undefined12Устанавливает пользовательские viewport margin для содержимого наложения
widthstring | number | undefined—Ширина компонента
zIndexstring | number | undefined2000Значение z-index для компонента.

События

ИмяТипОписание
afterEnter[]Сработало после завершения анимации открытия меню
afterLeave[]Сработало после завершения анимации закрытия меню
update:modelValue[value: boolean]Сработало при открытии или закрытии меню. Передаёт новое состояние видимости

Слоты

ИмяТипОписание
activator{ isActive: boolean; props: Record<string, any>; targetRef: TemplateRef; }Слот для элемента, который будет выступать в роли активатора для оверлея.
default{ isActive: Ref<boolean, boolean>; }Слот для контента оверлея.

Exposed

ИмяТипОписание
activatorElHTMLElement | undefinedDOM-элемент активатора.
activatorRefTemplateRefTemplate ref для назначения активатора вручную.
animateClick() => voidЗапускает bounce-анимацию контента — как при клике мимо persistent-оверлея.
contentElHTMLElement | undefinedDOM-элемент контента оверлея.
globalTopbooleanЯвляется ли оверлей верхним в глобальном стеке открытых оверлеев.
rootElHTMLElement | undefinedКорневой DOM-элемент оверлея.
scrimElHTMLElement | undefinedDOM-элемент подложки (scrim), затемняющей страницу.
targetElHTMLElement | undefinedDOM-элемент цели позиционирования.
targetRefTemplateRefTemplate ref для назначения цели позиционирования вручную.
updateLocation((e: Event) => void) | undefinedПересчитывает позицию контента относительно цели.