Code
import { createContext, useContext, ReactNode } from 'react'
interface TabsContext {
activeTab: string
setActiveTab: (id: string) => void
}
const TabsContext = createContext<TabsContext | null>(null)
function Tabs({ children }: { children: ReactNode }) {
const [activeTab, setActiveTab] = useState('')
return (
<TabsContext.Provider value={{ activeTab, setActiveTab }}>
{children}
</TabsContext.Provider>
)
}
function TabList({ children }: { children: ReactNode }) {
return <div role="tablist">{children}</div>
}
function Tab({ id, children }: { id: string; children: ReactNode }) {
const context = useContext(TabsContext)
if (!context) throw new Error('Tab must be used within Tabs')
const { activeTab, setActiveTab } = context
return (
<button
role="tab"
aria-selected={activeTab === id}
onClick={() => setActiveTab(id)}
>
{children}
</button>
)
}
function TabPanel({ id, children }: { id: string; children: ReactNode }) {
const context = useContext(TabsContext)
if (!context) throw new Error('TabPanel must be used within Tabs')
return context.activeTab === id ? <div>{children}</div> : null
}
// Usage
<Tabs>
<TabList>
<Tab id="tab1">Tab 1</Tab>
<Tab id="tab2">Tab 2</Tab>
</TabList>
<TabPanel id="tab1">Content 1</TabPanel>
<TabPanel id="tab2">Content 2</TabPanel>
</Tabs>