Limited offer: $250 off for the first 200 customers!Claim discount

Tabs

Fully accessible tab panels with ARIA roles — swap between views without leaving the page.

What it does

Tabs renders a role="tablist" button bar and the matching role="tabpanel"for the active tab. State is managed internally — you only need to supply the data. The component uses the first tab's id as the default unless you specify defaultTab.

Props

  • tabs — an array of objects, each with id (string), label (string), and content (ReactNode). Required.
  • defaultTab — the id of the tab that should be active on first render. Defaults to the first tab's id.

Usage

import Tabs, { type Tab } from "@/components/Tabs";

const tabs: Tab[] = [
  { id: "monthly", label: "Monthly", content: <MonthlyPlans /> },
  { id: "yearly",  label: "Yearly",  content: <YearlyPlans /> },
];

<Tabs tabs={tabs} defaultTab="monthly" />

The content field accepts any JSX, so you can pass entire React components, plain text, or a mix. Non-active panels are hidden with the HTML hidden attribute so they stay in the DOM — screen readers can still navigate to them.

TipKeep tab labels short — ideally one or two words. Long labels break the pill shape on small screens. If you need more than four tabs, consider a different navigation pattern.
TipThe Pricing component uses Tabs internally to switch between monthly and yearly billing. Look at src/components/Pricing.tsx for a real-world example of how to wire tab state to price display.