Vertical Tabs
NavigationVertically oriented tab navigation.
Preview
General settings panel content.
Usage
example.jsx
import { VerticalTabs, VerticalTabsList, VerticalTabsTrigger, VerticalTabsContent } from "@/components/ui/vertical-tabs";
export default function Example() {
return <VerticalTabs />;
}Source Code
Copy this file into components/ui/vertical-tabs.jsx in your project.
vertical-tabs.jsx
"use client";
import { forwardRef, createContext, useContext, useState } from "react";
import { cn } from "@/lib/utils";
const VTabsContext = createContext({ value: "", onChange: () => {} });
const VerticalTabs = forwardRef(({ className, value: cv, defaultValue = "", onValueChange, children, ...props }, ref) => {
const [uv, setUv] = useState(defaultValue);
const value = cv !== undefined ? cv : uv;
const onChange = (v) => { setUv(v); onValueChange?.(v); };
return (
<VTabsContext.Provider value={{ value, onChange }}>
<div ref={ref} className={cn("flex gap-4", className)} {...props}>{children}</div>
</VTabsContext.Provider>
);
});
VerticalTabs.displayName = "VerticalTabs";
const VerticalTabsList = forwardRef(({ className, ...props }, ref) => (
<div ref={ref} role="tablist" aria-orientation="vertical" className={cn("flex w-48 flex-col gap-1 border-r pr-4", className)} {...props} />
));
VerticalTabsList.displayName = "VerticalTabsList";
const VerticalTabsTrigger = forwardRef(({ className, value, ...props }, ref) => {
const ctx = useContext(VTabsContext);
return (
<button ref={ref} role="tab" aria-selected={ctx.value === value} onClick={() => ctx.onChange(value)}
className={cn("w-full rounded-md px-3 py-2 text-left text-sm font-medium transition-colors",
ctx.value === value ? "bg-accent text-foreground" : "text-muted-foreground hover:bg-accent/50 hover:text-foreground",
className
)}
{...props}
/>
);
});
VerticalTabsTrigger.displayName = "VerticalTabsTrigger";
const VerticalTabsContent = forwardRef(({ className, value, ...props }, ref) => {
const ctx = useContext(VTabsContext);
if (ctx.value !== value) return null;
return <div ref={ref} role="tabpanel" className={cn("flex-1", className)} {...props} />;
});
VerticalTabsContent.displayName = "VerticalTabsContent";
export { VerticalTabs, VerticalTabsList, VerticalTabsTrigger, VerticalTabsContent };
Quick Install
Make sure you have the cn() utility set up. It requires clsx and tailwind-merge.
npm install clsx tailwind-merge