Tabs
A set of layered sections of content—known as tab panels—that are displayed one at a time. Built with accessibility in mind using Astro components and styled with Tailwind CSS.
Usage
---
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/block/tabs"
---
<Tabs defaultValue="account" className="w-[400px]">
<TabsList>
<TabsTrigger value="account">Account</TabsTrigger>
<TabsTrigger value="password">Password</TabsTrigger>
</TabsList>
<TabsContent value="account">
Make changes to your account here.
</TabsContent>
<TabsContent value="password">
Change your password here.
</TabsContent>
</Tabs>
Examples
Basic Tabs
Account
Make changes to your account here. Click save when you’re done.
Password
Change your password here. After saving, you’ll be logged out.
Multiple Tab Sets
You can have multiple independent tab sets on the same page:
Overview content goes here.
Analytics dashboard content.
Reports and data visualization.
General settings content.
Security settings content.
<Tabs defaultValue="overview" className="w-[300px]">
<TabsList>
<TabsTrigger value="overview">Overview</TabsTrigger>
<TabsTrigger value="analytics">Analytics</TabsTrigger>
<TabsTrigger value="reports">Reports</TabsTrigger>
</TabsList>
<TabsContent value="overview">
Overview content goes here.
</TabsContent>
<TabsContent value="analytics">
Analytics dashboard content.
</TabsContent>
<TabsContent value="reports">
Reports and data visualization.
</TabsContent>
</Tabs>
Disabled Tabs
You can disable specific tabs to prevent user interaction:
This tab is enabled and can be accessed.
This content won’t be accessible because the tab is disabled.
This is another enabled tab.
<Tabs defaultValue="enabled1" className="w-[400px]">
<TabsList>
<TabsTrigger value="enabled1">Enabled Tab</TabsTrigger>
<TabsTrigger value="disabled" disabled>Disabled Tab</TabsTrigger>
<TabsTrigger value="enabled2">Another Tab</TabsTrigger>
</TabsList>
<TabsContent value="enabled1">
This tab is enabled and can be accessed.
</TabsContent>
<TabsContent value="disabled">
This content won't be accessible because the tab is disabled.
</TabsContent>
<TabsContent value="enabled2">
This is another enabled tab.
</TabsContent>
</Tabs>
Code Examples
Tabs are perfect for showing the same functionality in different programming languages:
console.log("Debugging in the console is old school");
public static void main(String... args){
System.out.println("It's verbose but at least it's a real programming language");
}
fmt.Println("TBH I'm not sure this is how console logging works in Go but StackOverflow said it is")
Component API
Tabs
The root container component that manages the tab state.
Prop | Type | Default | Description |
---|---|---|---|
defaultValue | string | - | The value of the tab that should be active by default |
className | string | "" | Additional CSS classes to apply |
id | string | auto | Unique identifier (auto-generated if not provided) |
TabsList
A container for the tab triggers (buttons).
Prop | Type | Default | Description |
---|---|---|---|
className | string | "" | Additional CSS classes to apply |
TabsTrigger
The clickable tab button that activates a tab panel.
Prop | Type | Default | Description |
---|---|---|---|
value | string | - | Required. The value that identifies this tab |
className | string | "" | Additional CSS classes to apply |
disabled | boolean | false | Whether the tab trigger is disabled |
TabsContent
The tab panel content that is displayed when its corresponding trigger is active.
Prop | Type | Default | Description |
---|---|---|---|
value | string | - | Required. The value that identifies this panel |
className | string | "" | Additional CSS classes to apply |
Accessibility
The Tabs component is built with comprehensive accessibility features:
- Keyboard Navigation:
- Arrow keys (Left/Right/Up/Down) to navigate between tabs
- Home/End keys to jump to first/last tab
- Enter/Space to activate a tab
- Tab key to move focus in and out of the tab group
- ARIA Attributes:
role="tablist"
on the TabsList containerrole="tab"
on each TabsTriggerrole="tabpanel"
on each TabsContentaria-selected
to indicate active tab statearia-controls
linking tabs to their panelsaria-labelledby
linking panels to their tabs
- Focus Management:
- Proper tabindex management (-1 for inactive tabs, 0 for active tab)
- Focus moves to newly activated tabs
- Disabled tabs are skipped during keyboard navigation
- Screen Reader Support: Announces tab changes and content with proper semantic markup
Styling
The components are styled using standard Tailwind CSS classes. You can customize the appearance by:
- CSS Classes: Add custom Tailwind classes via the
className
prop (note: these components useclassName
instead of the standard Astroclass
prop for consistency with React/JSX patterns) - Custom CSS: Override specific styles by targeting the component classes
- Tailwind Utilities: Use Tailwind’s utility classes for quick styling
Default Styling
- TabsList: Uses
bg-gray-100 dark:bg-gray-800
background with rounded corners and padding - TabsTrigger: Styled as buttons with focus rings (
focus-visible:ring-blue-500
) and smooth transitions - TabsContent: Has focus ring styles and proper spacing
- Active State: Active tabs get
bg-white dark:bg-gray-950
,text-gray-950 dark:text-gray-50
, andshadow-sm
classes
/* Example: Customizing tab colors */
.my-custom-tabs [role="tablist"] {
@apply bg-slate-100 dark:bg-slate-800;
}
.my-custom-tabs [role="tab"][data-state="active"] {
@apply bg-blue-500 text-white;
}
/* Example: Custom focus ring color */
.my-custom-tabs [role="tab"] {
@apply focus-visible:ring-green-500;
}
Implementation Details
The Tabs component is implemented as Astro components with embedded JavaScript for interactivity:
- State Management: Uses DOM attributes and classes to manage tab state
- Event Handling: Click and keyboard events are handled with vanilla JavaScript
- Auto-initialization: Tabs are automatically initialized when the page loads
- Unique IDs: Each tab set gets unique IDs to prevent conflicts on pages with multiple tab groups