Segmented Control
Segmented Control переключает короткие режимы в одной строке. Тон активного сегмента может обозначать include или exclude.
Статус: stable · в системе с 2026-06 · интерактивность: always (всегда)
Когда использовать
- 2–6 коротких взаимоисключающих режимов в одну строку: вид списка, период, фильтр, формат виджета.
- Фильтры «включить/исключить» — тоны
include/exclude(toggle-passer).
Не использовать:
- Множественный выбор.
- Длинные подписи или больше 6 опций: ряд перестаёт читаться одним взглядом и становится Select.
- Навигация между страницами — это ссылки, не контрол.
Альтернативы:
Конструктор
Меняйте свойства Segmented Control, сочетайте их и проверяйте результат в одном живом экземпляре.
Базовый
Сегменты с иконкой-обрамлением; всегда один активен.
Выбрано: none
<script>
import { t } from "$lib/spec/demo-lang.svelte.js";
import SegmentedControl from "$lib/ui/SegmentedControl.svelte";
import Pulse from "phosphor-svelte/lib/Pulse";
let value = $state("none");
const items = [
{ value: "none", label: "None" },
{ value: "one", label: "One" },
{ value: "two", label: "Two" },
{ value: "three", label: "Three" },
];
</script>
<div style="display: grid; gap: var(--sp-2); justify-items: start;">
<SegmentedControl {items} icon={Pulse} bind:value />
<p style="margin: 0; font-size: var(--fs-s);">{t("Выбрано:")} <code>{value}</code></p>
</div>
Toggle-passer
Без сегмента NONE: повторный клик по активному снимает выбор — бегунок гаснет (deselectable).
Выбрано: —
<script>
import { t } from "$lib/spec/demo-lang.svelte.js";
import SegmentedControl from "$lib/ui/SegmentedControl.svelte";
import Pulse from "phosphor-svelte/lib/Pulse";
let value = $state("");
const items = [
{ value: "include", label: "Include", tone: "include" },
{ value: "exclude", label: "Exclude", tone: "exclude" },
];
</script>
<div style="display: grid; gap: var(--sp-2); justify-items: start;">
<SegmentedControl {items} icon={Pulse} deselectable bind:value />
<p style="margin: 0; font-size: var(--fs-s);">{t("Выбрано:")} <code>{value || "—"}</code></p>
</div>
Без иконок
Иконка-обрамление опциональна — без неё остаётся только подпись.
Выбрано: week
<script>
import { t } from "$lib/spec/demo-lang.svelte.js";
import SegmentedControl from "$lib/ui/SegmentedControl.svelte";
let value = $state("week");
const items = [
{ value: "day", label: t("День") },
{ value: "week", label: t("Неделя") },
{ value: "month", label: t("Месяц") },
];
</script>
<div style="display: grid; gap: var(--sp-2); justify-items: start;">
<SegmentedControl {items} bind:value />
<p style="margin: 0; font-size: var(--fs-s);">{t("Выбрано:")} <code>{value}</code></p>
</div>
Короткий
compact: одна плашка с активным значением, клик переводит к следующему — как includeExcludeShort в легаси.
Страны включены
<!--
🟢
Короткий режим (эталон: Vue-легаси includeExcludeShort): в тесной строке
фильтра нет места на два сегмента — плашка показывает только активный,
клик переводит на следующий. Подпись рядом показывает текущее значение.
-->
<script>
import { t } from "$lib/spec/demo-lang.svelte.js";
import SegmentedControl from "$lib/ui/SegmentedControl.svelte";
const items = [
{ value: "include", label: t("Включить"), tone: "include" },
{ value: "exclude", label: t("Исключить"), tone: "exclude" },
];
let value = $state("include");
</script>
<div style="display: flex; align-items: center; gap: var(--sp-2);">
<SegmentedControl compact {items} bind:value />
<span aria-live="polite">{value === "include" ? t("Страны включены") : t("Страны исключены")}</span>
</div>