admin/components/heroui/Tabs.tsx
alisaza e1eaf5eff5 feat: initial ghabilee-admin backoffice app
Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js
app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
2026-09-05 13:12:59 +03:30

109 lines
2.7 KiB
TypeScript

'use client'
import type { ComponentProps, ReactElement, ReactNode } from 'react'
import { Children, isValidElement } from 'react'
import { Tabs as HeroTabs } from '@heroui/react'
export interface TabsClassNames {
base?: string
tabList?: string
tab?: string
tabContent?: string
cursor?: string
panel?: string
tabWrapper?: string
}
export type TabsProps = Omit<ComponentProps<typeof HeroTabs>, 'children' | 'className' | 'variant'> & {
children?: ReactNode
className?: string
classNames?: TabsClassNames
color?: string
fullWidth?: boolean
placement?: string
size?: 'sm' | 'md' | 'lg'
variant?: 'solid' | 'bordered' | 'light' | 'underlined'
}
interface LegacyTabProps {
children?: ReactNode
title: ReactNode
}
export function Tab(_props: LegacyTabProps) {
return null
}
function getLegacyTabs(children: ReactNode): ReactElement<LegacyTabProps>[] {
return Children.toArray(children).filter((child): child is ReactElement<LegacyTabProps> => isValidElement<LegacyTabProps>(child))
}
function tabId(tab: ReactElement<LegacyTabProps>, index: number): string {
if (tab.key == null) return String(index)
const key = String(tab.key)
return key.startsWith('.$') ? key.slice(2) : key
}
export function Tabs({
children,
className,
classNames,
fullWidth,
size: _size,
color: _color,
placement: _placement,
variant,
...props
}: TabsProps) {
const tabs = getLegacyTabs(children)
const mappedVariant = variant === 'light' || variant === 'underlined' ? 'secondary' : 'primary'
return (
<HeroTabs
className={`${fullWidth ? 'w-full' : ''} ${classNames?.base ?? ''} ${className ?? ''}`.trim()}
variant={mappedVariant}
{...props}
>
<HeroTabs.ListContainer className={classNames?.tabWrapper}>
<HeroTabs.List
aria-label={props['aria-label']}
className={classNames?.tabList}
>
{tabs.map((tab, index) => {
const id = tabId(tab, index)
return (
<HeroTabs.Tab
key={id}
className={classNames?.tab}
id={id}
>
<span className={classNames?.tabContent}>{tab.props.title}</span>
<HeroTabs.Indicator className={classNames?.cursor} />
</HeroTabs.Tab>
)
})}
</HeroTabs.List>
</HeroTabs.ListContainer>
{tabs.map((tab, index) => {
if (tab.props.children === undefined) return null
const id = tabId(tab, index)
return (
<HeroTabs.Panel
key={id}
className={classNames?.panel}
id={id}
>
{tab.props.children}
</HeroTabs.Panel>
)
})}
</HeroTabs>
)
}