Tabs
A component used to display multiple views or sections of related content using tabbed navigation.
import { Tabs } from '@fidely-ui/react/tabs'
import { FaReact, FaVuejs } from 'react-icons/fa6'
import { RiSvelteLine } from 'react-icons/ri'
export const TabsBasics = () => {
return (
<Tabs.Root defaultValue="react">
<Tabs.List>
<Tabs.Trigger value="react">
<FaReact />
React
</Tabs.Trigger>
<Tabs.Trigger value="vue">
<FaVuejs />
Vue
</Tabs.Trigger>
<Tabs.Trigger value="svelte">
<RiSvelteLine />
Svelte
</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="react">
React is a free and open-source front-end JavaScript library
</Tabs.Content>
<Tabs.Content value="vue">
Vue is a progressive JavaScript framework for building user interfaces
</Tabs.Content>
<Tabs.Content value="svelte">
Svelte is a UI framework that uses a compiler to let you write
breathtakingly concise components
</Tabs.Content>
</Tabs.Root>
)
}
Usage
import { Tabs } from '@fidely-ui/react'<Tabs.Root>
<Tabs.List>
<Tabs.Trigger />
<Tabs.Indicator />
</Tabs.List>
<Tabs.Content />
</Tabs.Root>Examples
Variants
Use the variant prop to change the visual style of the tabs.
import { Flex, Tabs } from '@fidely-ui/react'
export const TabsVariants = () => {
const variants = ['outline', 'underline'] as const
return (
<Flex flexDirection={{ base: 'column', md: 'row' }} gap={3}>
{variants.map((variant) => (
<Tabs.Root key={variant} variant={variant} defaultValue="teams">
<Tabs.List>
<Tabs.Trigger value="teams">Teams</Tabs.Trigger>
<Tabs.Trigger value="projects">Projects</Tabs.Trigger>
<Tabs.Trigger value="overview">Overview</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="teams">Manage your team members</Tabs.Content>
<Tabs.Content value="projects">Manage your projects</Tabs.Content>
<Tabs.Content value="overview">
Manage your teams overview
</Tabs.Content>
</Tabs.Root>
))}
</Flex>
)
}
Sizes
Use the size prop to adjust the spacing and font size of the tabs.
import { Stack, Tabs } from '@fidely-ui/react'
export const TabsSizes = () => {
const sizes = ['sm', 'md', 'lg'] as const
return (
<Stack gap={6}>
{sizes.map((size) => (
<Tabs.Root key={size} size={size} defaultValue="teams">
<Tabs.List bg={'bg.muted'} rounded={'s2'}>
<Tabs.Trigger value="teams">Teams</Tabs.Trigger>
<Tabs.Trigger value="projects">Projects</Tabs.Trigger>
<Tabs.Trigger value="overview">Overview</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="teams">Manage your team members</Tabs.Content>
<Tabs.Content value="projects">Manage your projects</Tabs.Content>
<Tabs.Content value="overview">
Manage your teams overview
</Tabs.Content>
</Tabs.Root>
))}
</Stack>
)
}
Disabled
Set the disabled prop on the Tabs.Trigger component to disable a tab
import { Tabs } from '@fidely-ui/react/tabs'
import { LuFolder, LuSquareCheck, LuUser } from 'react-icons/lu'
export const TabsDisabled = () => {
return (
<Tabs.Root defaultValue="members">
<Tabs.List>
<Tabs.Trigger value="members">
<LuUser />
Members
</Tabs.Trigger>
<Tabs.Trigger value="projects">
<LuFolder />
Projects
</Tabs.Trigger>
<Tabs.Trigger value="tasks" disabled>
<LuSquareCheck />
Settings
</Tabs.Trigger>
<Tabs.Indicator rounded="l2" />
</Tabs.List>
<Tabs.Content value="members">Manage your team members</Tabs.Content>
<Tabs.Content value="projects">Manage your projects</Tabs.Content>
<Tabs.Content value="tasks">
Manage your tasks for freelancers
</Tabs.Content>
</Tabs.Root>
)
}
Manual Activation
By default, tabs are automatically selected when navigated with arrow keys.
Set activationBehavior prop to manual on Tabs.Root to disable this behavior — tabs will only activate when clicked or when pressing Enter.
import { Tabs } from '@fidely-ui/react/tabs'
import { LuFolder, LuSquareCheck, LuUser } from 'react-icons/lu'
export const TabsManual = () => {
return (
<Tabs.Root defaultValue="members" activationMode="manual">
<Tabs.List>
<Tabs.Trigger value="members">
<LuUser />
Members
</Tabs.Trigger>
<Tabs.Trigger value="projects">
<LuFolder />
Projects
</Tabs.Trigger>
<Tabs.Trigger value="tasks">
<LuSquareCheck />
Settings
</Tabs.Trigger>
<Tabs.Indicator rounded="l2" />
</Tabs.List>
{/* contents */}
</Tabs.Root>
)
}
Store (State Managed)
An alternative way to control the Tabs is to use the RootProvider component and the useTabs store hook.
This way you can access the tabs state and methods from outside the tabs.
selected: teams
'use client'
import { Stack, Text, Tabs, useTabs } from '@fidely-ui/react'
import { LuFolder, LuSquareCheck, LuUser } from 'react-icons/lu'
export const TabsStore = () => {
const tabs = useTabs({ defaultValue: 'teams' })
return (
<Stack alignItems="flex-start">
<Tabs.RootProvider value={tabs}>
<Tabs.List>
<Tabs.Trigger value="teams">
<LuUser />
Teams
</Tabs.Trigger>
<Tabs.Trigger value="projects">
<LuFolder />
Projects
</Tabs.Trigger>
<Tabs.Trigger value="tasks">
<LuSquareCheck />
Tasks
</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="teams">Manage your team members</Tabs.Content>
<Tabs.Content value="projects">Manage your projects</Tabs.Content>
<Tabs.Content value="tasks">
Manage your tasks for freelancers
</Tabs.Content>
</Tabs.RootProvider>
<Text>selected: {tabs.value}</Text>
</Stack>
)
}
Controlled Tabs
Use the value and onValueChange prop to control the active tab.
'use client'
import { useState } from 'react'
import { Tabs } from '@fidely-ui/react/tabs'
export const TabsControlled = () => {
const [value, setValue] = useState<string | null>('first')
return (
<Tabs.Root value={value} onValueChange={(e) => setValue(e.value)}>
<Tabs.List>
<Tabs.Trigger value="first">First tab</Tabs.Trigger>
<Tabs.Trigger value="second">Second tab</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="first">First panel</Tabs.Content>
<Tabs.Content value="second">Second panel</Tabs.Content>
</Tabs.Root>
)
}
With Links
Pass the asChild to the Tabs.Trigger component to render a link as a tab. When a tab is clicked, the link will be navigated to.
import { Tabs } from '@fidely-ui/react/tabs'
import { LuFolder, LuSquareCheck, LuUser } from 'react-icons/lu'
export const TabsLinks = () => {
return (
<Tabs.Root defaultValue="members">
<Tabs.List>
<Tabs.Trigger value="members" asChild>
<a href="#members">
<LuUser />
Members
</a>
</Tabs.Trigger>
<Tabs.Trigger value="projects" asChild>
<a href="#projects">
<LuFolder />
Projects
</a>
</Tabs.Trigger>
<Tabs.Trigger value="settings" asChild>
<a href="#settings">
<LuSquareCheck />
Settings
</a>
</Tabs.Trigger>
<Tabs.Indicator rounded="l2" />
</Tabs.List>
{/* contents */}
</Tabs.Root>
)
}
Props
Root
| Prop | Type | Default | Description |
|---|---|---|---|
defaultValue | string | — | The tab value to activate by default. |
activationMode | "automatic" \ "manual" | automatic | The activation mode of the tabs. Can be manual or automatic - manual: Tabs are activated when clicked or press enter key. - automatic: Tabs are activated when receiving focus |
value | string | — | The controlled value of the active tab.. |
onValueChange | (value: string) => void | — | Callback fired when a tab value changes.. |
lazyMount | boolean | false | Whether to enable lazy mounting. |
loopFocus | boolean | false | Whether the keyboard navigation will loop from last tab to first, and vice versa. |
Tabs.List
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | Passes props to a custom child element. |
Tabs.Trigger
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | — | The value associated with this tab trigger. |
disabled | boolean | false | Disables interaction with the tab. |
asChild | boolean | false | Renders a custom element instead of the default button. |
Tabs.Content
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | - | The value associated with this content panel. |
asChild | boolean | false | Renders a custom element instead of the default container. |