Сегментный переключатель — Button Group
с appearance="segmented": утопленная дорожка на заливке контейнера, сегменты
без рамок и плашка под выбранным. Он выбирает ровно одно значение из
нескольких — период отчёта, вид списка, фильтр, тему оформления — и сразу
применяет его. Это тот же <sf-button-group>: группа переключателей
(radiogroup) с одной остановкой Tab, стрелками, событием change и
методами select() и clear(). Меняется только вид.
Когда брать
Задача
Что взять
Одно значение из двух–пяти коротких вариантов, которое сразу меняет вид или данные на той же странице
сегментный переключатель
То же, но варианты должны выглядеть как обычные кнопки в общем контуре
Сегментный переключатель — не вкладки: панелей содержимого у него нет, и
выбранный вариант не связан с областью страницы. Что показать после выбора,
решает страница по событию change.
Переключатель темы
Атрибут theme-switch превращает группу в готовый переключатель темы:
HTML
<divclass="flex flex-col gap-3 items-cross-start"data-theme-demo>
<divclass="flex flex-wrap items-cross-center gap-2">
<sf-button-groupappearance="segmented"theme-switchsize="1/2"></sf-button-group>
<sf-buttonsize="1/2"appearance="outline"scheme="on-surface"text="Войти"></sf-button>
<sf-buttonsize="1/2"text="Начать"></sf-button>
</div>
<pclass="m-0 text-1/2"role="status"data-theme-result>Выбор темы: как в системе</p>
</div>
JavaScript
// Переключатель сам вызывает SF.Loader.setTheme; событие change приходит,// когда тема уже сменилась.constnames= {system: 'как в системе', light: 'светлая', dark: 'тёмная'};
document.querySelectorAll('[data-theme-demo]').forEach((demo) => {
constresult= demo.querySelector('[data-theme-result]');
demo.addEventListener('change', (event) => {
if (event.target.localName !=='sf-button-group') return;
result.textContent =`Выбор темы: ${names[event.detail.value] ??event.detail.value}`;
});
});
Группа сама рисует три пункта только с иконками: «Как в системе»
(system), «Светлая» (light) и «Тёмная» (dark). Подписи и имя группы
(«Тема») берутся на языке страницы; aria-label на группе заменяет имя.
items не нужен.
Выбран пункт предпочтения темы (SF.Loader.themePreference), а не
нарисованной темы: «Как в системе» остаётся выбранным и тогда, когда
система тёмная.
Выбор вызывает SF.Loader.setTheme('system' | 'light' | 'dark'): Loader
сохраняет выбор и ставит theme-dark или theme-light на <html>.
change приходит, когда тема уже сменилась.
Переключатель следует за темой, изменённой в другом месте: другим
переключателем, кнопкой .sf-theme-button или вызовом
SF.Loader.setTheme (событие sf-theme-change).
Без Loader или при SF_BOOT_CONFIG.theme === false выбор не меняется.
Остальные атрибуты группы работают: size, spacing, plate,
radius, scheme.
Переключатель стоит в одном ряду с кнопками: его дорожка равна по высоте
sf-button того же размера, поэтому в шапке сайта его ставят рядом с
кнопками без подгонки отступов.
Размеры
size берёт ту же лестницу, что кнопки: дорожка равна по высоте кнопке того
же size и spacing. Сегменты внутри на шаг меньше — это компактный шаг
кнопки, а отступ дорожки равен разнице.
Значения — для экрана шире 60rem. На узком экране кнопки ниже, и группа
меняется вместе с ними, оставаясь вровень с кнопками. На размере 1/3
компактная кнопка не меньше обычной, поэтому отступ дорожки — 2px.
spacing="compact" опускает и кнопку, и дорожку на компактную ступень.
Скругление
radius работает как у sf-button: default, square или rounded; без
атрибута — обычный радиус элементов. Плашка — сегмент размером с кнопку,
поэтому она получает радиус кнопки с тем же значением, а у дорожки радиус
больше на её отступ, и углы концентричны: при rounded и плашка, и дорожка —
«таблетки», при square плашка прямоугольная, а дорожка скруглена на
величину отступа.
/* Радиус плашки и сегмента; дорожка получает его плюс свой отступ. */.segmented-soft-corners {
--sf-button-group-radius: 0.75rem;
}
Свой радиус задаёт переменная --sf-button-group-radius — углы сегмента и
плашки; дорожка получает его плюс отступ. Атрибут radius важнее переменной.
Плашка и схема
plate выбирает плашку под выбранным сегментом: scheme (по умолчанию) —
заливка цвета схемы, raised — приподнятая нейтральная поверхность с тенью.
scheme — primary (по умолчанию), secondary или on-surface — красит
плашку scheme.
Плашку raised берите там, где цвет схемы уже занят главным действием
страницы, а переключатель второстепенен. on-surface — нейтральный выбор без
цвета проекта.
Число в варианте
Поле count выводит число после подписи табличными цифрами — так фильтр
показывает, сколько записей в каждом варианте. Число входит в доступное имя
варианта, а в event.detail.item приходит вместе с подписью.
// Число варианта приходит в event.detail.item вместе с подписью.
document.querySelectorAll('[data-filter-demo]').forEach((demo) => {
constresult= demo.querySelector('[data-filter-result]');
demo.addEventListener('change', (event) => {
if (event.target.localName !=='sf-button-group') return;
result.textContent =`Показано тем: ${event.detail.item?.count??0}`;
});
});
count задаётся только в записи items массивом JSON.
Иконки
Поле icon ставит иконку перед подписью. icon-only оставляет только иконку,
а label становится скрытым доступным именем варианта; без icon флаг не
действует.
Флаг disabled у варианта отключает только его: стрелки его пропускают, а
нажатие не выбирает. Атрибут disabled на <sf-button-group> отключает всю
группу.
HTML
<divclass="flex flex-col gap-3 items-cross-start">
<sf-button-groupappearance="segmented"aria-label="Период, год недоступен"value="m"items='[{"value":"d","label":"День"},{"value":"w","label":"Неделя"},{"value":"m","label":"Месяц"},{"value":"y","label":"Год","disabled":true}]'></sf-button-group>
<sf-button-groupappearance="segmented"disabledaria-label="Период, группа отключена"value="w"items='[{"value":"d","label":"День"},{"value":"w","label":"Неделя"},{"value":"m","label":"Месяц"}]'></sf-button-group>
</div>
Вертикальная раскладка
orientation="vertical" ставит сегменты столбцом и сообщает ориентацию
вспомогательным технологиям; стрелки по обеим осям работают в любой
ориентации.
Прокрутка — запасной выход. Если варианты регулярно не помещаются, сократите
подписи, оставьте иконки или возьмите выпадающий список.
В форме
С атрибутом name группа участвует в форме, как другие Smart-поля:
при отправке форма получает name=value выбранного варианта;
сброс формы (reset) возвращает значение, с которым группа была написана;
группа с disabled в отправку не входит.
Значение несёт скрытое поле <input type="hidden"> рядом с группой.
HTML
<formclass="flex flex-col gap-3 items-cross-start"data-segmented-form>
<sf-button-groupappearance="segmented"name="period"value="w"aria-label="Период"items='[{"value":"d","label":"День"},{"value":"w","label":"Неделя"},{"value":"m","label":"Месяц"}]'></sf-button-group>
<sf-button-groupappearance="segmented"name="format"value="pdf"disabledaria-label="Формат, отключён"items='[{"value":"pdf","label":"PDF"},{"value":"csv","label":"CSV"}]'></sf-button-group>
<divclass="flex flex-wrap gap-2">
<sf-buttonnative-type="submit"text="Отправить"></sf-button>
<sf-buttonnative-type="reset"appearance="outline"scheme="on-surface"text="Сбросить"></sf-button>
</div>
<outputclass="text-1/2"data-form-result>Выберите период и нажмите «Отправить».</output>
</form>
JavaScript
// Форма получает name=value выбранного варианта; отключённая группа в данные// не входит, а сброс возвращает значение, с которым группа была написана.
document.querySelectorAll('[data-segmented-form]').forEach((form) => {
constresult= form.querySelector('[data-form-result]');
form.addEventListener('submit', (event) => {
event.preventDefault();
constdata= [...newFormData(form)].map(([key, value]) =>`${key}=${value}`);
result.textContent =`Отправлено: ${data.join(', ') || 'пусто'}`;
});
form.addEventListener('reset', () => {
// Группа возвращает значение в своём обработчике сброса: читаем после него.setTimeout(() => {
constperiod= form.querySelector('sf-button-group[name="period"]');
result.textContent =`Сброшено: period=${period.value}`;
});
});
});
В примере выберите «Месяц» и нажмите «Отправить»: в данных формы будет
period=m, а отключённой группы format в них нет. «Сбросить» возвращает
period=w.
Клавиатура и событие change
Группа — одна остановка Tab на выбранном варианте. Стрелки, Home и End
переходят по доступным вариантам по кругу и сразу выбирают их. Выбор
отправляет всплывающее событие change; методы select(value) и clear()
меняют выбор из кода и отправляют то же событие.
HTML
<divclass="flex flex-col gap-3 items-cross-start"data-events-demo>
<sf-button-groupappearance="segmented"aria-label="Период"value="w"items='[{"value":"d","label":"День"},{"value":"w","label":"Неделя"},{"value":"m","label":"Месяц"}]'></sf-button-group>
<divclass="flex flex-wrap gap-2">
<sf-buttonsize="1/2"appearance="outline"scheme="on-surface"text="select('m')"data-action="select"></sf-button>
<sf-buttonsize="1/2"appearance="outline"scheme="on-surface"text="clear()"data-action="clear"></sf-button>
</div>
<preclass="m-0 text-1/2"role="status"data-events-log>Нажмите вариант или перейдите к группе клавишей Tab и нажмите стрелку.</pre>
</div>
значение до изменения; пустая строка, если выбора не было
value
новое значение; после clear() — пустая строка
item
данные выбранного варианта: value, label, icon, count, disabled; после clear() — null
component
элемент <sf-button-group>
Повторный выбор текущего варианта и выбор недоступного ничего не меняют.
Группа хранит выбор только в атрибуте value; сохранить его и применить
выбранный вид — задача страницы.
Настройка через CSS-переменные
Вид дорожки, сегментов и плашки настраивают публичные переменные. Их задают
на <sf-button-group> или на любом предке: они наследуются.
Переменная
Что задаёт
--sf-button-group-background-color
заливка дорожки
--sf-button-group-padding
отступ дорожки со всех сторон, он же промежуток между сегментами
<divclass="flex flex-col gap-3 items-cross-start">
<sf-button-groupappearance="segmented"aria-label="Темы, по умолчанию"value="dark"items='[{"value":"all","label":"Все","count":20},{"value":"dark","label":"Тёмные","count":7},{"value":"light","label":"Светлые","count":13}]'></sf-button-group>
<sf-button-groupappearance="segmented"class="segmented-brand"aria-label="Темы, свои переменные"value="dark"items='[{"value":"all","label":"Все","count":20},{"value":"dark","label":"Тёмные","count":7},{"value":"light","label":"Светлые","count":13}]'></sf-button-group>
</div>
CSS
/* Публичные переменные задают на элементе группы или выше: они наследуются. */.segmented-brand {
--sf-button-group-background-color: var(--sf-secondary-container);
--sf-button-group-padding: var(--sf-a2);
--sf-button-group-radius: 999rem;
--sf-button-group-color: var(--sf-on-secondary-container);
--sf-button-group-plate-background-color: var(--sf-secondary);
--sf-button-group-plate-color: var(--sf-on-secondary);
--sf-button-group-count-color: var(--sf-on-secondary-container);
}
Берите роли темы (--sf-secondary-container, --sf-on-secondary и
другие), а не постоянные цвета: тогда переключатель остаётся читаемым в обеих
темах. Подпись невыбранного сегмента должна давать не меньше 4.5:1 на
заливке дорожки. Значения по умолчанию и внутренние переменные — в разделе
Классы и переменные группы кнопок.
Доступность
Группе нужно доступное имя: aria-label на <sf-button-group>. Подписи
вариантов его не заменяют. У переключателя темы имя «Тема» есть по
умолчанию.
Вариант только с иконкой называется своей подписью label: она скрыта
глазу, но читается экранным диктором.
Выбранный вариант отличается не только цветом плашки: у него
aria-checked="true".
Кольцо фокуса рисуется внутри сегмента и не перекрывает соседние.
Невыбранная подпись даёт не меньше 4.5:1 на дорожке над поверхностями от
0 до 3.
См. также
Button Group — тот же компонент в обычном виде и его справочник API.
Smart-вкладки — когда варианты переключают панели содержимого.
Группа кнопок — независимые действия в общем контуре и CSS-переменные группы.