Components
Tabs
A set of layered sections of content—known as tab panels—that are displayed one at a time.
Loading...
Installation
CLI
npx shadcn@latest add https://exawizards.com/exabase/design/registry/tabs.jsonManual
Copy and paste the following code into your project.
"use client"
import { Tabs as TabsPrimitive } from "@base-ui/react/tabs"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
function Tabs({
className,
orientation = "horizontal",
...props
}: TabsPrimitive.Root.Props) {
return (
<TabsPrimitive.Root
data-slot="tabs"
data-orientation={orientation}
className={cn(
"group/tabs flex gap-2 data-horizontal:flex-col",
className
)}
{...props}
/>
)
}
const tabsListVariants = cva(
"group/tabs-list relative inline-flex w-fit items-center justify-center rounded-lg p-[3px] text-muted-foreground group-data-horizontal/tabs:h-8 group-data-vertical/tabs:h-fit group-data-vertical/tabs:flex-col data-[variant=line]:rounded-none",
{
variants: {
variant: {
default: "bg-muted",
line: "gap-1 bg-transparent",
},
},
defaultVariants: {
variant: "default",
},
}
)
const tabsIndicatorVariants = cva("", {
variants: {
variant: {
default: "rounded-md bg-background shadow-sm dark:bg-foreground/10",
line: "bg-primary-text group-data-horizontal/tabs:bottom-0 group-data-horizontal/tabs:h-0.5 group-data-vertical/tabs:-right-1 group-data-vertical/tabs:w-0.5",
},
},
defaultVariants: {
variant: "default",
},
})
function TabsList({
children,
className,
variant = "default",
...props
}: TabsPrimitive.List.Props & VariantProps<typeof tabsListVariants>) {
return (
<TabsPrimitive.List
data-slot="tabs-list"
data-variant={variant}
className={cn(tabsListVariants({ variant }), className)}
{...props}
>
<TabsPrimitive.Indicator
data-slot="tabs-indicator"
className={cn(
tabsIndicatorVariants({ variant }),
"absolute h-[var(--active-tab-height)] w-[var(--active-tab-width)] transition-all duration-200 ease-in-out group-data-horizontal/tabs:left-0 group-data-horizontal/tabs:translate-x-[var(--active-tab-left)] group-data-vertical/tabs:top-0 group-data-vertical/tabs:translate-y-[var(--active-tab-top)]"
)}
/>
{children}
</TabsPrimitive.List>
)
}
function TabsTrigger({ className, ...props }: TabsPrimitive.Tab.Props) {
return (
<TabsPrimitive.Tab
data-slot="tabs-trigger"
className={cn(
"relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-1.5 py-0.5 text-sm font-medium whitespace-nowrap text-muted-foreground transition-all group-data-vertical/tabs:w-full group-data-vertical/tabs:justify-start not-aria-disabled:hover:text-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:outline-1 focus-visible:outline-ring has-data-[icon=inline-end]:pr-1 has-data-[icon=inline-start]:pl-1 aria-disabled:cursor-not-allowed aria-disabled:opacity-50 dark:not-aria-disabled:hover:text-foreground data-active:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
{...props}
/>
)
}
function TabsContent({ className, ...props }: TabsPrimitive.Panel.Props) {
return (
<TabsPrimitive.Panel
data-slot="tabs-content"
className={cn("flex-1 text-sm outline-none", className)}
{...props}
/>
)
}
export { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants }
Usage
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"<Tabs defaultValue="account">
<TabsList>
<TabsTrigger value="account">Account</TabsTrigger>
<TabsTrigger value="password">Password</TabsTrigger>
</TabsList>
<TabsContent value="account">Make changes to your account here.</TabsContent>
<TabsContent value="password">Change your password here.</TabsContent>
</Tabs>Examples
Line
Use the variant="line" prop on TabsList for a line style.
Loading...
If you want to use a style without left and right padding, add className="gap-4" to TabsList and className="px-0" to TabsTrigger to adjust the spacing.
Loading...
Vertical
Use orientation="vertical" for vertical tabs.
Loading...
Disabled
Loading...
Icon
Loading...
API
See the Base UI documentation for more information.