Animated, accessible tab component with keyboard navigation and an animated indicator.
Made by raouf.codesOverview
Core Concept
The Tabs component provides a small, composable, and accessible tab system with first-class keyboard support and smooth motion. Built with Framer Motion for animated indicators and panel transitions.
Key Features
- Animated indicator — Smooth layout animation for the active tab marker
- Keyboard navigation — Arrow keys, Home/End support per WAI-ARIA
- Controlled/Uncontrolled — Flexible state management patterns
- Variant system — Full support for intent, styling, shape, and visuals
- SSR compatible — Stable IDs via
useIdhook
Anatomy
Tabs— Root component (state, ids, keyboard logic)Tabs.List— Tablist containerTabs.Trigger— Interactive tab buttonTabs.Indicator— Animated underline/selection indicatorTabs.Content— Layout wrapper for panelsTabs.Panel— Individual animated paneluseTabs()— Hook for custom integrations
Installation
Usage
It can be used uncontrolled for simplicity, or controlled when you need external state management.
Basic (uncontrolled)
Controlled
Using useTabs() inside a custom panel
API Reference
Tabs (root)
| Prop | Type | Default |
|---|---|---|
value? | string | - |
defaultValue? | string | - |
onValueChange? | function | - |
activation? | enum | "manual" |
direction? | enum | "ltr" |
intent? | enum | "primary" |
styling? | enum | "underline" |
visuals? | enum | "classic" |
size? | enum | "md" |
shape? | enum | "rounded" |
className? | string | - |
...props? | ComponentProps<"div"> | - |
Tabs.List
| Prop | Type | Default |
|---|---|---|
className? | string | - |
...props? | ComponentProps<"div"> | - |
Tabs.Trigger
Azemmur API Reference - Button Primitive
| Prop | Type | Default |
|---|---|---|
value | string | - |
triggerClassName? | string | - |
indicatorClassName? | string | - |
...props? | HTMLMotionProps<"button"> | - |
Tabs.Content
| Prop | Type | Default |
|---|---|---|
className? | string | - |
...props? | ComponentProps<"div"> | - |
Tabs.Panel
| Prop | Type | Default |
|---|---|---|
value | string | - |
className? | string | - |
...props? | ComponentProps<typeof motion.div> | - |
Tabs.Indicator
| Prop | Type | Default |
|---|---|---|
intent? | enum | "primary" |
styling? | enum | "underline" |
visuals? | enum | "classic" |
shape? | enum | "rounded" |
...props? | ComponentProps<typeof motion.div> | - |
useTabs() hook
Variants
Visual variants are powered by tabs-variants and applied consistently across the component:
intent— semantic intent (primary / secondary / accent)styling— trigger & indicator stylevisuals— surface / background treatmentsize— spacing & typographyshape— border radius
For more details, refer to the tables above.
Accessibility
Tabs.Listrendersrole="tablist"witharia-orientation.Tabs.Triggerusesrole="tab",aria-selected, andaria-controls.Tabs.Panelusesrole="tabpanel",id, andaria-labelledby.- Ids are generated via
useTabs()helpers for consistency.
Keyboard support
ArrowRight/ArrowLeft— move focus between tabs (respectsdirection)Home/End— jump to first / last tab'auto'vs'manual'activation controls when selection changes
Notes
Tabsmanages focus and selection internally unless controlled viavalue.- This component exposes a stable public API. Lower-level primitives (auto-height contents, advanced layout helpers) live in the shared UI package and are intentionally not part of this surface.
Credits
- Follows WAI-ARIA Tabs Pattern
- Inspired by Radix UI Tabs
- Animations powered by Motion
Built by raouf.codes. The source code is available on GitHub.
Last updated: 3/21/2026