Segmented Control

Single-choice segmented selector for switching modes, views, or filters. Install Segmented Control from the VLLNT UI registry with the shadcn CLI.

Report a bug

Single-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.ai/r/segmented-control.json

Source

"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.

Dependencies

  • @vllnt/ui@^0.3.0