Easy Shadcn
Components

Tabs

Tabs flattens shadcn's Tabs compound components into a single items-driven component: each item describes its trigger label and panel content, instead of hand-writing nested TabsList / TabsTrigger / TabsContent structures.

First Content
Line variant

Installation

With the @easy-shadcn namespace configured:

pnpm dlx shadcn@latest add @easy-shadcn/tabs

Or install via the full URL (zero configuration):

pnpm dlx shadcn@latest add https://easy-shadcn.vercel.app/r/tabs.json

Props

PropTypeDefaultDescription
itemsTabsItem[]-Tab definitions — see the table below. An empty array renders no tab list.
valuestring-The active tab. Use for the controlled mode.
defaultValuestring-The initially active tab. Use for the uncontrolled mode.
onValueChange(value: string, eventDetails) => void-Called when the user activates a tab.
variant"default" | "line""default"List style: pill background or underline, forwarded to the TabsList primitive.
keepMountedbooleanfalseKeeps inactive panels mounted (hidden) instead of unmounting them. Per-item overridable.
listClassNameClassValue-Class override for TabsList.
triggerClassNameClassValue-Class override applied to every TabsTrigger.
contentClassNameClassValue-Class override applied to every TabsContent.

All other props (className, orientation, etc.) are forwarded to the underlying Tabs root.

TabsItem

FieldTypeDescription
valuestringUnique identifier of the tab.
triggerReactNodeTrigger content — plain text or e.g. icon + text.
contentReactNodePanel content.
disabledbooleanDisables this tab.
keepMountedbooleanOverrides the root-level keepMounted for this panel.
triggerClassNameClassValuePer-item trigger class, merged after the root-level triggerClassName.
contentClassNameClassValuePer-item content class, merged after the root-level contentClassName.

Notes

  • value / defaultValue / onValueChange are narrowed to string — the Base UI primitive accepts any, which silently swallows typos. If you need the null "no active tab" state, compose the primitives directly.
  • Use keepMounted when a panel holds expensive state (forms, iframes) that should survive tab switches.
  • items must be homogeneous. For heterogeneous triggers or panels (custom markup per trigger, non-uniform layouts), compose the components/ui/tabs primitives directly instead.

On this page