Sophic Interface Systems
Components

View Switch

Switch between views of one card or page; a Segmented Control when there is room, a chip Select when there is not.

Past performance

Showing annualized returns.

Past performance

Showing annualized returns.

Picks one view of a surface: Annualized / Trailing, Holdings / Sectors / Countries, document type. With room it is a Segmented Control; in a narrow card or toolbar it becomes a chip Select with the same options and the same accessible name.

It responds to the width of its container, not the screen. A Section Card header is a container, so the same card collapses on a phone and in a narrow sidebar alike. The rules for card headers live in Responsive Behaviour.

Keep option labels short. The card title already names the subject, so "Annualized" reads better than "Annualized returns" and fits more widths.

Usage

import { SectionCard, ViewSwitch } from "@sophic/portal-ui";

const VIEWS = [
  { value: "annualized", label: "Annualized" },
  { value: "trailing", label: "Trailing" },
] as const;

<SectionCard
  title="Past performance"
  actions={
    <ViewSwitch
      label="Past performance"
      items={VIEWS}
      value={view}
      onValueChange={setView}
      className="ml-auto"
    />
  }
>
  {view === "annualized" ? <AnnualPlot /> : <TrailingPlot />}
</SectionCard>;

Outside a Section Card, make the row that holds it a container:

<div className="@container flex items-center justify-between gap-3">
  <ViewSwitch
    label="Document type"
    items={CATEGORIES}
    value={category}
    onValueChange={setCategory}
    collapseBelow="xl"
    align="start"
  />
  <SearchButton />
</div>

Props

PropTypeDescription
items{ value, label }[]Two to four views.
valuestringSelected view. Controlled only.
onValueChange(value) => voidCalled with one of the item values.
labelstringAccessible name for both forms.
collapseBelow"md" | "lg" | "xl"Container width below which it becomes a chip Select: 28, 32 or 36rem. Default lg.
align"start" | "end"Edge the Select menu lines up with. Default end.
classNamestringPlacement only (ml-auto).

Changelog

  • 6 October 2026 — New. Replaces hand-paired Select and Segmented Control swaps. Full notes

On this page