# Tabs
A tabbed interface component using Unpoly's `up-switch` directive with hidden
radio buttons for zero-JavaScript tab switching.
## Installation
```bash
deno run -A jsr:@lockness/ui add tabs
```
## Usage
```tsx
import { Tabs, TabsList, TabsTrigger, TabsContent } from '@lockness/ui/components'
Account
Password
Account settings content
Password settings content
```
### Vertical Tabs
```tsx
Profile
Account
Profile content
Account content
```
## Components
### Tabs
The root container component.
| Prop | Type | Default | Description |
| -------------- | ---------------------------- | -------------- | ------------------------------------------------------- |
| `defaultValue` | `string` | - | Default active tab value |
| `name` | `string` | `'tab'` | Unique name for this tab group (used for radio buttons) |
| `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` | Orientation of the tabs |
| `class` | `string` | - | Additional CSS class names |
| `children` | `unknown` | - | Tabs content |
### TabsList
Container for tab triggers.
| Prop | Type | Default | Description |
| ------------- | ---------------------------- | -------------- | ---------------------------- |
| `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` | Orientation of the tabs list |
| `class` | `string` | - | Additional CSS class names |
| `children` | `unknown` | - | Tab triggers |
### TabsTrigger
Individual tab button using a hidden radio button with label.
| Prop | Type | Default | Description |
| ---------- | --------- | ------------ | ----------------------------------------------------------- |
| `value` | `string` | **required** | Tab value (should match TabsContent value) |
| `checked` | `boolean` | - | Whether this tab is checked by default |
| `name` | `string` | `'tab'` | Unique name for radio button group (should match Tabs name) |
| `class` | `string` | - | Additional CSS class names |
| `children` | `unknown` | - | Trigger label content |
### TabsContent
Tab panel content shown when the corresponding trigger is active.
| Prop | Type | Default | Description |
| ---------- | --------- | ------------ | ------------------------------------------------------------ |
| `value` | `string` | **required** | Tab value (should match TabsTrigger value) |
| `name` | `string` | `'tab'` | Unique name for this tab group (must match parent Tabs name) |
| `class` | `string` | - | Additional CSS class names |
| `children` | `unknown` | - | Panel content |
## Theming
The Tabs component can be customized using CSS variables. This allows you to
change the appearance of tabs globally or override specific instances.
### Available CSS Variables
| Variable | Default | Description |
| ---------------------------------- | --------------------------- | ----------------------------------- |
| `--tabs-padding` | `0.25rem` | Padding around tabs list |
| `--tabs-height` | `2.5rem` | Height of tabs list |
| `--tabs-background` | `var(--muted)` | Background color for tabs list |
| `--tabs-foreground` | `var(--muted-foreground)` | Text color for inactive tabs |
| `--tabs-border-radius` | `var(--radius)` | Border radius for tabs list |
| `--tabs-trigger-padding-x` | `0.75rem` | Horizontal padding for tab triggers |
| `--tabs-trigger-padding-y` | `0.375rem` | Vertical padding for tab triggers |
| `--tabs-trigger-font-size` | `0.875rem` | Font size for tab triggers |
| `--tabs-trigger-font-weight` | `500` | Font weight for tab triggers |
| `--tabs-trigger-border-radius` | `calc(var(--radius) - 2px)` | Border radius for tab triggers |
| `--tabs-trigger-background-active` | `var(--background)` | Background color for active tab |
| `--tabs-trigger-foreground-active` | `var(--foreground)` | Text color for active tab |
| `--tabs-content-margin-top` | `0.5rem` | Top margin for tab content |
### Theming Examples
#### Global Customization
Customize all tabs by setting CSS variables in your theme:
```css
/* app/view/assets/app.css */
@theme {
/* Make tabs larger */
--tabs-height: 3rem;
--tabs-trigger-padding-x: 1rem;
--tabs-trigger-padding-y: 0.5rem;
--tabs-trigger-font-size: 1rem;
/* Make tabs more rounded */
--tabs-border-radius: 0.75rem;
--tabs-trigger-border-radius: 0.625rem;
/* Bold active tabs */
--tabs-trigger-font-weight: 600;
/* Add spacing between tabs and content */
--tabs-content-margin-top: 1rem;
}
```
#### Local Overrides
Override CSS variables for specific tabs instances:
```tsx
{/* Larger tabs */}
{/* Pill-shaped tabs */}
```
#### Component-Specific Theming
Create themed sections with different tab styles:
```tsx
{/* Tabs with primary-colored active state */}
{/* Compact tabs for sidebar navigation */}
```
## Features
- **Zero JavaScript** - Uses Unpoly's `up-switch` with hidden radio buttons
- **Accessible** - Proper ARIA roles and keyboard navigation
- **Vertical layout** - Support for vertical tab orientation
- **Themeable** - Uses CSS variables for styling
- **Multiple groups** - Use different `name` props for multiple tab groups on
one page
## Notes
- Make sure to use the same `name` prop on `Tabs`, `TabsTrigger`, and
`TabsContent` when using multiple tab groups
- Set `checked` on one `TabsTrigger` to define the default active tab
- Requires Unpoly for the `up-switch` functionality