Stepwise UI

Segment

A segmented control for switching between mutually exclusive options - the active indicator slides with a spring. Choose the filled pill or the underline style, and give options a content panel to turn it into a tab group.

Installation

npx stepwise-ui add segment
import { Segment } from '@/components/stepwise/segment'

// Controlled
const [view, setView] = useState('list')
<Segment
  options={[
    { value: 'list',  label: 'List'  },
    { value: 'grid',  label: 'Grid'  },
    { value: 'table', label: 'Table' },
  ]}
  value={view}
  onChange={setView}
/>

// Uncontrolled
<Segment
  options={[{ value: 'day', label: 'Day' }, { value: 'week', label: 'Week' }]}
  defaultValue="week"
  onChange={(v) => console.log(v)}
/>

// Small size
<Segment options={options} value={v} onChange={setV} size="sm" />

// With icons
<Segment
  options={[
    { value: 'sun',  label: 'Light', icon: <SunIcon size={13} /> },
    { value: 'moon', label: 'Dark',  icon: <MoonIcon size={13} /> },
  ]}
  value={theme}
  onChange={setTheme}
/>

Underline

<Segment variant="underline" options={options} value={v} onChange={setV} />

With panels (tabs)

Add a content to each option and Segment renders the active panel below with a blur-fade - a full tab group, no separate component.

A high-level summary of your project health and recent activity.

// give options a `content` panel and Segment becomes a tab group
<Segment
  variant="underline"
  options={[
    { value: 'overview', label: 'Overview', content: <Overview /> },
    { value: 'activity', label: 'Activity', content: <Activity /> },
    { value: 'settings', label: 'Settings', content: <Settings /> },
  ]}
/>

Usage

import { Segment } from '@/components/stepwise/segment'

// Controlled
const [view, setView] = useState('list')
<Segment
  options={[
    { value: 'list',  label: 'List'  },
    { value: 'grid',  label: 'Grid'  },
    { value: 'table', label: 'Table' },
  ]}
  value={view}
  onChange={setView}
/>

// Uncontrolled
<Segment
  options={[{ value: 'day', label: 'Day' }, { value: 'week', label: 'Week' }]}
  defaultValue="week"
  onChange={(v) => console.log(v)}
/>

// Small size
<Segment options={options} value={v} onChange={setV} size="sm" />

// With icons
<Segment
  options={[
    { value: 'sun',  label: 'Light', icon: <SunIcon size={13} /> },
    { value: 'moon', label: 'Dark',  icon: <MoonIcon size={13} /> },
  ]}
  value={theme}
  onChange={setTheme}
/>

Props

PropTypeDescription
options
SegmentOption[]
Array of { value, label, icon?, content? }. content turns it into a tab group.
value
string
Controlled selected value. Pair with onChange.
defaultValue
string
Uncontrolled initial value. Defaults to the first option when omitted.
onChange
(value) => void
Called when the user selects a different option.
variant
"pill" | "underline"
pill → filled sliding pill (default) | underline → sliding underline.
size
"sm" | "md"
sm → 28 px buttons | md → 32 px buttons (default).
className
string
Applied to the wrapper.