oscript-ui
oscript-ui

Вкладки

Вкладки переключают соседние виды одного объекта: описание, редакции, связи. Каждая вкладка — отдельная страница со своим адресом, а полоса — обычный список ссылок, поэтому вкладку можно открыть в новом окне, отправить ссылкой и вернуть кнопкой «назад».

Когда использовать#

  • У объекта несколько видов одного уровня, и человек переходит между ними туда и обратно.
  • Каждый вид достаточно велик, чтобы занять свою страницу: список редакций, журнал, связи.
  • Видов немного — от двух до пяти-шести, и подпись каждого укладывается в одно-два слова.

Не берите вкладки для разделов, которых много или которые вложены друг в друга, — для этого есть дерево разделов. Шаги, которые проходят по порядку, показывает проводник, а длинный список по страницам — пагинация.

Полоса вкладок#

Это основные вкладки Material 3: подпись шрифтом title-small, под активной вкладкой — индикатор цвета primary толщиной 3 пикселя со скруглёнными верхними углами. Активную вкладку отмечает сервер полем Активна; панель содержимого под полосой рисует сам контроллер страницы.

Вкладки страницы объекта

Вкладки = Новый Массив(); Вкладки.Добавить(Новый Структура("Подпись, Адрес, Активна", "Описание", "/документы/отчёт", Истина)); Вкладки.Добавить(Новый Структура("Подпись, Адрес, Счётчик", "Редакции", "/документы/отчёт/редакции", 12)); Вкладки.Добавить(Новый Структура("Подпись, Адрес", "Связи", "/документы/отчёт/связи")); HTML = Набор.Табы().Отрисовать(Новый Структура("Вкладки, Заголовок", Вкладки, "Разделы объекта"));

Счётчик печатается плашкой рядом с подписью: сколько записей ждёт на той вкладке. У активной вкладки плашка залита цветом primary.

В дереве холста полоса собирается словами: вкладки — дети узла, каждая Кит.Вкладка(Подпись, Адрес) со словами Активна, Иконка, Счётчик (см. Язык узлов).

Узлом холста — словами

HTML = Кит.Табы( Кит.Вкладка("Обзор", "/о").Активна(), Кит.Вкладка("Версии", "/в").Счётчик(4)).Заголовок("Разделы проекта").Рендер();

С иконками#

Иконка стоит перед подписью и повторяет её смысл. Ставьте иконки всем вкладкам полосы или никому: половина значков выглядит как недосмотр.

Иконка и подпись

Вкладки = Новый Массив(); Вкладки.Добавить(Новый Структура("Подпись, Адрес, Иконка, Активна", "Настройки", "/пулы/основной", "шестерёнка", Истина)); Вкладки.Добавить(Новый Структура("Подпись, Адрес, Иконка, Счётчик", "История", "/пулы/основной/история", "история", 4)); Вкладки.Добавить(Новый Структура("Подпись, Адрес, Иконка", "Ключи", "/пулы/основной/ключи", "ключ")); HTML = Набор.Табы().Отрисовать(Новый Структура("Вкладки, Заголовок", Вкладки, "Разделы пула"));

Индикатор едет между страницами#

Каждая вкладка — отдельный документ, и всё же индикатор не прыгает, а скользит со старой вкладки на новую, как у Tabs в MUI. Это делает переход между документами (View Transitions): скрипт кита oscript-ui.js называет индикатор именем перехода, когда человек уходит по вкладке того же ряда, а лист кита задаёт ему кривую и длительность движения Material. Сама страница меняется сразу, без наплыва: движется только индикатор.

Браузер без View Transitions и страница без скрипта просто открывают новую вкладку с уже подчёркнутым индикатором — работает всё, кроме скольжения. Переход по чужой ссылке, не из полосы, остаётся обычным: индикатор путешествует, только если человек пришёл вкладкой.

Вкладки дома настроек#

Значение Класс = «настройки» снимает у полосы верхний отступ: так вкладки встают вплотную под шапку секции в доме настроек. Другие значения класса компонент отбрасывает — в атрибут class попадает только известное.

Полоса в доме настроек

Вкладки = Новый Массив(); Вкладки.Добавить(Новый Структура("Подпись, Адрес, Активна", "Общие", "/настройки", Истина)); Вкладки.Добавить(Новый Структура("Подпись, Адрес", "Доступ", "/настройки/доступ")); HTML = Набор.Табы().Отрисовать(Новый Структура("Вкладки, Класс, Заголовок", Вкладки, "настройки", "Разделы настроек"));

Пустая полоса и вкладка без адреса#

Пустой список вкладок не печатает ничего: полоса из одной рамки ничего не переключает.

Пустой список — ничего

этот вызов не печатает ничего

HTML = Набор.Табы().Отрисовать(Новый Структура("Вкладки", Новый Массив()));

Вкладка без Адреса — ошибка разработчика, и кит отказывается её печатать: такую вкладку нельзя ни открыть ссылкой, ни вернуть «назад». Адрес с опасной схемой (javascript:) вкладку не роняет: она остаётся видна, но перестаёт быть ссылкой.

Вкладка без адреса — исключение с объяснением

Вкладки = Новый Массив(); Вкладки.Добавить(Новый Структура("Подпись, Адрес, Активна", "Описание", "/документы/отчёт", Истина)); Вкладки.Добавить(Новый Структура("Подпись", "Связи")); Попытка HTML = Набор.Табы().Отрисовать(Новый Структура("Вкладки", Вкладки)); Исключение HTML = Набор.Тост().Отрисовать(Новый Структура("Текст, Вид", ИнформацияОбОшибке().Описание, "ошибка")); КонецПопытки;

Гайдлайны#

ДелайтеВкладки — соседние виды одного объекта, подписи короткие
Код
Вкладки = Новый Массив();
Вкладки.Добавить(Новый Структура("Подпись, Адрес, Активна", "Описание", "/о", Истина));
Вкладки.Добавить(Новый Структура("Подпись, Адрес", "Редакции", "/о/редакции"));
Вкладки.Добавить(Новый Структура("Подпись, Адрес", "Связи", "/о/связи"));
HTML = Набор.Табы().Отрисовать(Новый Структура("Вкладки", Вкладки));
Не делайтеВкладки вместо шагов мастера: порядок не читается, пропустить шаг легко
Код
Вкладки = Новый Массив();
Вкладки.Добавить(Новый Структура("Подпись, Адрес, Активна", "Шаг 1. Учётная запись", "/мастер/1", Истина));
Вкладки.Добавить(Новый Структура("Подпись, Адрес", "Шаг 2. Ключ", "/мастер/2"));
Вкладки.Добавить(Новый Структура("Подпись, Адрес", "Шаг 3. Документ", "/мастер/3"));
HTML = Набор.Табы().Отрисовать(Новый Структура("Вкладки", Вкладки));
ДелайтеНесколько вкладок умещаются в один ряд
Код
Вкладки = Новый Массив();
Вкладки.Добавить(Новый Структура("Подпись, Адрес, Активна", "Обзор", "/п", Истина));
Вкладки.Добавить(Новый Структура("Подпись, Адрес, Счётчик", "Версии", "/п/версии", 8));
Вкладки.Добавить(Новый Структура("Подпись, Адрес", "Доступ", "/п/доступ"));
HTML = Набор.Табы().Отрисовать(Новый Структура("Вкладки", Вкладки));
Не делайтеДесяток вкладок: ряд переносится, и индикатор теряется
Код
Вкладки = Новый Массив();
Для Каждого Подпись Из СтрРазделить("Обзор,Версии,Доступ,Ключи,Журнал,Метки,Вебхуки,Квоты,Связи,Экспорт", ",") Цикл
	Вкладки.Добавить(Новый Структура("Подпись, Адрес, Активна", Подпись, "/п/" + Подпись, Подпись = "Обзор"));
КонецЦикла;
HTML = Набор.Табы().Отрисовать(Новый Структура("Вкладки", Вкладки));
ДелайтеАктивна ровно одна вкладка — та, что открыта
Код
Вкладки = Новый Массив();
Вкладки.Добавить(Новый Структура("Подпись, Адрес", "Описание", "/о"));
Вкладки.Добавить(Новый Структура("Подпись, Адрес, Активна", "Редакции", "/о/редакции", Истина));
HTML = Набор.Табы().Отрисовать(Новый Структура("Вкладки", Вкладки));
Не делайтеДве активные вкладки: человек не понимает, где он
Код
Вкладки = Новый Массив();
Вкладки.Добавить(Новый Структура("Подпись, Адрес, Активна", "Описание", "/о", Истина));
Вкладки.Добавить(Новый Структура("Подпись, Адрес, Активна", "Редакции", "/о/редакции", Истина));
HTML = Набор.Табы().Отрисовать(Новый Структура("Вкладки", Вкладки));

Доступность#

  • Полоса печатается <nav> с aria-label: по умолчанию «Разделы страницы», своё имя задаёт поле Заголовок. Назовите полосу, если на странице есть другая навигация.
  • Активная вкладка несёт aria-current="page", остальные — ничего: значение "false" скринридеры читают по-разному, а отсутствие атрибута однозначно.
  • Вкладки — ссылки, а не role="tab": каждая ведёт на свою страницу, и клавиатура ходит по ним табуляцией, как по любым ссылкам.
  • Иконка вкладки декоративна (aria-hidden), имя вкладки — её подпись. Счётчик читается числом после подписи, поэтому выбирайте подпись, с которой число понятно («Редакции 12»).
  • Фокус с клавиатуры виден всегда; рябь от нажатия скрипт не показывает, если в системе включено «уменьшить движение».

Узлом холста#

На холсте полоса вкладок — узел рода «вкладки». Его кладут под шапку объекта, перед содержимым активной вкладки.

Вкладки узлом дерева

HTML = Кит.Табы( Кит.Вкладка("Описание", "/документы/отчёт").Активна(), Кит.Вкладка("Редакции", "/документы/отчёт/редакции").Счётчик(12), Кит.Вкладка("Связи", "/документы/отчёт/связи")).Рендер();

Модель#

Структура ниже — прежний вид модели; в дереве холста вкладки — узлы Кит.Вкладка, а поля полосы и вкладок пишут слова. Слова для поля Класс нет: полосу дома настроек печатают прежней моделью.

Табы.Отрисовать()src/Классы/компоненты/Табы.os

Отрисовывает полосу вкладок.

Параметры:
 Модель - Структура - Вкладки (массив структур: Подпись, Адрес — ОБЯЗАТЕЛЕН, Активна,
          Иконка, Счётчик), Заголовок (aria-label, "Разделы страницы"), Класс.

Возвращаемое значение:
 Строка - фрагмент <nav class="tabs"> либо "" для пустого списка. Кидается
          исключением, если у вкладки нет Адреса.

Табы.НормализованныйКласс()src/Классы/компоненты/Табы.os

Приводит дополнительный класс контейнера к allowlist: значение из модели попадает
в CSS-класс.

Параметры:
 Класс - Произвольный - класс из модели.

Возвращаемое значение:
 Строка - "tabs--settings" либо "" для чужого значения.

Кит.Табы()src/Классы/холст/Кит.os

Полоса вкладок страницы объекта: каждая вкладка своим адресом. Вкладки — дети узла,
узлы Кит.Вкладка. Слова: Заголовок (доступное имя полосы).

Параметры:
 Р1…Р8 - ЭлементЭкрана, Структура - (необязательные) вкладки; Структура первым
         аргументом — прежний вид модели с полем Вкладки.

Возвращаемое значение:
 ЭлементЭкрана

Кит.Вкладка()src/Классы/холст/Кит.os

Вкладка полосы Кит.Табы. Печатается только внутри неё. Слова: Активна, Иконка, Счётчик.

Параметры:
 Подпись - Строка - название вкладки.
 Адрес   - Строка - адрес её страницы (обязателен).

Возвращаемое значение:
 ЭлементЭкрана