Components
Tabs
Extended with additional variants and styling options.
<Tabs defaultValue="tab1">
<TabsList variant="default" className="w-full">
<TabsTrigger value="tab1" variant="default">
Tab 1
</TabsTrigger>
<TabsTrigger value="tab2" variant="default">
Tab 2
</TabsTrigger>
</TabsList>
</Tabs>
<Tabs defaultValue="tab1">
<TabsList variant="underline" className="w-full">
<TabsTrigger value="tab1" variant="underline">
Tab 1
</TabsTrigger>
<TabsTrigger value="tab2" variant="underline">
Tab 2
</TabsTrigger>
</TabsList>
</Tabs>
<Tabs defaultValue="tab1">
<TabsList variant="border" className="w-full">
<TabsTrigger value="tab1" variant="border">
Tab 1
</TabsTrigger>
<TabsTrigger value="tab2" variant="border">
Tab 2
</TabsTrigger>
</TabsList>
</Tabs>
Installation
npx shadcn@latest add https://yuki-ui.vercel.app/r/tabs.json
npx shadcn@latest add https://yuki-ui.vercel.app/r/tabs.json
pnpm dlx shadcn@latest add https://yuki-ui.vercel.app/r/tabs.json
bunx --bun shadcn@latest add https://yuki-ui.vercel.app/r/tabs.json
Install the following dependencies:
npm install @radix-ui/react-tabs
pnpm add @radix-ui/react-tabs
yarn add @radix-ui/react-tabs
bun add @radix-ui/react-tabs
Copy and paste the following code into your project.
'use client'
import type { VariantProps } from 'class-variance-authority'
import * as React from 'react'
import * as TabsPrimitive from '@radix-ui/react-tabs'
import { cva } from 'class-variance-authority'
import { cn } from '@/lib/utils'
function Tabs({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.Root>) {
return (
<TabsPrimitive.Root
data-slot="tabs"
className={cn('flex flex-col gap-2', className)}
{...props}
/>
)
}
const tabsListVariants = cva(
'inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]',
{
variants: {
variant: {
default:
'bg-muted *:data-[slot=tabs-trigger]:data-[state=active]:bg-background *:data-[slot=tabs-trigger]:dark:data-[state=active]:bg-input/30 *:data-[slot=tabs-trigger]:dark:data-[state=active]:border-input *:data-[slot=tabs-trigger]:rounded-md *:data-[slot=tabs-trigger]:border *:data-[slot=tabs-trigger]:data-[state=active]:shadow-sm',
underline:
'*:data-[slot=tabs-trigger]:data-[state=active]:border-primary *:data-[slot=tabs-trigger]:border-b',
border:
'*:data-[slot=tabs-trigger]:dark:data-[state=active]:bg-muted *:data-[slot=tabs-trigger]:border-border *:data-[slot=tabs-trigger]:data-[state=active]:bg-background border *:data-[slot=tabs-trigger]:rounded-md *:data-[slot=tabs-trigger]:data-[state=active]:border',
},
},
defaultVariants: {
variant: 'default',
},
},
)
interface TabsListProps
extends React.ComponentProps<typeof TabsPrimitive.List>,
VariantProps<typeof tabsListVariants> {}
function TabsList({ className, variant, ...props }: TabsListProps) {
return (
<TabsPrimitive.List
data-slot="tabs-list"
className={cn(tabsListVariants({ variant }), className)}
{...props}
/>
)
}
function TabsTrigger({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
return (
<TabsPrimitive.Trigger
data-slot="tabs-trigger"
className={cn(
"focus-visible:border-ring focus-visible:ring-ring/50 dark:data-[state=active]:text-foreground focus-visible:outline-ring text-foreground dark:text-muted-foreground dark:data-[state=inactive]:hover:text-muted-foreground/60 data-[state=inactive]:hover:text-foreground/60 inline-flex h-[calc(100%-1px)] flex-1 cursor-pointer items-center justify-center gap-1.5 border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className,
)}
{...props}
/>
)
}
function TabsContent({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.Content>) {
return (
<TabsPrimitive.Content
data-slot="tabs-content"
className={cn('flex-1 outline-none', className)}
{...props}
/>
)
}
export { Tabs, TabsList, TabsTrigger, TabsContent }