Меню
Меню прячет действия за одной кнопкой: шестерёнкой в строке таблицы или именем вошедшего в шапке. На широком экране панель выпадает у самой кнопки, на телефоне встаёт нижним листом у края окна.
Когда использовать#
- У строки таблицы больше двух действий, и кнопкам рядом с данными не хватает места.
- Действия нужны редко: настройки, права, перенос — а не то, ради чего человек пришёл на экран.
- Учётка в шапке: имя вошедшего, кабинет, выход.
Не берите меню для одного действия — поставьте кнопку. Не прячьте в меню главное действие экрана: его должно быть видно сразу. Навигация инсталляции живёт в едином меню, а не в этом компоненте.
В дереве холста меню собирается словами: подпись позицией, пункты — детьми, учётка и счётчик — словами (см. Язык узлов).
Узлом холста — словами
HTML = Кит.Меню("Меню учётки",
Кит.ПунктМеню("Кабинет", "/кабинет").Иконка("аккаунт"),
Кит.ФормаБезТокена("/выход", Кит.Кнопка("Выйти").Иконка("выход")).Вид("меню"))
.Аккаунт("а.иванова").Рендер();Как оно устроено#
Меню — кнопка-открывашка и панель пунктов при ней. Панель лежит в верхнем слое браузера (атрибут popover), поэтому строка таблицы от неё не растёт, а обёртка прокрутки её не обрезает. Открытие, закрытие щелчком мимо и по Esc, возврат фокуса на кнопку делает сам браузер: скрипта у меню нет.
На широком экране панель висит под кнопкой и растёт влево от её правого края: меню обычно стоит в последней колонке. Кнопка — якорь панели (anchor()); не хватит места снизу или слева — браузер отзеркалит панель. Появляется она из угла, как Grow в MUI.
На телефоне (до 900 пикселей) панель к кнопке не привязана: она выезжает листом от нижнего края окна, с ручкой сверху, затемнением под собой и заголовком — подписью меню. Пункты становятся строками под палец, по 56 пикселей.
Действия строки — шестерёнка открывает панель
Пункты = Новый Массив();
Пункты.Добавить(Новый Структура("Подпись, Адрес, Иконка",
"Настройки", "/настройки", "шестерёнка"));
Пункты.Добавить(Новый Структура("Подпись, Адрес, Иконка",
"Права", "/настройки/доступ", "замок"));
Пункты.Добавить(Новый Структура("HTML", Набор.Кнопка().Отрисовать(
Новый Структура("Подпись, Вариант, Размер",
"Сделать основным", "вторичная", "малый"))));
HTML = Набор.Меню().Отрисовать(Новый Структура("Подпись, Пункты",
"Меню строки «Альфа»", Пункты));Пункты#
Пункт — либо ссылка (Подпись, Адрес, Иконка), либо готовый фрагмент в поле HTML: кнопка окна, форма из одной кнопки, примечание. Пункт без адреса и без HTML пропускается.
Вид пунктов задаёт меню, а не вызывающий. Ссылка, кнопка и форма из одной кнопки выглядят одинаково — строкой списка Material высотой 48 пикселей с иконкой слева, какой бы вариант кнопки ни пришёл. В примере выше «Сделать основным» передан вторичной кнопкой, а в панели стоит такой же строкой, как ссылки.
Действие, которое меняет данные, — форма из одной кнопки. Опасный пункт узнаётся красной подписью и иконкой, а не заливкой: залитая кнопка перекрикивала бы весь список.
Опасный пункт — форма из одной кнопки
Пункты = Новый Массив();
Пункты.Добавить(Новый Структура("Подпись, Адрес, Иконка",
"Скачать выгрузку", "/проекты/альфа/выгрузка", "скачать"));
Токен = "токен-сессии"; // CSRF-токен текущей сессии
Удаление = Кит.Форма("/проекты/альфа/удалить",
Кит.Кнопка("Удалить").Опасная().Иконка("корзина")).Токен(Токен).Вид("меню");
Пункты.Добавить(Новый Структура("HTML", Удаление.Рендер()));
HTML = Набор.Меню().Отрисовать(Новый Структура("Подпись, Пункты",
"Меню проекта «Альфа»", Пункты));Форма с полями внутри меню остаётся маленькой формой: её кнопка не превращается в строку списка.
Несколько меню на странице#
В таблице меню столько же, сколько строк. Идентификатор связи кнопки с панелью кит выдаёт сам, порядковым номером: из данных в него ничего не попадает, и два похожих имени не откроют чужую панель.
Соседнее меню — свой идентификатор
Пункты = Новый Массив();
Пункты.Добавить(Новый Структура("Подпись, Адрес, Иконка",
"Настройки", "/настройки", "шестерёнка"));
Пункты.Добавить(Новый Структура("Подпись, Адрес, Иконка",
"Права", "/настройки/доступ", "замок"));
Пункты.Добавить(Новый Структура("HTML", Набор.Кнопка().Отрисовать(
Новый Структура("Подпись, Вариант, Размер",
"Сделать основным", "вторичная", "малый"))));
HTML = Набор.Меню().Отрисовать(Новый Структура("Подпись, Пункты",
"Меню строки «Бета»", Пункты));Меню учётки#
Задано поле Аккаунт — открывашка печатается учёткой: значок, имя вошедшего и шеврон раскрытия, который переворачивается, пока панель открыта. Без него меню остаётся кнопкой-значком.
Счётчик показывает на кнопке, сколько ждёт человека. Ноль бейджа не печатает. ПодписьСчётчика называет число словами для скринридера и обязательна, когда бейдж есть.
Учётка — имя, счётчик и шеврон раскрытия
Пункты = Новый Массив();
Пункты.Добавить(Новый Структура("Подпись, Адрес, Иконка",
"Кабинет", "/кабинет", "аккаунт"));
Пункты.Добавить(Новый Структура("HTML", Набор.Кнопка().Отрисовать(
Новый Структура("Подпись, Вариант, Размер, Иконка",
"Выйти", "ссылка", "малый", "выход"))));
HTML = Набор.Меню().Отрисовать(Новый Структура(
"Подпись, Аккаунт, Счётчик, ПодписьСчётчика, Пункты",
"Меню учётки", "а.иванова", 3, "3 непрочитанных", Пункты));Иконка открывашки по умолчанию — шестерёнка у меню строки и человечек у учётки. Своя задаётся полем Иконка.
Гайдлайны#
Код
HTML = Набор.Кнопка().Отрисовать(Новый Структура("Подпись, Вариант, Размер, Иконка",
"Настройки", "вторичная", "малый", "шестерёнка"));Код
Пункты = Новый Массив();
Пункты.Добавить(Новый Структура("Подпись, Адрес, Иконка",
"Настройки", "/настройки", "шестерёнка"));
HTML = Набор.Меню().Отрисовать(Новый Структура("Подпись, Пункты",
"Меню строки «Альфа»", Пункты));Код
Пункты = Новый Массив();
Пункты.Добавить(Новый Структура("Подпись, Адрес, Иконка",
"Кабинет", "/кабинет", "аккаунт"));
HTML = Набор.Меню().Отрисовать(Новый Структура("Подпись, Аккаунт, Пункты",
"Меню учётки", "а.иванова", Пункты));Код
Пункты = Новый Массив();
Пункты.Добавить(Новый Структура("Подпись, Адрес, Иконка",
"Кабинет", "/кабинет", "аккаунт"));
HTML = Набор.Меню().Отрисовать(Новый Структура("Подпись, Иконка, Пункты",
"Меню учётки", "аккаунт", Пункты));Код
Пункты = Новый Массив();
Пункты.Добавить(Новый Структура("Подпись, Адрес, Иконка",
"Права", "/проекты/альфа/доступ", "замок"));
Пункты.Добавить(Новый Структура("Подпись, Адрес, Иконка",
"Настройки", "/проекты/альфа/настройки", "шестерёнка"));
HTML = Набор.Меню().Отрисовать(Новый Структура("Подпись, Пункты",
"Действия проекта «Альфа»", Пункты));Код
Пункты = Новый Массив();
Пункты.Добавить(Новый Структура("Подпись, Адрес, Иконка",
"Права", "/проекты/альфа/доступ", "замок"));
Пункты.Добавить(Новый Структура("Подпись, Адрес, Иконка",
"Настройки", "/проекты/альфа/настройки", "шестерёнка"));
HTML = Набор.Меню().Отрисовать(Новый Структура("Подпись, Пункты",
"Меню", Пункты));Доступность#
Подписьобязательна: у кнопки-значка она уходит вaria-label, на телефоне становится заголовком листа. Без неё кит меню не соберёт.- У учётки видимый текст — имя, поэтому подпись меню уходит во всплывающую подсказку: скринридер читает то, что человек видит.
- Состояние «открыто», Esc, щелчок мимо и возврат фокуса на кнопку даёт браузер по связке
popovertarget—popover. - Открывашка — кнопка типа
button: меню внутри формы не отправляет её при открытии. - Пустое меню кит не печатает, а кидает исключение: кнопка, открывающая пустоту, — сломанный экран.
- Браузер без верхнего слоя показывает панель на месте, в потоке, со всеми пунктами — действия остаются доступны.
Узлом холста#
На холсте меню кладут в ячейку таблицы или в шапку объекта. Пункт-ссылка — Кит.ПунктМеню(Подпись, Адрес), любой другой ребёнок (кнопка, форма, примечание) становится пунктом как есть. Учётку задаёт слово .Аккаунт(Имя), бейдж — .Счётчик(Число, Подпись).
Меню узлом дерева
HTML = Кит.Меню("Меню строки «Гамма»",
Кит.ПунктМеню("Настройки", "/настройки").Иконка("шестерёнка"),
Кит.ПунктМеню("Права", "/настройки/доступ").Иконка("замок"),
Кит.Кнопка("Сделать основным").Вторичная().Малая()).Рендер();Модель#
Поля модели — из комментария в исходнике компонента. Структура с полем Пункты — прежний вид модели: в дереве холста пункты — дети узла Кит.Меню, остальные поля пишут его слова.
Кит.Меню()src/Классы/холст/Кит.os
Меню — кнопка-открывашка и панель пунктов при ней. Пункты — дети узла: Кит.ПунктМеню
становится пунктом-ссылкой, любой другой узел (форма, примечание) — пунктом как есть.
Слова: Иконка, Аккаунт, Счётчик(Число, Подпись).
Параметры:
Модель - Строка, Структура - подпись меню (имя кнопки для скринридера); Структура —
прежний вид модели с полем Пункты.
Р1…Р8 - ЭлементЭкрана - (необязательные) пункты.
Возвращаемое значение:
ЭлементЭкранаКит.ПунктМеню()src/Классы/холст/Кит.os
Пункт меню — ссылка в панели Кит.Меню. Печатается только внутри неё. Слова: Иконка. Параметры: Подпись - Строка - что пункт показывает. Адрес - Строка - куда ведёт. Возвращаемое значение: ЭлементЭкрана
Меню.Отрисовать()src/Классы/компоненты/Меню.os
Отрисовывает меню: кнопку-открывашку и её панель.
Параметры:
Модель - Структура - Подпись (обязательна: имя кнопки для скринридера и видимый
заголовок панели там, где она встаёт листом у края окна), Иконка
(по умолчанию "шестерёнка", у меню учётки — "аккаунт"), Аккаунт (имя,
которое кнопка показывает ТЕКСТОМ: с ним открывашка печатается учёткой —
значок, имя и шеврон раскрытия, — а без него остаётся кнопкой-значком),
Счётчик (число на открывашке; ноль и отсутствие бейджа не печатают),
ПодписьСчётчика (чем это число называется в речи; обязательна, когда бейдж
печатается), Пункты (Массив: либо модель кнопки-ссылки — Подпись, Адрес,
Иконка, — либо структура с полем HTML: ДОВЕРЕННЫЙ фрагмент, например форма
или примечание. Пункт без Адреса и без HTML пропускается).
Возвращаемое значение:
Строка - HTML-фрагмент. Кидается исключением, если Подпись пуста либо панель
осталась пустой.