Tabs
The Tabs
component provides a way to organize content into multiple panels, with each panel being associated with a tab trigger. It supports both regular tabs and navigation tabs that integrate with your router.
It can be composed with several subcomponents such as Tabs.Root
, Tabs.NavRoot
, Tabs.List
, Tabs.Trigger
, and Tabs.Content
to offer a structured and customizable interface.
Usage
import { Tabs } from "@harnessio/ui/components";
//...
return ( <Tabs.Root defaultValue="general"> <Tabs.List> <Tabs.Trigger value="general">General</Tabs.Trigger> <Tabs.Trigger value="security">Security</Tabs.Trigger> <Tabs.Trigger value="advanced">Advanced</Tabs.Trigger> </Tabs.List>
<Tabs.Content value="general"> {/* General settings content */} </Tabs.Content> <Tabs.Content value="security"> {/* Security settings content */} </Tabs.Content> <Tabs.Content value="advanced"> {/* Advanced settings content */} </Tabs.Content> </Tabs.Root>)
Anatomy
All parts of the Tabs
component can be imported and composed as required.
// Regular Tabs<Tabs.Root> <Tabs.List> <Tabs.Trigger /> </Tabs.List> <Tabs.Content /></Tabs.Root>
// Navigation Tabs<Tabs.NavRoot> <Tabs.List> <Tabs.Trigger /> </Tabs.List></Tabs.NavRoot>
Variants
The Tabs
component supports multiple visual variants that can be applied via the variant
prop on Tabs.List
.
With Icons
Tab triggers can include icons to enhance visual recognition and improve user experience.
With Logos
Tab triggers can display logos for brand-specific navigation or integration tabs.
With Counters
Tab triggers can display counter badges to show quantities or notifications.
Complex Children
When icons, logos, and counters aren’t sufficient, you can use custom children for more complex tab triggers.
Navigation Tabs
The Tabs.NavRoot
variant integrates with your router to create navigation-based tabs that update based on the current route.
Controlled Tabs
Both Tabs.Root
and Tabs.NavRoot
can be controlled by passing value
and onValueChange
props.
Custom Active Class
You can customize the active tab styling using the activeClassName
prop on Tabs.List
.
API Reference
Root
The Root
component serves as the main container for regular tabs functionality. It manages the active tab state and provides context to child components.
<Tabs.Root value={activeTab} // [OPTIONAL] controlled active tab value onValueChange={onChange} // [OPTIONAL] callback when active tab changes defaultValue="tab1" // [OPTIONAL] default active tab (uncontrolled)> {/* List and Content components */}</Tabs.Root>
Prop | Required | Default | Type |
---|---|---|---|
defaultValue | false | string | |
value | false | string | |
onValueChange | false | (value: string) => void | |
children | true | ReactNode |
NavRoot
The NavRoot
component serves as the main container for navigation-based tabs. It integrates with your router to update the active tab based on the current route.
<Tabs.NavRoot value={activeRoute} // [OPTIONAL] controlled active route onValueChange={navigate} // [OPTIONAL] callback when route changes defaultValue="/home" // [OPTIONAL] default route> {/* List and optional Content components */}</Tabs.NavRoot>
Prop | Required | Default | Type |
---|---|---|---|
value | false | string | |
onValueChange | false | (value: string) => void | |
defaultValue | false | string | |
children | true | ReactNode |
List
The List
component is a container for tab triggers that handles layout and styling variants.
<Tabs.List variant="underlined" // [OPTIONAL] visual variant className="my-class" // [OPTIONAL] custom class activeClassName="active" // [OPTIONAL] class for active tab> {/* Trigger components */}</Tabs.List>
Prop | Required | Default | Type |
---|---|---|---|
className | false | string | |
variant | false | 'underlined' | 'underlined' | 'overlined' | 'ghost' | 'outlined' |
activeClassName | false | string | |
children | true | ReactNode |
Trigger
The Trigger
component represents an individual tab button or navigation link.
// Regular tab trigger<Tabs.Trigger value="tab1" // unique identifier for the tab icon="dashboard" // [OPTIONAL] icon name logo="github" // [OPTIONAL] logo name (mutually exclusive with icon) counter={5} // [OPTIONAL] counter badge value variant="underlined" // [OPTIONAL] override List variant className="my-class" // [OPTIONAL] custom class disabled // [OPTIONAL] disable the trigger> {/* Optional custom children */}</Tabs.Trigger>
// Navigation tab trigger<Tabs.Trigger value="/path" // route path linkProps={{ // [OPTIONAL] additional link properties target: "_blank", replace: true }}> Navigation Tab</Tabs.Trigger>
Prop | Required | Default | Type |
---|---|---|---|
className | false | string | |
variant | false | 'underlined' | 'overlined' | 'ghost' | 'outlined' | |
value | true | string | |
icon | false | string | |
logo | false | string | |
counter | false | number | null | |
disabled | false | false | boolean |
linkProps | false | Omit<NavLinkProps, 'to'> | |
children | false | ReactNode |
Content
The Content
component represents the panel content associated with a tab.
<Tabs.Content value="tab1" // matches the Trigger value className="my-class" // [OPTIONAL] custom class> {/* Panel content */}</Tabs.Content>
Prop | Required | Default | Type |
---|---|---|---|
className | false | string | |
value | true | string | |
children | true | ReactNode |
Best Practices
- Unique Values: Ensure each tab trigger has a unique
value
prop - Default Selection: Always provide either a
defaultValue
or controlledvalue
to ensure a tab is selected by default - Accessible Labels: Use descriptive text for tab triggers to ensure good accessibility
- Icon Usage: Choose between
icon
orlogo
props - don’t use both on the same trigger - Navigation Tabs: Use
NavRoot
when tabs represent different routes in your application - Content Loading: Consider lazy loading tab content for better performance with heavy content
- Keyboard Navigation: The component supports standard keyboard navigation (Arrow keys, Home, End)