Tabs
NavigationHorizontal tabbed content switcher.
Preview
Manage your account settings and preferences.
Usage
example.jsx
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";
export default function Example() {
return <Tabs />;
}Source Code
Copy this file into components/ui/tabs.jsx in your project.
tabs.jsx
"use client";
import { forwardRef, createContext, useContext, useState } from "react";
import { cn } from "@/lib/utils";
const TabsContext = createContext({ value: "", onChange: () => {} });
const Tabs = forwardRef(({ className, value: controlledValue, defaultValue = "", onValueChange, children, ...props }, ref) => {
const [uncontrolled, setUncontrolled] = useState(defaultValue);
const value = controlledValue !== undefined ? controlledValue : uncontrolled;
const onChange = (v) => { setUncontrolled(v); onValueChange?.(v); };
return (
<TabsContext.Provider value={{ value, onChange }}>
<div ref={ref} className={cn(className)} {...props}>{children}</div>
</TabsContext.Provider>
);
});
Tabs.displayName = "Tabs";
const TabsList = forwardRef(({ className, ...props }, ref) => (
<div ref={ref} role="tablist" className={cn("inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground", className)} {...props} />
));
TabsList.displayName = "TabsList";
const TabsTrigger = forwardRef(({ className, value, ...props }, ref) => {
const ctx = useContext(TabsContext);
return (
<button ref={ref} role="tab" aria-selected={ctx.value === value} onClick={() => ctx.onChange(value)}
className={cn("inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
ctx.value === value ? "bg-background text-foreground shadow-sm" : "hover:bg-background/50 hover:text-foreground",
className
)}
{...props}
/>
);
});
TabsTrigger.displayName = "TabsTrigger";
const TabsContent = forwardRef(({ className, value, ...props }, ref) => {
const ctx = useContext(TabsContext);
if (ctx.value !== value) return null;
return (
<div ref={ref} role="tabpanel" className={cn("mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", className)} {...props} />
);
});
TabsContent.displayName = "TabsContent";
export { Tabs, TabsList, TabsTrigger, TabsContent };
Quick Install
Make sure you have the cn() utility set up. It requires clsx and tailwind-merge.
npm install clsx tailwind-merge