This component no longer exists. It was in ericts-ui’s manifest when we first indexed it and is not there now — the registry served its inventory on 2026-08-15 and this item was not on it. The install command below will fail. It is kept here because a tutorial somewhere still tells people to run it.
Expanding Segmented Tabs
ericts-ui/expanding-segmented-tabsRemovedComponent
A Motion-powered segmented tab list for switching modes or views, with an active tab that expands from icon-only into a label.
Live preview
live · rendered by the registry
Rendered by ericts-ui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://ui.ericts.com/r/expanding-segmented-tabs.jsonSource
1"use client";23import * as React from "react";4import {5 AnimatePresence,6 motion,7 useReducedMotion,8 type Transition,9} from "motion/react";1011import { cn } from "@/lib/utils";1213export type ExpandingSegmentedTabsItem = {14 value: string;15 label: React.ReactNode;16 icon: React.ReactNode;17 disabled?: boolean;18 ariaLabel?: string;19};2021export type ExpandingSegmentedTabsProps = Omit<22 React.ComponentPropsWithoutRef<"div">,23 "defaultValue" | "onChange"24> & {25 items: ExpandingSegmentedTabsItem[];26 value?: string;27 defaultValue?: string;28 onValueChange?: (29 value: string,30 item: ExpandingSegmentedTabsItem,31 ) => void;32 onValueIntent?: (33 value: string,34 item: ExpandingSegmentedTabsItem,35 ) => void;36 /**37 * Preserves the last selected value across unmount/remount for this key, so38 * route-driven mode switches can still animate from the previous tab.39 */40 transitionKey?: string | null;41 listClassName?: string;42 itemClassName?: string;43 activeItemClassName?: string;44 iconClassName?: string;45 labelClassName?: string;46 indicatorClassName?: string;47 "aria-label"?: string;48};4950type FlexTarget = {51 flexGrow: number;52 flexShrink: number;53 flexBasis: string;54};5556const EXPAND_TRANSITION: Transition = {57 duration: 0.28,58 ease: [0.77, 0, 0.175, 1],59};6061const ACTIVE_FLEX: FlexTarget = {62 flexGrow: 1,63 flexShrink: 1,64 flexBasis: "0px",65};6667const INACTIVE_FLEX: FlexTarget = {68 flexGrow: 0,69 flexShrink: 0,70 flexBasis: "2.25rem",71};7273const selectedValueByTransitionKey = new Map<string, string>();7475function getEnabledItems(items: ExpandingSegmentedTabsItem[]) {76 return items.filter((item) => !item.disabled);77}7879function getSelectableValue(80 items: ExpandingSegmentedTabsItem[],81 value: string | undefined,82) {83 const enabledItems = getEnabledItems(items);8485 return enabledItems.some((item) => item.value === value)86 ? value87 : enabledItems[0]?.value;88}8990function getItemByValue(91 items: ExpandingSegmentedTabsItem[],92 value: string,93) {94 return items.find((item) => item.value === value);95}9697export function ExpandingSegmentedTabs({98 items,99 value,100 defaultValue,101 onValueChange,102 onValueIntent,103 transitionKey,104 className,105 listClassName,106 itemClassName,107 activeItemClassName,108 iconClassName,109 labelClassName,110 indicatorClassName,111 "aria-label": ariaLabel = "Options",112 ...props113}: ExpandingSegmentedTabsProps) {114 const shouldReduceMotion = useReducedMotion();115 const isControlled = value !== undefined;116// … truncated
What it pulls in
npm packages
Files it writes
More from ericts-ui
All 43 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Adaptive Draweradaptive-drawer | ericts-ui | Components | Free | 2 deps | |
| Adaptive Switchadaptive-switch | ericts-ui | Components | Free | 2 deps | |
| Check Markcheck-mark | ericts-ui | Components | Free | no deps · 2 files | |
| Context Cursorcontext-cursor | ericts-ui | Components | Free | 1 dep | |
| Copy Buttoncopy-button | ericts-ui | Components | Free | 2 deps | |
| Expandable Dialogexpandable-dialog | ericts-ui | Components | Free | 1 dep | |
| Expandable Panelexpandable-panel | ericts-ui | Components | Free | 2 deps | |
| Expandable Segmented Tabsexpandable-segmented-tabs | ericts-ui | Components | Free | 1 dep |
