mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 17:35:10 +03:00
## Problem Now that we migrated all usages of the deprecated `Tabs` component, we don't need the `_Shadcn_` suffix anymore. ## Solution Remove `_Shadcn_` suffix from `ui` tabs components. That's all this PR does, no visual nor functional changes <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Standardized tab components across the app so pages and dialogs now use the same consistent tab UI. * Improved tab-based views in design, docs, studio, learn, and website experiences for a more uniform interface. * **Chores** * Updated shared UI exports to expose tab components directly, simplifying future usage across the product. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
74 lines
2.0 KiB
TypeScript
74 lines
2.0 KiB
TypeScript
'use client'
|
|
|
|
import { useEffect, useState } from 'react'
|
|
import { cn, TabsContent, TabsList, TabsTrigger, Tabs as UITabs } from 'ui'
|
|
|
|
export interface TabsProps {
|
|
children: React.ReactNode
|
|
className?: string
|
|
defaultActiveId?: string
|
|
listClassNames?: string
|
|
}
|
|
|
|
export interface TabPanelProps {
|
|
children: React.ReactNode
|
|
id: string
|
|
label: string
|
|
className?: string
|
|
}
|
|
|
|
function Tabs({ children, className, defaultActiveId, listClassNames }: TabsProps) {
|
|
const [mounted, setMounted] = useState(false)
|
|
const [activeTab, setActiveTab] = useState(defaultActiveId)
|
|
|
|
useEffect(() => {
|
|
setMounted(true)
|
|
}, [])
|
|
|
|
if (!mounted) return null
|
|
|
|
// Extract tab panels from children
|
|
const tabPanels = Array.isArray(children) ? children : [children]
|
|
const validTabPanels = tabPanels.filter(
|
|
(child) => child && typeof child === 'object' && 'props' in child && child.props.id
|
|
)
|
|
|
|
if (validTabPanels.length === 0) return null
|
|
|
|
const currentActiveTab = activeTab || validTabPanels[0]?.props?.id
|
|
|
|
return (
|
|
<div className={cn('not-prose', className)}>
|
|
<UITabs
|
|
value={currentActiveTab}
|
|
onValueChange={setActiveTab}
|
|
className="w-full flex flex-col gap-4 [&_.ch-codeblock]:mt-0!"
|
|
>
|
|
<TabsList className={cn('shiki-wrapper flex', listClassNames)}>
|
|
{validTabPanels.map((panel) => (
|
|
<TabsTrigger key={panel.props.id} value={panel.props.id} className="text-xs px-2.5">
|
|
{panel.props.label}
|
|
</TabsTrigger>
|
|
))}
|
|
</TabsList>
|
|
{validTabPanels.map((panel) => (
|
|
<TabsContent key={panel.props.id} value={panel.props.id} className="mt-0">
|
|
{panel.props.children}
|
|
</TabsContent>
|
|
))}
|
|
</UITabs>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function TabPanel({ children, id, label, className }: TabPanelProps) {
|
|
return (
|
|
<div className={cn('tab-panel', className)} data-id={id} data-label={label}>
|
|
{children}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export { Tabs, TabPanel }
|
|
export default Tabs
|