Tabs component is used to display a set of tabs that can be used to navigate between different sections of a page.
export const Example = () => {
return (
<Tabs defaultValue="login">
<TabsList>
<TabsTrigger value="login">Login</TabsTrigger>
<TabsTrigger value="register">Register</TabsTrigger>
</TabsList>
<TabsContent value="login" className="mt-2">
<div>Login content</div>
</TabsContent>
<TabsContent value="register" className="mt-2">
<div>Register content</div>
</TabsContent>
</Tabs>
);
};
If you haven't included Piksel UI in your project, include it first. You can check the installation page.
Copy the following source code and add it to your project.
"use client";
import { cn } from "@/utils/cn";
import * as TabsPrimitive from "@radix-ui/react-tabs";
import {
ComponentPropsWithRef,
createContext,
forwardRef,
useContext,
useEffect,
} from "react";
import { tv, VariantProps } from "tailwind-variants";
type TabsContextType = VariantProps<typeof tabsStyles>;
const TabsContext = createContext<TabsContextType | null>(null);
const TabsContextProvider = TabsContext.Provider;
const useTabsContext = () => {
const context = useContext(TabsContext) || {};
return context;
};
export const tabsDisplayName = "Tabs";
export type TabsProps = ComponentPropsWithRef<typeof TabsPrimitive.Root> &
VariantProps<typeof tabsStyles>;
/**
* @name Tabs
* @description Tabs component is used to display a set of tabs that can be used to navigate between different sections of a page.
*/
export const Tabs = forwardRef<HTMLDivElement, TabsProps>((props, ref) => {
const { variant, color, size, radius, className, ...rest } = props;
const { root } = tabsStyles({
variant,
color,
size,
radius,
});
return (
<TabsContextProvider
value={{
variant,
color,
size,
radius,
}}
>
<TabsPrimitive.Root className={root({ className })} {...rest} ref={ref} />
</TabsContextProvider>
);
});
Tabs.displayName = tabsDisplayName;
export const tabsListDisplayName = "TabsList";
export type TabsListProps = ComponentPropsWithRef<typeof TabsPrimitive.List>;
/**
* @name TabsList
* @description TabsList component is used to display a list of tabs that can be used to navigate between different sections of a page.
*/
export const TabsList = forwardRef<HTMLDivElement, TabsListProps>(
(props, ref) => {
const { className, ...rest } = props;
const context = useTabsContext();
const { list } = tabsStyles(context);
useEffect(() => {}, [rest.id]);
return (
<TabsPrimitive.List className={list({ className })} {...rest} ref={ref} />
);
}
);
TabsList.displayName = tabsListDisplayName;
export const tabsTriggerDisplayName = "TabsTrigger";
export type TabsTriggerProps = ComponentPropsWithRef<
typeof TabsPrimitive.Trigger
>;
/**
* @name TabsTrigger
* @description TabsTrigger component is used to display a trigger
*/
export const TabsTrigger = forwardRef<HTMLButtonElement, TabsTriggerProps>(
(props, ref) => {
const { className, ...rest } = props;
const context = useTabsContext();
const { trigger } = tabsStyles(context);
return (
<TabsPrimitive.Trigger
className={trigger({ className })}
{...rest}
ref={ref}
/>
);
}
);
TabsTrigger.displayName = tabsTriggerDisplayName;
export const tabsContentDisplayName = "TabsContent";
export type TabsContentProps = ComponentPropsWithRef<
typeof TabsPrimitive.Content
>;
/**
* @name TabsContent
* @description TabsContent component is used to display the content of the tabs
*/
export const TabsContent = forwardRef<HTMLDivElement, TabsContentProps>(
(props, ref) => {
const { className, ...rest } = props;
const context = useTabsContext();
const { content } = tabsStyles(context);
return (
<TabsPrimitive.Content
className={cn(content({ className }))}
{...rest}
ref={ref}
/>
);
}
);
TabsContent.displayName = tabsContentDisplayName;
export const tabsStyles = tv({
/**
* Base styles of the tabs
*/
slots: {
root: "flex flex-col",
list: "flex items-stretch overflow-x-auto",
trigger: [
"flex-1 text-center cursor-pointer whitespace-nowrap transition-colors",
"data-[state=active]:shadow disabled:cursor-not-allowed disabled:opacity-75",
],
content: "",
},
variants: {
/**
* Variant prop of the tabs
*/
variant: {
filled: {},
soft: {},
outline: {},
},
/**
* Color prop of the tabs
*/
color: {
blue: {},
red: {},
indigo: {},
green: {},
yellow: {},
zinc: {},
white: {},
black: {},
},
/**
* Size prop of the tabs
*/
size: {
sm: {
list: "gap-0.5",
},
md: {
list: "gap-1 p-0.5",
trigger: "px-2 py-1 text-base",
},
lg: {
list: "gap-1.5",
},
},
radius: {
none: {},
sm: {},
md: {
list: "rounded-lg",
trigger: "rounded-md",
},
lg: {},
xl: {},
},
},
compoundVariants: [
/* -------------------------------------------------------------------------- */
/* Variants and colors */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* Filled variant */
/* -------------------------------------------------------------------------- */
{
variant: "filled",
color: "blue",
className: { root: "bg-blue-500 text-white hover:text-white" },
},
{
variant: "filled",
color: "red",
className: { root: "bg-red-500 text-white hover:text-white" },
},
{
variant: "filled",
color: "indigo",
className: { root: "bg-indigo-500 text-white hover:text-white" },
},
{
variant: "filled",
color: "green",
className: { root: "bg-green-500 text-white hover:text-white" },
},
{
variant: "filled",
color: "yellow",
className: { root: "bg-yellow-400 text-black hover:text-black" },
},
{
variant: "filled",
color: "zinc",
className: { root: "bg-zinc-500 text-white hover:text-white" },
},
{
variant: "filled",
color: "white",
className: {
list: "bg-white shadow border",
trigger:
"font-medium text-zinc-900 data-[state=active]:bg-zinc-800 data-[state=active]:text-zinc-50",
},
},
{
variant: "filled",
color: "black",
className: {
root: "bg-zinc-950 border-zinc-900 hover:text-white",
},
},
/* -------------------------------------------------------------------------- */
/* Soft variant */
/* -------------------------------------------------------------------------- */
{
variant: "soft",
color: "blue",
className: { root: "bg-blue-100 text-blue-600 hover:text-blue-600" },
},
{
variant: "soft",
color: "red",
className: { root: "bg-red-100 text-red-600 hover:text-red-600" },
},
{
variant: "soft",
color: "indigo",
className: {
root: "bg-indigo-100 text-indigo-600 hover:text-indigo-600",
},
},
{
variant: "soft",
color: "green",
className: { root: "bg-green-100 text-green-600 hover:text-green-600" },
},
{
variant: "soft",
color: "yellow",
className: {
root: "bg-yellow-100 text-yellow-600 hover:text-yellow-600",
},
},
{
variant: "soft",
color: "zinc",
className: { root: "bg-zinc-100 text-zinc-600 hover:text-zinc-600" },
},
{
variant: "soft",
color: "white",
className: { root: "bg-zinc-50 text-zinc-950" },
},
{
variant: "soft",
color: "black",
className: {
root: "bg-zinc-200 text-zinc-600",
tabsTitle: "text-zinc-950",
},
},
/* -------------------------------------------------------------------------- */
/* Outline variant */
/* -------------------------------------------------------------------------- */
{
variant: "outline",
color: "blue",
className: {
root: [
"text-blue-500 outline-blue-500",
"hover:bg-blue-500 hover:text-white",
"focus-visible:ring-offset-blue-300",
],
},
},
{
variant: "outline",
color: "red",
className: {
root: [
"text-red-500 outline-red-500",
"hover:bg-red-500 hover:text-white",
"focus-visible:ring-offset-red-300",
],
},
},
{
variant: "outline",
color: "indigo",
className: {
root: [
"text-indigo-500 outline-indigo-500",
"hover:bg-indigo-500 hover:text-white",
"focus-visible:ring-offset-indigo-300",
],
},
},
{
variant: "outline",
color: "green",
className: {
root: [
"text-green-500 outline-green-500",
"hover:bg-green-500 hover:text-white",
"focus-visible:ring-offset-green-300",
],
},
},
{
variant: "outline",
color: "yellow",
className: {
root: [
"text-yellow-600",
"hover:bg-yellow-500 hover:text-black",
"focus-visible:ring-offset-yellow-300",
],
},
},
{
variant: "outline",
color: "zinc",
className: {
root: [
"text-zinc-500",
"hover:bg-zinc-500 hover:text-white",
"focus-visible:ring-offset-zinc-300",
],
},
},
{
variant: "outline",
color: "white",
className: {
root: [""],
},
},
{
variant: "outline",
color: "black",
className: {
root: ["text-zinc-950"],
},
},
],
defaultVariants: {
variant: "filled",
color: "white",
size: "md",
radius: "md",
},
});
The Tabs component has the following props.
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | filled | soft | outline | filled | filled | The variant of the tabs. |
| color | blue | red | indigo | green | yellow | zinc | white | black | white | The color of the tabs. |
| size | sm | md | lg | md | The size of the tabs. |
| radius | none | sm | md | lg | xl | md | The radius of the tabs. |