Segmented Control
Switch between views, modes, or filters with Segmented Control, a React single-select toggle built on Radix with size variants. Install via the shadcn CLI.
What it is & 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.
Browse all FormPreview
Switch between light and dark to inspect the embedded Storybook preview.
Installation
pnpm dlx shadcn@latest add https://ui.vllnt.com/r/segmented-control.jsonStorybook
Explore all variants, controls, and accessibility checks in the interactive Storybook playground.
View in Storybook3 stories available:
Code
"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,
};
Frequently asked questions
- 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.