Tabs Component
An accessible tabs component for horizontal and vertical layouts with fixed or scrollable tab lists, keyboard navigation, optional manual activation, responsive behavior, and robust overflow handling for many tabs.
Overview
Tabs organize related views in the same context and let users switch quickly between sections without leaving the page. This component specification supports two orientations (horizontal and vertical), multiple activation models (automatic and manual), and overflow behavior for many tabs.
Use tabs when content groups are clearly related and users typically need one group at a time. Avoid tabs for primary site navigation or for flows where users must compare multiple sections side by side.
Component Structure
The Tabs component contains:
- Root container
- Tab list (
tablist) - Tab buttons (
tab) - Active indicator
- One tab panel (
tabpanel) visible at a time - Optional overflow controls for many tabs (scroll buttons or overflow menu)
Core Behavior
Selection and Visibility
- Exactly one tab is active by default
- Only the active tab panel is visible
- Selecting a new tab updates active styles and displays its associated panel
- Each tab controls one panel through matching IDs and
aria-controls
Activation Models
- Automatic activation: focused tab activates immediately (best when panel switching is instant)
- Manual activation: focused tab activates only on Enter or Space (better when panel content is expensive or asynchronous)
Orientation
- Horizontal tabs: common for top content segmentation
- Vertical tabs: useful in settings pages, dashboards, and dense desktop interfaces
Variants
Fixed Tabs
- Used when tab count is small and labels are short
- Tabs share available width in horizontal orientation
- Preserves stable position and quick scanning
Scrollable Tabs
- Used when there are many tabs or dynamic tab counts
- Tab list can scroll horizontally (or vertically in vertical mode)
- Optional previous/next controls improve discoverability of hidden tabs
Overflow Menu Tabs
- Used when space is tight and many tabs exist
- Shows a subset of tabs plus a "More" trigger
- Hidden tabs remain keyboard reachable through menu
States
Default
- Tab list visible, one tab selected
- Selected tab has clear active indicator and stronger text emphasis
Focus
- Focus ring visible on focused tab
- Focus and selected states are visually distinguishable
Hover
- Non-selected tabs show subtle hover feedback
Active/Pressed
- Brief pressed feedback on pointer or keyboard activation
Disabled Tab
- Disabled tabs are non-interactive
- Use
aria-disabled='true'and remove from activation flow
Loading Panel (Optional)
- If panel content loads asynchronously, show loading state in panel area
- Keep tab switching responsive and predictable
Keyboard Navigation
Keyboard behavior follows the WAI-ARIA Tabs pattern.
Horizontal Tab List
ArrowRight: Move focus to next tab (wrap from last to first)ArrowLeft: Move focus to previous tab (wrap from first to last)Home: Move focus to first tabEnd: Move focus to last tabEnter / Space: Activate focused tab in manual activation modeTab: Move focus out of tab list to active panel or next focusable element
Vertical Tab List
ArrowDown: Move focus to next tab (wrap from last to first)ArrowUp: Move focus to previous tab (wrap from first to last)Home: Move focus to first tabEnd: Move focus to last tabEnter / Space: Activate focused tab in manual activation mode
Notes:
- In automatic mode, arrow navigation also activates the newly focused tab.
- In manual mode, arrow navigation changes focus only.
Accessibility Requirements
Required Semantics
- Tab list container uses
role='tablist' - Each tab uses
role='tab' - Each panel uses
role='tabpanel' - Active tab has
aria-selected='true', inactive tabsaria-selected='false' - Each tab references its panel via
aria-controls - Each panel references its tab via
aria-labelledby - Non-active tab panels are hidden from visual flow and assistive technology when appropriate
Orientation Metadata
- For vertical tabs, set
aria-orientation='vertical'on the tab list - Horizontal is default; explicit horizontal orientation is optional
Focus Management
- Focus entering tablist lands on active tab
- Keyboard navigation must support wrap behavior
- Focus indicators must meet contrast requirements and remain visible
Screen Reader Behavior
- Tab announcements include label, selected state, and position context
- Switching tabs announces updated selected state and active panel content context
Responsive Behavior
Mobile (< 768px)
- Default to horizontal scrollable tabs when labels do not fit
- Minimum touch target size: 44px height
- Optional compact labels and truncation with tooltip/title support
- Consider converting dense vertical tabs to horizontal scrollable tabs
Tablet (768px to 1023px)
- Fixed tabs for small counts; scrollable tabs for medium-to-large counts
- Keep selected tab visible when users switch
Desktop (>= 1024px)
- Horizontal fixed or scrollable both valid
- Vertical tabs recommended for settings-style pages and side navigation contexts
- Show optional scroll buttons for large tab sets
Many Tabs Strategy
When tab count grows, use one of these approaches:
- Scrollable tab strip with optional scroll controls
- Overflow menu for lower-priority tabs
- Grouping tabs into higher-level categories before rendering tabs
- Progressive disclosure if all tabs are not needed immediately
Guidance:
- Keep labels short and distinct
- Preserve tab order stability
- Ensure active tab always remains visible
Transitions and Motion
Tab Indicator
- Animate indicator movement between tabs
- Recommended duration: 150ms to 220ms
- Recommended easing:
cubic-bezier(0.4, 0, 0.2, 1)
Panel Transition
- Prefer subtle fade or fade + slight translate
- Recommended duration: 180ms to 240ms
- Avoid heavy or distracting motion for frequent tab switching
Reduced Motion
- Respect
prefers-reduced-motion: reduce - Minimize or disable indicator/panel animations
Design Tokens
Layout
- Tab min height: 44px
- Horizontal padding: 12px to 16px per tab
- Indicator thickness: 2px to 3px
- Panel top spacing: 12px to 20px
Typography
- Tab label size: 14px to 16px
- Selected tab label weight stronger than inactive state
Color
- Clear contrast between selected and inactive tabs
- Indicator and focus ring must be visible on all theme modes
Implementation Checklist
Visual
- [ ] One active tab is always obvious
- [ ] Active indicator aligns correctly with active tab
- [ ] Disabled tabs are visually distinct
- [ ] Long labels truncate gracefully without layout breakage
- [ ] Scroll controls/overflow affordances are visible when needed
Functionality
- [ ] Clicking a tab switches to its panel
- [ ] Automatic and manual activation modes both supported
- [ ] Active tab remains visible in scrollable mode
- [ ] Overflow behavior works for many tabs
- [ ] Dynamic tab add/remove keeps valid active state
Keyboard
- [ ] Arrow key navigation works with wrapping
- [ ] Home and End shortcuts work
- [ ] Enter and Space activate tab in manual mode
- [ ] Tab key exits tab list predictably
- [ ] Focus starts on active tab when entering tab list
Accessibility
- [ ] Correct
tablist,tab, andtabpanelroles - [ ]
aria-controlsandaria-labelledbymappings are valid - [ ]
aria-selectedupdates correctly on switch - [ ]
aria-orientation='vertical'present for vertical mode - [ ] Hidden panels are not announced as active content
Framework Patterns
Tabs can be implemented in React, Vue, Angular, or Svelte with the same behavioral contract:
- Controlled pattern: active tab driven by parent state
- Uncontrolled pattern: default active tab managed internally
- Shared logic for orientation, activation mode, overflow handling, and keyboard interactions
See Also
The Tabs component works well with these potions:
- Dashboard Layout with Collapsible Sidebar - Segment dense admin views into focused tab panels
- Data Table - Use tabs to switch between table views (for example: All, Open, Archived)
- Button - Reuse button semantics and state styles for tab triggers
These are suggestions to enhance your implementation. Tabs work independently and can be used in any context.
Summary for AI Agents
Goal: Build an accessible Tabs component supporting horizontal and vertical orientation, automatic or manual activation, responsive overflow handling for many tabs, and subtle motion with reduced-motion support.
Critical Requirements:
- Detect framework and styling system first
- Implement full ARIA tabs semantics (
tablist,tab,tabpanel) - Provide robust keyboard navigation with wrap behavior
- Support both automatic and manual activation
- Handle many tabs using scrollable or overflow strategies
- Ensure active tab remains visible in scrollable lists
- Implement responsive behavior across mobile, tablet, and desktop
- Respect reduced-motion preferences
- Use project tokens and classes, not inline styles