Tabs on Base UI's Tabs (roving focus, arrow keys, Home/End, ARIA wiring), with a gliding indicator and panels that cross-fade in the direction of travel.
import { Tab, Tabs, TabsList, TabsPanel, TabsPanels } from "@/components/eased/tabs/tabs";
<Tabs defaultValue="overview">
<TabsList aria-label="Project">
<Tab value="overview">Overview</Tab>
<Tab value="activity">Activity</Tab>
</TabsList>
<TabsPanels className="mt-3">
<TabsPanel value="overview">…</TabsPanel>
<TabsPanel value="activity">…</TabsPanel>
</TabsPanels>
</Tabs>| Component | Props | |
|---|---|---|
Tabs | value, defaultValue, onValueChange, variant: "underline" | "pill" (default underline), orientation | Base UI Root props pass through. |
TabsList | activateOnFocus, loopFocus, aria-label | Scrolls sideways with edge fades when the tabs outgrow it, so it never widens the page. |
Tab | value, icon?, disabled?, render? | render={<Link href="/settings/domains" />} makes a routed tab; the indicator and label render inside it. |
TabsPanels | className | Its height springs between panels of different lengths. |
TabsPanel | value, keepMounted? |
Motion signature: the indicator glides on the snappy spring; the new panel enters from 6px on the side of the tab you came from while the old one leaves 3px the other way, faster, and the container's height springs between them. Reduced motion keeps only an opacity cross-fade.