Системное меню
Системное меню — это всплывающий список пунктов, который открывается рядом с кнопкой или другим элементом страницы. В меню можно добавить секции, заголовок с иконкой и вложенные меню. Пункты поддерживают счетчики, дополнительные иконки и разные варианты оформления.
Компонент используют для контекстных действий над объектом или выбора одного варианта из короткого списка. Меню закрывается по клику вне области, по Esc и после клика по пункту, если это не переопределено в параметрах.
В Bitrix Framework за системное меню отвечает расширение ui.system.menu. В нем доступны класс Menu и константы для оформления пунктов, секций и заголовка. Для Vue-компонента используется отдельное расширение ui.system.menu.vue.
Подключить расширение
Если вы подключаете класс Menu из PHP, загрузите расширение ui.system.menu.
\Bitrix\Main\UI\Extension::load('ui.system.menu');
Если вы работаете в модульном JavaScript, импортируйте класс и константы из ui.system.menu.
import { Menu, MenuItemDesign } from 'ui.system.menu';
Для иконок в пунктах меню используйте значения из ui.icon-set.api.core.
import { Outline } from 'ui.icon-set.api.core';
Создать меню
Чтобы создать меню, выполните основные действия:
-
Создайте экземпляр
Menu. -
Передайте массив
itemsс пунктами меню. -
Вызовите
show(bindElement), чтобы открыть меню рядом с элементом страницы.
import { Menu, MenuItemDesign } from 'ui.system.menu';
const button = document.getElementById('actions-button');
const menu = new Menu({
items: [
{
id: 'edit',
title: 'Редактировать',
onClick: () => {
console.log('Редактировать объект');
},
},
{
id: 'delete',
title: 'Удалить',
design: MenuItemDesign.Alert,
onClick: () => {
console.log('Удалить объект');
},
},
],
});
menu.show(button);
Передать параметры меню
Конструктор Menu принимает объект с параметрами меню. Если вызвать show() без аргумента, компонент откроет меню рядом с bindElement.
bindElement — это DOM-элемент, рядом с которым нужно открыть меню. Обычно его получают из страницы через document.getElementById() или из Vue-шаблона через ref.
-
items— массив пунктов меню. -
sections— массив секций. Секция группирует пункты по значениюsectionCode. -
richHeader— крупный заголовок в верхней части меню. Объект может содержатьdesign,title,subtitle,iconиonClick. -
closeOnItemClick— закрывать меню после клика по пункту без вложенного меню. По умолчаниюtrue.
Настроить пункт меню
Пункт меню задается объектом внутри массива items.
-
id— идентификатор пункта. Используется, чтобы отличать пункты при обновлении списка. -
title— основной текст пункта. -
subtitle— дополнительный текст под названием. -
onClick— обработчик клика по пункту. -
design— оформление пункта, значение изMenuItemDesign. -
sectionCode— код секции, в которой нужно вывести пункт. -
icon— иконка справа, например значение изOutline. -
svg— SVG-элемент справа. Используется вместоicon, еслиiconне передан. -
badgeText— короткий текстовый бейдж рядом с названием. Объект содержитtitleи необязательныйcolor. -
isSelected— состояние выбора. Значениеtrueпоказывает галочку,falseоставляет место под галочку пустым. -
isLocked— значок замка перед названием. -
counter— параметры счетчика изui.cnt. Объект передается в компонентCounter. Для простого счетчика передайтеvalue. -
extraIcon— дополнительная иконка справа. Объект содержитicon,onClickиisSelected. -
subMenu— параметры вложенного меню. Объект принимает те же параметры, что иMenu. -
closeOnSubItemClick— закрывать родительское меню после клика по пункту вложенного меню. По умолчаниюtrue. -
uiButtonOptions— параметры кнопки изui.buttons. Объект передается в компонентButton. Для простого пункта-кнопки передайтеtextиonclick.
import { Menu, MenuItemDesign, MenuSectionDesign } from 'ui.system.menu';
import { Outline } from 'ui.icon-set.api.core';
const targetElement = document.getElementById('menu-button');
const createItem = ({ id, subtitle, design, extraIconSelected = true }) => ({
id,
title: 'Название',
subtitle,
design,
badgeText: {
title: 'новое',
},
isLocked: true,
isSelected: true,
extraIcon: {
icon: Outline.CHEVRON_RIGHT_L,
isSelected: extraIconSelected,
},
counter: {
value: 1,
},
icon: Outline.PERSON,
});
const menu = new Menu({
sections: [
{
code: 'accent',
title: 'Секция с акцентом',
design: MenuSectionDesign.Accent,
},
{
code: 'default',
title: 'Обычная секция',
},
],
items: [
createItem({
id: 'default',
subtitle: 'Подназвание (Default)',
extraIconSelected: false,
}),
createItem({
id: 'accent-1',
subtitle: 'Подназвание (Accent1)',
design: MenuItemDesign.Accent1,
}),
createItem({
id: 'accent-2',
subtitle: 'Подназвание (Accent2)',
design: MenuItemDesign.Accent2,
}),
createItem({
id: 'alert',
subtitle: 'Подназвание (Alert)',
design: MenuItemDesign.Alert,
}),
createItem({
id: 'bitrix-gpt',
subtitle: 'Подназвание (BitrixGPT)',
design: MenuItemDesign.Copilot,
}),
createItem({
id: 'disabled',
subtitle: 'Подназвание (Disabled)',
design: MenuItemDesign.Disabled,
extraIconSelected: false,
}),
{
id: 'recommended',
title: 'Название',
subtitle: 'Подназвание',
badgeText: {
title: 'рекомендуется',
color: '#0B66FF',
},
},
{
id: 'delete',
title: 'Удалить',
icon: Outline.TRASHCAN,
design: MenuItemDesign.Alert,
},
],
});
menu.show(targetElement);

Выбрать оформление пункта
Оформление меняет цвет текста и служебных иконок пункта. Используйте константы MenuItemDesign, а не строковые значения.
-
MenuItemDesign.Default— обычный пункт без цветового акцента: темный текст и нейтральные служебные иконки. Используется для нейтральных действий. -
MenuItemDesign.Accent1— окрашивает служебные иконки в основной акцентный цвет, но оставляет текст нейтральным. Подходит для действия, которое нужно выделить без усиления текста. -
MenuItemDesign.Accent2— окрашивает текст и служебные иконки в основной акцентный цвет. Подходит для основного или рекомендуемого действия в меню. -
MenuItemDesign.Alert— окрашивает текст и служебные иконки в красный цвет. Используется для опасного или критичного действия, например удаления. -
MenuItemDesign.Copilot— окрашивает текст и служебные иконки в цвета BitrixGPT. Используйте для действий, связанных с BitrixGPT. -
MenuItemDesign.Disabled— окрашивает текст и служебные иконки в приглушенный серый цвет, чтобы показать недоступный пункт.
MenuItemDesign.Disabled меняет оформление пункта и не открывает вложенное меню при наведении. Этот режим не отменяет обработчик onClick. Если пункт не должен выполнять действие, не передавайте ему обработчик или обработайте блокировку в своем коде.
Добавить секции
Секции помогают разделить пункты по группам. У секции должен быть code, а у пункта — такой же sectionCode.
import { Menu, MenuSectionDesign } from 'ui.system.menu';
const menu = new Menu({
sections: [
{
code: 'main',
title: 'Основные действия',
design: MenuSectionDesign.Accent,
},
{
code: 'service',
title: 'Служебные действия',
},
],
items: [
{
id: 'open',
sectionCode: 'main',
title: 'Открыть',
onClick: () => {},
},
{
id: 'copy-link',
sectionCode: 'service',
title: 'Скопировать ссылку',
onClick: () => {},
},
],
});
Пункты без sectionCode выводятся до секций. Если секция указана, но в ней нет пунктов, компонент ее не выводит.
Доступные варианты оформления секции:
-
MenuSectionDesign.Default— обычный заголовок секции: небольшой серый текст и разделитель. -
MenuSectionDesign.Accent— акцентный заголовок секции: текст крупнее и плотнее, разделитель остается нейтральным.
Добавить заголовок меню
Параметр richHeader добавляет верхний блок с крупной иконкой, заголовком, подзаголовком и необязательной иконкой справа.
import { Menu, MenuRichHeaderDesign } from 'ui.system.menu';
import { Outline } from 'ui.icon-set.api.core';
const menu = new Menu({
richHeader: {
design: MenuRichHeaderDesign.Copilot,
title: 'BitrixGPT',
subtitle: 'Помощник',
icon: Outline.CHEVRON_RIGHT_L,
onClick: () => {
console.log('Открыть раздел BitrixGPT');
},
},
items: [
{
id: 'create-text',
title: 'Создать текст',
onClick: () => {},
},
],
});
Доступные варианты оформления:
-
MenuRichHeaderDesign.Default— обычный заголовок с мягким синим фоном, синей иконкой и акцентным цветом текста. -
MenuRichHeaderDesign.Copilot— заголовок в цветах BitrixGPT: фиолетовый фон, фиолетовая иконка и акцентный цвет текста. Используйте для сценариев BitrixGPT.
Если subtitle, icon или onClick не переданы, соответствующая часть заголовка не используется.
Добавить вложенное меню
Чтобы открыть вложенное меню при наведении, передайте в пункт параметр subMenu.
import { Menu } from 'ui.system.menu';
const menu = new Menu({
items: [
{
id: 'move',
title: 'Переместить',
subMenu: {
items: [
{
id: 'move-to-active',
title: 'В активные',
onClick: () => {},
},
{
id: 'move-to-archive',
title: 'В архив',
onClick: () => {},
},
],
},
},
],
});
Если у пункта есть subMenu, клик по нему не закрывает родительское меню — параметр closeOnItemClick его не затрагивает. Закрытие при клике по пункту вложенного меню управляется отдельным параметром closeOnSubItemClick у родительского пункта.
Добавить дополнительную иконку
Клик по extraIcon вызывает только обработчик этой иконки и не вызывает onClick основного пункта.
import { Menu } from 'ui.system.menu';
import { Outline } from 'ui.icon-set.api.core';
const menu = new Menu({
items: [
{
id: 'filter',
title: 'Фильтр',
extraIcon: {
icon: Outline.CHEVRON_RIGHT_L,
isSelected: true,
onClick: () => {
console.log('Настроить фильтр');
},
},
onClick: () => {
console.log('Выбрать фильтр');
},
},
],
});
По умолчанию дополнительная иконка появляется при наведении на пункт. Чтобы показывать ее постоянно, передайте extraIcon.isSelected: true.
Использовать кнопку как пункт меню
Если нужно встроить кнопку из ui.buttons, передайте параметры кнопки в uiButtonOptions.
В этом режиме компонент не использует стандартные параметры пункта title, subtitle, icon, counter и onClick.
Параметры кнопки задают текст и обработчик клика.
import { Menu } from 'ui.system.menu';
const menu = new Menu({
items: [
{
id: 'create',
uiButtonOptions: {
text: 'Создать',
onclick: () => {
console.log('Создать объект');
},
},
},
],
});
Управлять меню
Используйте методы Menu, чтобы обновлять пункты и закрывать уже созданное меню.
-
show(bindElement)— показывает меню рядом с переданным элементом или рядом сbindElementиз параметров. -
close()— закрывает текущее меню. -
destroy()— удаляет меню и вложенные меню. Чтобы снова показать меню послеdestroy(), создайте новый экземплярMenu. -
updateItems(itemsOptions)— заменяет список пунктов в уже созданном меню.
import { Menu } from 'ui.system.menu';
const menu = new Menu({
closeOnItemClick: false,
items: [
{
id: 'draft',
title: 'Черновик',
isSelected: true,
onClick: () => {},
},
],
});
menu.show(document.getElementById('status-button'));
menu.updateItems([
{
id: 'published',
title: 'Опубликовано',
isSelected: true,
onClick: () => {},
},
]);
Использовать Vue-компонент
В расширении ui.system.menu.vue доступен Vue-компонент BMenu. Он принимает options с теми же параметрами, что и класс Menu.
Когда меню закрывается, BMenu вызывает событие close.
Если Vue-компонент используется на странице, загрузите расширение ui.system.menu.vue из PHP.
\Bitrix\Main\UI\Extension::load('ui.system.menu.vue');
В модульном JavaScript импортируйте компонент BMenu.
import { BMenu } from 'ui.system.menu.vue';
export const ActionsMenu = {
components: { BMenu },
data()
{
return {
isMenuShown: false,
};
},
computed: {
menuOptions()
{
return {
bindElement: this.$refs.actionsButton,
items: [
{
id: 'edit',
title: 'Редактировать',
onClick: () => {},
},
],
};
},
},
template: `
<button ref="actionsButton" @click="isMenuShown = true">
Действия
</button>
<BMenu
v-if="isMenuShown"
:options="menuOptions"
@close="isMenuShown = false"
/>
`,
};
Подробнее о работе с Vue в Bitrix Framework читайте в статье Vue.js.