К содержанию

Навигация

Context Menu

<sf-context-menu> — панель с коротким списком действий над объектом: страницей, строкой таблицы, файлом, профилем. Он оформлен как обычное контекстное меню и даёт пунктам роль меню и управление клавиатурой. Пункты задаются данными, а метод openFor открывает меню у кнопки и дальше управляет им сам; для выбора значения в форме берите Dropdown.

Пример

Применение

Стандартное меню

Любое меню действий строится одинаково: пункты передаются данными в свойстве entries, атрибут popup прячет меню до открытия, а toggleFor(кнопка) открывает его у кнопки или закрывает, если оно уже открыто у неё. Выбор пункта приходит событием sf-context-menu-select.

Пункты данными

entries — массив записей; его задают свойством или JSON в атрибуте. Если entries задан, он заменяет items и пункты из разметки. Запись без type — пункт меню:

  • id возвращается в событии выбора, text — подпись;
  • icon — имя иконки Material Symbols перед подписью, caption — вторая строка под подписью;
  • в конце строки стоят value — текущее значение, например выбранный язык, и shortcut — сочетание клавиш; оба только показываются;
  • kind: 'check' или kind: 'radio' делает пункт отмечаемым, checked — его отметка;
  • submenu — массив записей, который открывается сбоку от пункта;
  • danger отмечает опасное действие, disabled — недоступное, current — место, где человек находится;
  • href делает пункт ссылкой, lang — язык, на котором написана подпись;
  • avatar — адрес картинки в начале строки вместо иконки, например логотип сайта или фото человека; без картинки там рисуются инициалы initials.

Другие записи задаются полем type: {type: 'separator'} — разделитель, {type: 'heading', text} — заголовок группы пунктов. Если иконка есть хотя бы у одного пункта, место под иконку остаётся у всех, и подписи начинаются на одной линии.

Открытие у кнопки

openFor(кнопка, options) открывает меню в верхнем слое страницы: его не обрезает прокручиваемый блок и не перекрывает таблица. Меню встаёт под кнопкой по её началу, а у края окна переворачивается вверх или сдвигается; если окно ниже меню, его строки прокручиваются. Подменю открывается сбоку, и его первый пункт стоит на одной линии с пунктом, который его открыл. Ширина меню подстраивается под самый длинный пункт, от нижней границы --sf-e8 до верхней --sf-g2; меню, которому нужно шире, задаёт переменную --sf-context-menu--min-inline-size.

options уточняет открытие: side — сторона кнопки (block-end по умолчанию, block-start, inline-start, inline-end), align — выравнивание по ней (start по умолчанию, center, end), focus — куда встаёт фокус: на первый пункт (first, по умолчанию), на последний (last) или никуда (none). toggleFor(кнопка, options) закрывает меню, открытое у этой кнопки, а иначе открывает его; close() закрывает меню вместе с подменю.

Меню, открытое через openFor, управляет собой само: Escape закрывает текущий уровень, а Tab, нажатие вне меню и выбор пункта закрывают всё меню и возвращают фокус туда, где он был до открытия, а если фокуса нигде не было — на кнопку, у которой меню открывалось. Открытие и закрытие сообщают события sf-context-menu-open и sf-context-menu-close. openFor и toggleFor возвращают Promise<boolean>: дождитесь его, если следующий шаг зависит от того, открылось ли меню.

Выбор пункта

Выбор на любом уровне, в том числе в подменю, приходит одним событием sf-context-menu-select на самом меню. В event.detail — id и запись entry; для отмечаемого пункта checked — отметка, которую пункт просит поставить, для обычного — null. После выбора меню закрывается. Чтобы оно осталось открытым, например в списке с несколькими отметками, отмените событие через preventDefault() или задайте пункту keepOpen: true.

Отметки check и radio хранит приложение: получив событие, оно записывает новое checked и значение value в entries, как в примере выше.

Меню профиля

Меню профиля собирается из тех же записей и ещё трёх типов строк. {type: 'header'} показывает, о ком меню: имя в text, строки под ним в caption (строка или массив строк) и фото avatar; без фото рисуются инициалы из имени или из initials. {type: 'choice'} ставит несколько вариантов options рядом, например тему: выбранный вариант отмечается сразу, меню остаётся открытым, а событие несёт id варианта и group — id строки. keepOpen: false на строке выбора закрывает меню после выбора. {type: 'note'} — пояснение мелким текстом.

Пункт с search: {placeholder, empty} открывает подменю с полем поиска: оно сужает пункты по подписи, второй строке и словам keywords, а empty — текст, когда ничего не найдено. Такое подменю открывается сразу на поле, и мышью, и с клавиатуры.

Поиск на стороне хоста

Если пунктов слишком много, чтобы передать их все, на поиск отвечает хост. Свойство search самого меню ставит поле над строками, а search: {remote: true} отключает поиск по пунктам: на каждый запрос меню поднимает событие sf-context-menu-search с detail.query, а хост записывает найденные пункты в entries. Для подменю то же задаёт search: {remote: true} в записи пункта. Закрытие меню запроса не поднимает.

JavaScript
menu.search = {placeholder: 'Найти сайт', empty: 'Ничего не найдено', remote: true};
menu.addEventListener('sf-context-menu-search', async (event) => {
  menu.entries = await findSites(event.detail.query);
});

Пункты в разметке

Меню без entries показывает пункты, переданные со slot="content": <sf-button>, нативные <button> и <a href>. Обычно берут <sf-button> вида link со схемой on-surface и размером 1/2; держите в одном меню пункты одного размера. Меню выравнивает подписи по началу строки.

Пункты можно передать и данными в свойстве items: каждый элемент массива — {component, props}. Для component: 'sf-button' в props читаются text, type (вид кнопки), scheme, size, iconLeft, iconRight, ariaLabel, disabled и обработчик '@click'. text без пунктов показывает в меню простой текст.

Меню, которым управляет страница

Меню без popup рисуется там, где стоит в разметке, и не открывается и не закрывается само. Показывает его страница — по нажатию кнопки или правой кнопке мыши — и после показа переводит в него фокус методом focus(), дождавшись отрисовки. По Escape и после выбора пункта страница скрывает меню и возвращает фокус на кнопку, которая его открыла. Действие пункта — обычный click на кнопке. Скрывайте обёртку меню: сам <sf-context-menu> не занимает места в раскладке, и атрибут hidden на нём не действует.

JavaScript
const layer = document.querySelector('#file-menu-layer');
const menu = layer.querySelector('sf-context-menu');
const opener = document.querySelector('#file-menu-button');

opener.addEventListener('click', async () => {
  layer.hidden = false;
  opener.setAttribute('aria-expanded', 'true');
  await menu.whenRendered();
  menu.focus();
});

layer.addEventListener('keydown', (event) => {
  if (event.key !== 'Escape') return;
  layer.hidden = true;
  opener.setAttribute('aria-expanded', 'false');
  opener.focus();
});

Размер, ширина и подвал

Меню бывает двух размеров: size="1/2" (по умолчанию) и size="1". Строки меню высотой с поле того же размера; от размера зависят текст, иконки, отступы, поиск и подвал. Подменю берёт размер родительского меню.

Ширину задаёт атрибут width или параметр openFor(кнопка, {width}):

  • content (по умолчанию) — по самой длинной строке, в пределах --sf-context-menu--min-inline-size и --sf-context-menu--max-inline-size;
  • trigger — точно по кнопке, которая открыла меню, как у выбора сайта или меню профиля; длинная строка обрезается многоточием;
  • длина CSS, например 16rem.

Окно с собственным содержимым (slot="content") собирается из тех же частей: .sf-context-menu-top для поиска или заголовка, .sf-context-menu-body для прокручиваемого списка и подвал в slot="footer" с кнопками вроде «Сбросить» и «Применить». Подвал стоит под строками и остаётся на месте, пока список прокручивается; его кнопки делят ширину поровну.

HTML
<sf-context-menu popup size="1/2" aria-label="Настройки">
  <div slot="content" class="sf-context-menu-body">…</div>
  <sf-button slot="footer" size="1/2" appearance="outline" scheme="on-surface" text="Сбросить"></sf-button>
  <sf-button slot="footer" size="1/2" text="Применить"></sf-button>
</sf-context-menu>

Панель с вкладками

Окно с вкладками — настройки списка, фильтр — собирается тем же меню. tabs задаёт вкладки: подписи через |, например "Поля|Вид", или свойство [{id, label}]. active-tab — id или номер выбранной вкладки, closable добавляет в шапку кнопку закрытия.

Шапка — отдельная строка высотой с контрол и шагом отступа над ним: вкладки стоят по её нижнему краю, кнопка закрытия — по центру. Под шапкой одна линия через всю панель, в том числе под кнопкой закрытия; своей линии у вкладок нет. Шапка не прокручивается: прокручивается только содержимое слота content, а подвал в слоте footer остаётся внизу. Ширина у панели своя — восемь контролов или значение width, — поэтому панель не меняет размер при смене вкладки или подписи кнопки в подвале.

Выбор вкладки отправляет событие sf-context-menu-tab с {id, index}, и страница кладёт в content строки этой вкладки. Кнопка закрытия закрывает меню, открытое через openFor; если меню поставила страница, оно отправляет sf-context-menu-close, и закрывает его страница. Строка панели — .sf-context-menu-row: в ней может быть ручка, флажок или кнопка, а подпись .sf-context-menu-row-text занимает остаток и обрезается многоточием.

Пример панели с вкладками

Доступность

  • Меню нужно доступное имя: aria-label на <sf-context-menu>. Подменю получает имя по подписи пункта, который его открыл.
  • Пункты из entries получают роли menuitem, menuitemcheckbox или menuitemradio с aria-checked; пункт с подменю — aria-haspopup и aria-expanded. Заголовок профиля и пояснение — обычный текст, варианты строки выбора — menuitemradio в группе.
  • В порядке Tab остаётся один пункт. Стрелки вверх и вниз переходят по пунктам по кругу, Home и End — к первому и последнему, Enter и Space выбирают пункт. Недоступные и скрытые пункты пропускаются.
  • В меню, открытом через openFor, → открывает подменю, ← и Escape закрывают текущий уровень, Tab закрывает всё меню. Буквы переводят фокус к следующему пункту, подпись которого с них начинается. Варианты строки выбора перебирают стрелки влево и вправо.
  • В подменю с поиском фокус стоит в поле: буквы и боковые стрелки остаются полю, ↓ переходит к пунктам.
  • Кнопка, у которой открыто меню, получает aria-haspopup="menu" и aria-expanded. Меню, которым управляет страница, сообщает состояние через aria-expanded на кнопке силами страницы.
  • Атрибут role со значением, отличным от menu, отключает клавиатурную модель меню: задавайте его, только если пункты — не команды.

Справочник API

Раздел собран из манифеста компонента выпуска ui-106d5901f8c3 и обновляется вместе с выпуском. Чтобы исправить описание, исправьте манифест.

Каждому атрибуту соответствует свойство элемента с тем же именем в camelCase: search-placeholder — searchPlaceholder. Свойство атрибута template называется templateName.

Тег <sf-context-menu>
Назначение Меню действий Framework: пункты данными со значком, подписью, значением, сочетанием клавиш, отметкой, подменю, разделителем и заголовком; openFor() открывает его в верхнем слое с привязкой, клавиатурой, переходом по первой букве и возвратом фокуса. Хост может по-прежнему рисовать свои пункты и сам управлять жизненным циклом.
Контракт smart.context-menu, версия 1.3.0
Поставка выпуск Framework ui-106d5901f8c3
Жизненный цикл экспериментальный: API может меняться между выпусками
Готовность описан: манифест и сценарий есть, продуктовой приёмки нет
Заготовка до прихода кода нет: атрибут data-sf-skeleton не пишется; своего скелетона при загрузке данных нет (Заготовка до прихода кода)

Атрибуты

  • template — string, по умолчанию default.
  • position — string, по умолчанию пусто, значения: пусто, inline-start, inline-start-top, inline-start-bottom, inline-end, inline-end-top, inline-end-bottom, top, top-inline-start, top-inline-end, bottom, bottom-inline-start, bottom-inline-end, start, end, top-start, top-end, bottom-start, bottom-end, left, left-top, left-bottom, right, right-top, right-bottom, top-left, top-center, top-right, bottom-left, bottom-center, bottom-right, left-start, left-end, right-start, right-end, inline-start-start, inline-start-end, inline-end-start, inline-end-end. Устаревший: у меню нет хвоста; значение сохранено ради его класса и ничего не рисует.
  • tooltip — boolean, по умолчанию true. Устаревший: у меню нет хвоста; значение сохранено ради его класса и ничего не рисует.
  • text — string, по умолчанию пусто.
  • aria-label — string, по умолчанию пусто.
  • items — array из object, по умолчанию [].
  • role — string, по умолчанию menu.
  • content-class — string, по умолчанию пусто.
  • root-class — string, по умолчанию пусто.
  • entries — array из object, по умолчанию []. Меню данными (свойством или JSON в атрибуте). См. item_contract. Если задано, заменяет items и слот содержимого.
  • popup — boolean, по умолчанию false. Не рисуется, пока его не откроет openFor(). Меню без этого атрибута рисуется на месте.
  • search — object, по умолчанию null. {placeholder, empty, remote}: поле поиска над строками (задаётся свойством). По умолчанию поиск локальный; с remote: true меню поднимает sf-context-menu-search {query} и показывает пункты, которые задаёт хост. Пункт подменю передаёт его через search.
  • size — string, по умолчанию 1/2, значения: 1/2, 1. Размер меню: строки высотой с поле того же размера, текст, отступы, поиск и подвал. Подменю берёт размер родительского меню.
  • width — string, по умолчанию content. Какой ширины openFor() открывает меню: content — по самой длинной строке, в пределах –sf-context-menu–min-inline-size и –sf-context-menu–max-inline-size; trigger — точно по элементу, который его открыл (длинная строка обрезается многоточием); или длина CSS. openFor(anchor, {width}) переопределяет значение.
  • tabs — string | array, по умолчанию пусто. Панель с вкладками: подписи через | или свойство [{id, label}]. Шапка (вкладки и кнопка закрытия) и подвал не прокручиваются, прокручивается тело; ширина панели постоянна (ступень лестницы размеров или width) и не зависит от содержимого вкладки.
  • active-tab — string, по умолчанию пусто. id или номер выбранной вкладки; хост выводит строки этой вкладки в слот content.
  • closable — boolean, по умолчанию false. Кнопка закрытия в конце шапки панели.

Прежние имена:

Имя Прежнее имя Состояние Убирается после
position="inline-start" position="start" работает, отмечается в SF.deprecations 2026-12-01
position="inline-end" position="end" работает, отмечается в SF.deprecations 2026-12-01
position="top-inline-start" position="top-start" работает, отмечается в SF.deprecations 2026-12-01
position="top-inline-end" position="top-end" работает, отмечается в SF.deprecations 2026-12-01
position="bottom-inline-start" position="bottom-start" работает, отмечается в SF.deprecations 2026-12-01
position="bottom-inline-end" position="bottom-end" работает, отмечается в SF.deprecations 2026-12-01
position="left-top" position="left-start" работает, отмечается в SF.deprecations 2026-12-01
position="left-bottom" position="left-end" работает, отмечается в SF.deprecations 2026-12-01
position="right-top" position="right-start" работает, отмечается в SF.deprecations 2026-12-01
position="right-bottom" position="right-end" работает, отмечается в SF.deprecations 2026-12-01
position="inline-start-top" position="inline-start-start" работает, отмечается в SF.deprecations 2026-12-01
position="inline-start-bottom" position="inline-start-end" работает, отмечается в SF.deprecations 2026-12-01
position="inline-end-top" position="inline-end-start" работает, отмечается в SF.deprecations 2026-12-01
position="inline-end-bottom" position="inline-end-end" работает, отмечается в SF.deprecations 2026-12-01

Методы

  • focus(options?: object) — возвращает null. Переводит фокус на текущий доступный пункт. Хост, который рисует меню сам, ждёт отрисовки и сам отвечает за открытие и закрытие.
  • openFor(anchor: Element, options?: object) — возвращает Promise<boolean>. Открыть рядом с элементом: в верхнем слое, с привязкой через SF.Position с переворотом и сдвигом, фокус на первом пункте (или ‘last’, или ‘none’). Дальше меню управляет собой само: Escape, Tab, нажатие снаружи и выбор пункта закрывают его и возвращают фокус — туда, где он был, или на элемент управления якоря, если фокуса нигде не было.
  • toggleFor(anchor: Element, options?: object) — возвращает Promise<boolean>. Закрывает меню, если оно уже открыто у этого элемента, иначе вызывает openFor().
  • close(options?: object) — возвращает boolean. Закрывает это меню и все подменю.
  • chooseTab(index: number) — возвращает object. Выбирает вкладку по номеру и отправляет sf-context-menu-tab.
  • requestClose() — возвращает boolean. Закрывает меню, открытое самим компонентом; для меню, которое поставил хост, отправляет sf-context-menu-close, чтобы его закрыл хост.

События

Все события приходят на сам элемент и всплывают. Общие события базового элемента перечислены в главе Жизненный цикл → Этапы.

  • sf-context-menu-select — detail: { id?: string|null, entry?: object, checked?: boolean|null, group?: string|null }. Выбран пункт на любом уровне. Отмените событие, чтобы меню осталось открытым.
  • sf-context-menu-open — detail: null. Открыто через openFor(). Всплывает и с composed: true; detail не передаётся.
  • sf-context-menu-close — detail: null. Меню, открытое через openFor(), закрыто. Всплывает и с composed: true; detail не передаётся.
  • sf-context-menu-search — detail: { query?: string }. Запрос поиска, на который отвечает хост (search.remote).
  • sf-context-menu-tab — detail: { id?: string, index?: number }. Выбрана вкладка панели; хост показывает её строки.

Доступность

  • Роль: меню (menu).
  • Доступное имя: обязательно.
  • Клавиши: ArrowDown, ArrowUp, Home, End, ArrowRight, ArrowLeft, Enter, Space, Escape, Tab, поиск по первым буквам.
  • Фокус: Строки из entries получают роли menuitem, menuitemcheckbox или menuitemradio с aria-checked, а подменю — aria-haspopup и aria-expanded; одна перемещаемая остановка Tab. При открытии через openFor() элемент получает aria-haspopup=menu и aria-expanded; Escape закрывает один уровень и возвращает фокус на его строку или элемент; Tab закрывает всю цепочку; буква переводит к следующему пункту, который с неё начинается. Хост, который рисует меню сам, сам отвечает за открытие, закрытие по Escape и Tab и возврат фокуса. Заголовок и заметка — текст. Варианты строки выбора — menuitemradio в группе, их перебирают боковые стрелки. Меню с поиском открывается на поле поиска, которое оставляет себе буквы и боковые стрелки; ArrowDown переходит к строкам.

Минимальная разметка

HTML
<button id="more" type="button">Ещё</button><sf-context-menu id="menu" popup aria-label="Действия"></sf-context-menu><script>menu.entries=[{id:"rename",text:"Переименовать",icon:"edit"},{type:"separator"},{id:"delete",text:"Удалить",icon:"delete",danger:true}];more.onclick=()=>menu.toggleFor(more);</script>

Источник

  • simai/ui@106d5901f8c3b4f23131ce0e7ede5dbd8abfe4f4:distr/smart/context-menu
  • simai/ui@106d5901f8c3b4f23131ce0e7ede5dbd8abfe4f4:distr/rule/rule.json#name=cl-context-menu

См. также

  • Popover — поверхность у кнопки с открытием, закрытием и возвратом фокуса.
  • Dropdown — выбор значения из списка.

Поиск по документации

Введите минимум 2 символа

    Настройки

    Тема
    Размер шрифта
    Ширина страницы