Tab Select

A modern React component that displays an animated tab switcher with a smooth visual indicator for the current selection. It’s perfect for navigation bars or section pickers with beautiful, theme-aware transitions.

This component was inspired by various design systems’ high-contrast, tactile tab selectors.


Live Preview


Installation

You can install the TabSelect component with the following CLI command, or copy the implementation manually:

typescript-icon
1npx shadcn@latest add http://localhost:3000/r/tab-select.json

Import

To use the TabSelect component, import it in your code:

typescript-icon
1import TabSelect from '@/components/TabSelect';

Props

The TabSelect component accepts the following props:

PropTypeDefaultDescriptionRequired
tabsstring[]-Array of tab labels.Yes
activeTabstring-Optional controlled value for the current active tab.No
setActiveTab(tab: string) => void-Function to set the active tab (for controlled usage). Internal state will be used if not provided.No
classNamestring-Class name for the overall tab group container.No
tabClassNamestring-Class name for each tab button.No
gapstring | number"2rem"Spacing between tabs.No
typescript-icon
1
2type TabSelectProps = {
3  tabs: string[];
4  activeTab?: string;
5  setActiveTab?: React.Dispatch<React.SetStateAction<string>> | ((tab: string) => void);
6  className?: string;
7  tabClassName?: string;
8  gap?: string | number;
9};
10

Example usage

Basic usage

typescript-icon
1<TabSelect tabs={['Home', 'Components', 'Pricing']} />

Controlled (with external state)

typescript-icon
1
2const [tab, setTab] = useState('Home');
3<TabSelect
4  tabs={['Home', 'Components', 'Pricing']}
5  activeTab={tab}
6  setActiveTab={setTab}
7/>
8

Custom tab spacing and class names

typescript-icon
1<TabSelect
2  tabs={['Overview', 'Features', 'Pricing', 'FAQ']}
3  gap="1.5rem"
4  className="bg-blue-50 dark:bg-neutral-900"
5  tabClassName="text-base"
6/>

Features

  • Animated: Beautiful, performant animated tab indicator with smooth transitions.
  • Type-safe: All props are fully typed.
  • Customizable: Change gap, color, or add your own class names via props.
  • Supports controlled/uncontrolled state: Easily integrate with application state or let it manage itself.
  • Theme-aware: Automatically adapts to light and dark modes.

Customization

  • Use the gap prop to control distance between tabs.
  • Pass your own className or tabClassName for custom visual appearance.
  • Use controlled mode (activeTab and setActiveTab) if you want to fully manage selected tab from parent state logic.

Troubleshooting

  • The tabs prop is required and must be a non-empty array of strings.
  • For controlled usage, pass both activeTab and setActiveTab.
  • Make sure your project includes the required utility helper (cn from your utilities).
  • Double-check that tab labels are unique (as they’re used as keys).