PRIZM 4.0DSTA
All components

Tabs

Switch between related views.

stableBase UI Tabs

Preview

Overview panel content.

Code

tsx
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";

export function Example() {
  return (
    <Tabs defaultValue="overview">
      <TabsList>
        <TabsTrigger value="overview">Overview</TabsTrigger>
        <TabsTrigger value="activity">Activity</TabsTrigger>
        <TabsTrigger value="settings">Settings</TabsTrigger>
      </TabsList>
      <TabsContent value="overview">Overview content.</TabsContent>
      <TabsContent value="activity">Activity content.</TabsContent>
      <TabsContent value="settings">Settings content.</TabsContent>
    </Tabs>
  );
}

Props

PropTypeDefaultDescription
valuestringControlled active tab value.
defaultValuestringUncontrolled initial active tab.
onValueChange(value: string) => voidCalled when the active tab changes.
orientation"horizontal" | "vertical""horizontal"Tab list orientation.
classNamestringAdditional Tailwind classes, merged with the component's defaults via cn().

Sub-components

TabsListContainer for the trigger buttons.
TabsTriggerIndividual tab button.
PropTypeDefaultDescription
valuestringMatches a panel's value.
TabsContentPanel content shown when its value is active.
PropTypeDefaultDescription
valuestringMatches a trigger's value.

Built on Base UI Tabs. Selected trigger uses **accent-colored text** + raised surface (`data-active`). Keyboard: arrows navigate, Tab moves to content.

All components also accept standard HTML attributes for their root element (e.g. `id`, `aria-*`, `data-*`, event handlers) and forward `ref` where applicable.

Source

The full implementation of components/ui/tabs.tsx is below — copy it into your project and own it. Some components import the cn helper from lib/utils or other primitives; copy those too.

tsx
"use client";

import { cn } from "@/lib/utils";
import { Tabs as BaseTabs } from "@base-ui-components/react/tabs";
import type { ComponentPropsWithoutRef } from "react";

export const Tabs = BaseTabs.Root;

export function TabsList({ className, ...props }: ComponentPropsWithoutRef<typeof BaseTabs.List>) {
  return (
    <BaseTabs.List
      className={cn(
        "relative inline-flex h-9 items-center justify-center rounded-md bg-bg-muted p-1 text-fg-muted",
        className,
      )}
      {...props}
    />
  );
}

export function TabsTrigger({
  className,
  ...props
}: ComponentPropsWithoutRef<typeof BaseTabs.Tab>) {
  return (
    <BaseTabs.Tab
      className={cn(
        "inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1 text-sm font-medium transition-all",
        "text-fg-muted hover:text-fg",
        "focus-visible:outline-1 focus-visible:outline-offset-0 focus-visible:outline-accent",
        "data-[active]:bg-surface data-[active]:text-accent data-[active]:shadow-sm",
        "data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
        className,
      )}
      {...props}
    />
  );
}

export function TabsContent({
  className,
  ...props
}: ComponentPropsWithoutRef<typeof BaseTabs.Panel>) {
  return (
    <BaseTabs.Panel
      className={cn(
        "mt-2",
        "focus-visible:outline-1 focus-visible:outline-offset-0 focus-visible:outline-accent",
        className,
      )}
      {...props}
    />
  );
}

JavaFX

Ships in the PRIZM JavaFX library for thick-client C3 apps as PrizmTabs (extends TabPane). Run the gallery to see it natively.

java
import design.prizm.fx.controls.PrizmTabs;

PrizmTabs()
PropTypeDefaultDescription
tabsObservableList<Tab>Add Tabs via getTabs(); closing policy defaults to UNAVAILABLE.

Thin TabPane subclass; muted labels, accent + muted-fill on the selected tab, via the .prizm-tabs rules. Mirrors components/ui/tabs.tsx.