Skip to content

Tabs

Open in GitHub

Open in Figma

Organize content into tabbed panels, rendering one panel at a time.

---
import { CircleCheckIcon } from '@lucide/astro';
import { Avatar, AvatarFallback, AvatarImage } from '@bejamas/ui/components/avatar';
import { Badge } from '@bejamas/ui/components/badge';
import { Button } from '@bejamas/ui/components/button';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@bejamas/ui/components/card';
import { Separator } from '@bejamas/ui/components/separator';
import { Tabs, TabsContent, TabsIndicator, TabsList, TabsTrigger } from '@bejamas/ui/components/tabs';
---
<Tabs class="w-full max-w-md" defaultValue="features">
<TabsList class="w-full">
<TabsIndicator />
<TabsTrigger value="features" aria-selected="true">Features</TabsTrigger>
<TabsTrigger value="pricing">Pricing</TabsTrigger>
<TabsTrigger value="testimonials">Testimonials</TabsTrigger>
</TabsList>
<TabsContent value="features">
<Card>
<CardHeader>
<CardTitle>Powerful Features</CardTitle>
<CardDescription>Everything you need to grow your business</CardDescription>
</CardHeader>
<CardContent>
<div class="space-y-4">
<div class="flex items-start gap-3">
<div>
<h4 class="font-medium mb-1">Lightning Fast Performance <Badge variant="primary">New</Badge></h4>
<p class="text-sm text-muted-foreground">Optimized for speed and efficiency</p>
</div>
</div>
<Separator />
<div class="flex items-start gap-3">
<div>
<h4 class="font-medium mb-1">Easy Integration <Badge variant="success">Popular</Badge></h4>
<p class="text-sm text-muted-foreground">Set up in minutes, not hours</p>
</div>
</div>
</div>
</CardContent>
<CardFooter>
<Button variant="outline" class="w-full">Explore All Features</Button>
</CardFooter>
</Card>
</TabsContent>
<TabsContent value="pricing">
<Card>
<CardHeader>
<div class="flex items-center justify-between">
<CardTitle>Pro Plan</CardTitle>
<Badge variant="primary">Most Popular</Badge>
</div>
<CardDescription>Perfect for growing teams</CardDescription>
</CardHeader>
<CardContent>
<div class="mb-4">
<span class="text-4xl font-medium">$49</span>
<span class="text-muted-foreground">/month</span>
</div>
<ul class="space-y-2 text-sm">
<li class="flex items-center gap-2">
<CircleCheckIcon class="size-5" />
Unlimited projects
</li>
<li class="flex items-center gap-2">
<CircleCheckIcon class="size-5" />
Priority support
</li>
<li class="flex items-center gap-2">
<CircleCheckIcon class="size-5" />
Advanced analytics
</li>
</ul>
</CardContent>
<CardFooter class="flex gap-2">
<Button class="flex-1">Get Started</Button>
<Button variant="outline">Compare Plans</Button>
</CardFooter>
</Card>
</TabsContent>
<TabsContent value="testimonials">
<Card>
<CardContent>
<p class="text-lg mb-4 italic">
"This product transformed how we work. Highly recommended for any growing business!"
</p>
<div class="flex items-center gap-3">
<Avatar>
<AvatarImage src="/avatars/sarah.jpg" alt="Sarah Johnson" />
<AvatarFallback>SJ</AvatarFallback>
</Avatar>
<div>
<p class="font-semibold">Sarah Johnson</p>
<p class="text-sm text-muted-foreground">CEO, TechCorp</p>
</div>
</div>
</CardContent>
<CardFooter>
<Button variant="outline" class="w-full">Read More Stories</Button>
</CardFooter>
</Card>
</TabsContent>
</Tabs>
Terminal window
bunx bejamas add tabs
---
import { Tabs, TabsList, TabsTrigger, TabsContent } from '@bejamas/ui/components/tabs';
---
<Tabs defaultValue="overview">
<TabsList>
<TabsTrigger value="overview">Overview</TabsTrigger>
</TabsList>
<TabsContent value="overview">Content...</TabsContent>
</Tabs>

The tabs component emits custom events that you can listen to:

EventDetailDescription
tabs:change{ value: string }Fired when the selected tab changes
<Tabs id="my-tabs" defaultValue="tab1">
<TabsList>
<TabsTrigger value="tab1">Tab 1</TabsTrigger>
<TabsTrigger value="tab2">Tab 2</TabsTrigger>
</TabsList>
<TabsContent value="tab1">Content 1</TabsContent>
<TabsContent value="tab2">Content 2</TabsContent>
</Tabs>
<script>
const tabs = document.getElementById('my-tabs');
tabs.addEventListener('tabs:change', (e) => {
console.log('Selected tab:', e.detail.value);
});
</script>

You can control the tabs programmatically by dispatching a tabs:set event:

const tabs = document.getElementById('my-tabs');
// Select a tab
tabs.dispatchEvent(new CustomEvent('tabs:set', {
detail: { value: 'tab2' }
}));

The tabs component sets these data attributes that you can use for styling or querying state:

AttributeElementDescription
data-statetabs-triggerCurrent state (active or inactive)

The tabs indicator exposes CSS variables for animation:

VariableElementDescription
--active-tab-lefttabs-indicatorLeft position of active tab
--active-tab-widthtabs-indicatorWidth of active tab
--active-tab-toptabs-indicatorTop position of active tab
--active-tab-heighttabs-indicatorHeight of active tab