settop_component

Button Segmented

Segmented control for selecting options.

Button Segmented Examples

Copy-ready examples with live previews.

Basic usage

Controlled segmented control: you own `value` and update it via `onValueChange`.

Live preview

value: day

Single select (default)

import { useState } from "react";
import Button_segmented from "@/packages/ui/src/_components/buttons_variants/button_segmented/Button_segmented";

export default function Example() {
  const [value, setValue] = useState("day");

  return (
    <Button_segmented
      ariaLabel="Time range"
      value={value}
      onValueChange={setValue}
      items={[
        { id: "day", label: "Day" },
        { id: "week", label: "Week" },
        { id: "month", label: "Month", disabled: true },
      ]}
    />
  );
}

Live preview

value: bold

Multi select

import { useState } from "react";
import Button_segmented from "@/packages/ui/src/_components/buttons_variants/button_segmented/Button_segmented";

export default function Example() {
  const [value, setValue] = useState<string[]>(["bold"]);

  return (
    <Button_segmented
      mode="multi"
      ariaLabel="Text style"
      value={value}
      onValueChange={setValue}
      items={[
        { id: "bold", label: "Bold" },
        { id: "italic", label: "Italic" },
        { id: "underline", label: "Underline" },
      ]}
    />
  );
}

Tone + size

Switch surface tone (light vs solid) and apply size presets.

Live preview

Tone (light vs solid) + size (sm/md/lg)

import { useState } from "react";
import Button_segmented from "@/packages/ui/src/_components/buttons_variants/button_segmented/Button_segmented";
import type { ISegmentedProps } from "@/packages/ui/src/_components/buttons_variants/button_segmented/Button_segmented.type";

type V = ISegmentedProps["value"];

export default function Example() {
  const [tonePick, setTonePick] = useState<V>("light");
  const [sizePick, setSizePick] = useState<V>("md");

  const tone = (tonePick === "solid" ? "solid" : "light") as ISegmentedProps["tone"];

  return (
    <>
      <Button_segmented
        ariaLabel="Surface tone"
        mode="single"
        size="small"
        variant="secondary"
        value={tonePick}
        onValueChange={setTonePick}
        items={[
          { id: "light", label: "Light" },
          { id: "solid", label: "Solid" },
        ]}
      />

      <Button_segmented
        ariaLabel="Size preset"
        mode="single"
        size="medium"
        variant="primary"
        tone={tone}
        value={sizePick}
        onValueChange={setSizePick}
        items={[
          { id: "sm", label: "SM" },
          { id: "md", label: "MD" },
          { id: "lg", label: "LG", disabled: true },
        ]}
      />
    </>
  );
}

Variants

Same value, different visual variants.

Live preview

Tone
primary
secondary
tertiary
success
warning
danger
info

Variants list

import { useState } from "react";
import Button_segmented from "@/packages/ui/src/_components/buttons_variants/button_segmented/Button_segmented";
import type { ISegmentedProps } from "@/packages/ui/src/_components/buttons_variants/button_segmented/Button_segmented.type";

type V = ISegmentedProps["value"];

export default function Example() {
  const [value, setValue] = useState<V>("md");
  const [tonePick, setTonePick] = useState<V>("light");
  const tone = (tonePick === "solid" ? "solid" : "light") as ISegmentedProps["tone"];

  return (
    <>
      <Button_segmented
        ariaLabel="Tone"
        mode="single"
        size="small"
        variant="secondary"
        value={tonePick}
        onValueChange={setTonePick}
        items={[
          { id: "light", label: "Light" },
          { id: "solid", label: "Solid" },
        ]}
      />

      {(["primary", "secondary", "tertiary", "success", "warning", "danger", "info"] as const).map((variant) => (
        <div key={variant} style={{ marginTop: 10 }}>
          <Button_segmented
            ariaLabel={`Variant ${variant}`}
            mode="single"
            size="small"
            variant={variant}
            tone={tone}
            value={value}
            onValueChange={setValue}
            items={[
              { id: "sm", label: "SM" },
              { id: "md", label: "MD" },
              { id: "lg", label: "LG" },
            ]}
          />
        </div>
      ))}
    </>
  );
}

Multi-select with icons

Show an icon only when an item is selected.

Live preview

selected: new, sale

Filters with check icon

import { useState } from "react";
import Icon from "@/packages/ui/src/_components/icon/Icon";
import Button_segmented from "@/packages/ui/src/_components/buttons_variants/button_segmented/Button_segmented";
import type { ISegmentedProps } from "@/packages/ui/src/_components/buttons_variants/button_segmented/Button_segmented.type";

type V = ISegmentedProps["value"];
const has = (v: V, id: string) => Array.isArray(v) && v.includes(id);

export default function Example() {
  const [filters, setFilters] = useState<V>(["new", "sale"]);

  return (
    <Button_segmented
      ariaLabel="Filters"
      mode="multi"
      size="medium"
      variant="success"
      tone="solid"
      value={filters}
      onValueChange={setFilters}
      items={[
        { id: "new", label: "New", icon: has(filters, "new") ? <Icon name="Check" size="small" /> : undefined },
        { id: "sale", label: "Sale", icon: has(filters, "sale") ? <Icon name="Check" size="small" /> : undefined },
        { id: "vip", label: "VIP", icon: has(filters, "vip") ? <Icon name="Check" size="small" /> : undefined },
        { id: "arch", label: "Archived", disabled: true },
      ]}
    />
  );
}

Icon-only items

When you render icons without labels, provide item-level `ariaLabel`.

In `single` mode, the component uses `role='radiogroup'` and each item uses `aria-checked`.

Live preview

view: grid

Icon-only switcher

import { useState } from "react";
import Icon from "@/packages/ui/src/_components/icon/Icon";
import Button_segmented from "@/packages/ui/src/_components/buttons_variants/button_segmented/Button_segmented";
import type { ISegmentedProps } from "@/packages/ui/src/_components/buttons_variants/button_segmented/Button_segmented.type";

type V = ISegmentedProps["value"];

export default function Example() {
  const [view, setView] = useState<V>("grid");

  return (
    <Button_segmented
      ariaLabel="Change view"
      mode="single"
      size="small"
      variant="info"
      value={view}
      onValueChange={setView}
      items={[
        { id: "grid", label: "", icon: <Icon name="Home" size="small" />, ariaLabel: "Grid view" },
        { id: "list", label: "", icon: <Icon name="List" size="small" />, ariaLabel: "List view" },
        { id: "map", label: "", icon: <Icon name="Map" size="small" />, ariaLabel: "Map view" },
      ]}
    />
  );
}

Multi-select mapped to booleans

Useful when your state is not an array, but a set of booleans.

Live preview

wifi=true / bt=false / gps=true

Wi‑Fi / BT / GPS mapped to booleans

import { useMemo, useState } from "react";
import Icon from "@/packages/ui/src/_components/icon/Icon";
import Button_segmented from "@/packages/ui/src/_components/buttons_variants/button_segmented/Button_segmented";
import type { ISegmentedProps } from "@/packages/ui/src/_components/buttons_variants/button_segmented/Button_segmented.type";

type Item = ISegmentedProps["items"][number];

export default function Example() {
  const [wifi, setWifi] = useState(true);
  const [bt, setBt] = useState(false);
  const [gps, setGps] = useState(true);

  const items: Item[] = useMemo(
    () => [
      { id: "wifi", label: "Wi‑Fi", icon: wifi ? <Icon name="Check" size="small" /> : undefined, ariaLabel: "Toggle Wi‑Fi" },
      { id: "bt", label: "BT", icon: bt ? <Icon name="Check" size="small" /> : undefined, ariaLabel: "Toggle Bluetooth" },
      { id: "gps", label: "GPS", icon: gps ? <Icon name="Check" size="small" /> : undefined, ariaLabel: "Toggle GPS" },
    ],
    [wifi, bt, gps]
  );

  return (
    <Button_segmented
      ariaLabel="Quick toggles"
      mode="multi"
      variant="warning"
      value={[...(wifi ? ["wifi"] : []), ...(bt ? ["bt"] : []), ...(gps ? ["gps"] : [])]}
      onValueChange={(next) => {
        const arr = Array.isArray(next) ? next : [];
        setWifi(arr.includes("wifi"));
        setBt(arr.includes("bt"));
        setGps(arr.includes("gps"));
      }}
      items={items}
    />
  );
}

Full width + long labels

Stretch the control to the container width and verify ellipsis behavior.

Live preview

fullWidth + long labels

import { useState } from "react";
import Button_segmented from "@/packages/ui/src/_components/buttons_variants/button_segmented/Button_segmented";

export default function Example() {
  const [value, setValue] = useState("archive");

  return (
    <div style={{ maxWidth: 520 }}>
      <Button_segmented
        ariaLabel="Long labels"
        mode="single"
        fullWidth
        size="large"
        variant="danger"
        tone="solid"
        value={value}
        onValueChange={setValue}
        items={[
          { id: "delete", label: "Delete current selection (danger)" },
          { id: "archive", label: "Archive for later review" },
          { id: "restore", label: "Restore (disabled)", disabled: true },
        ]}
      />
    </div>
  );
}

On this page

Button Segmented Props

Button Segmented — Props
PropTypeRequiredDefaultDescription
itemsArray<{ id: string; label?: string; icon?: ReactNode; disabled?: boolean; ariaLabel?: string }>YesItems rendered as segmented buttons.
mode"single" | "multi"No"single"Selection mode. In single, only one item can be selected. In multi, multiple can be toggled on/off.
valuestring | string[]YesControlled value. Use string for mode='single', and string[] for mode='multi'.
onValueChange(next: string | string[]) => voidYesCalled when selection changes. Payload depends on mode.
ariaLabelstringNoAccessible label for the group container (aria-label).
size"small" | "medium" | "large"No"medium"Size preset for the segmented control and each inner Button.
variant"primary" | "secondary" | "tertiary" | "success" | "warning" | "danger" | "info"No"primary"Visual variant applied to the root.
tone"light" | "solid"No"light"Surface tone. solid adds a modifier class; light adds none.
fullWidthbooleanNofalseMakes the control stretch to full width (CSS class).
classNamestringNoExtra classes for the root container.