Segmented Control
Single-choice segmented selector for switching modes, views, or filters. Install Segmented Control from the VLLNT UI registry with the shadcn CLI.
What it is and when to use
Segmented Control is a single-choice selector that lets users switch between a small set of options, such as modes, views, or filters. Built on Radix Toggle Group, it renders a SegmentedControl with SegmentedControlItem children, exposes value, defaultValue, and onValueChange for controlled or uncontrolled use, and supports sm, default, and lg sizes. The active segment is highlighted, individual items can be disabled, and keyboard focus is handled for you.
FormSingle-choice segmented selector for switching modes, views, or filters. Part of the form family in VLLNT UI, it ships as a machine-readable registry entry — copy the source directly into your app with the shadcn CLI and own it, no runtime dependency on a component library.
Preview
Switch between light and dark to inspect the embedded Storybook preview.
Installation
Add Segmented Control to your project with the shadcn CLI. The source lands in your codebase, ready to adapt:
pnpm dlx shadcn@latest add https://ui.vllnt.com/r/segmented-control.jsonSource
"use client";
import * as React from "react";
import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "../../lib/utils";
const segmentedControlVariants = cva(
"inline-flex w-full items-center rounded-lg bg-muted p-1 text-muted-foreground",
{
defaultVariants: {
size: "default",
},
variants: {
size: {
default: "min-h-10",
lg: "min-h-11",
sm: "min-h-9",
},
},
},
);
const segmentedControlItemVariants = cva(
"inline-flex flex-1 items-center justify-center rounded-md px-3 text-sm font-medium whitespace-nowrap transition-all outline-none ring-offset-background focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-background data-[state=on]:text-foreground data-[state=on]:shadow-sm",
{
defaultVariants: {
size: "default",
},
variants: {
size: {
default: "min-h-8",
lg: "min-h-9 px-4",
sm: "min-h-7 px-2.5 text-xs",
},
},
},
);
export type SegmentedControlProps = Omit<
React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Root>,
"defaultValue" | "onValueChange" | "type" | "value"
> &
VariantProps<typeof segmentedControlVariants> & {
defaultValue?: string;
onValueChange?: (value: string) => void;
value?: string;
};
export type SegmentedControlItemProps = React.ComponentPropsWithoutRef<
typeof ToggleGroupPrimitive.Item
> &
VariantProps<typeof segmentedControlItemVariants>;
const SegmentedControl = ({
className,
ref,
size,
...props
}: SegmentedControlProps & {
ref?: React.Ref<React.ComponentRef<typeof ToggleGroupPrimitive.Root>>;
}) => (
<ToggleGroupPrimitive.Root
className={cn(segmentedControlVariants({ size }), className)}
ref={ref}
type="single"
{...props}
/>
);
SegmentedControl.displayName = "SegmentedControl";
const SegmentedControlItem = ({
className,
ref,
size,
...props
}: SegmentedControlItemProps & {
ref?: React.Ref<React.ComponentRef<typeof ToggleGroupPrimitive.Item>>;
}) => (
<ToggleGroupPrimitive.Item
className={cn(segmentedControlItemVariants({ size }), className)}
ref={ref}
{...props}
/>
);
SegmentedControlItem.displayName = "SegmentedControlItem";
export {
SegmentedControl,
SegmentedControlItem,
segmentedControlItemVariants,
segmentedControlVariants,
};
Stories
Explore every variant and state in the interactive Storybook:
Preview
Switch between light and dark to inspect the embedded Storybook preview.
FAQ
- What is Segmented Control?
- Segmented Control is a React single-select component from VLLNT UI, built on Radix Toggle Group. It groups related options into one control so users pick exactly one, ideal for toggling views, modes, or filters.
- How do I add Segmented Control?
- Run `pnpm dlx shadcn@latest add https://ui.vllnt.com/r/segmented-control.json` to install Segmented Control via the shadcn CLI. The component source is copied into your project so you can restyle the segments.
- Is Segmented Control controlled or uncontrolled?
- Both. Use value with onValueChange for a controlled component, or defaultValue for uncontrolled state. It allows only a single active option and offers sm, default, and lg size variants.