56 lines
1.9 KiB
TypeScript
56 lines
1.9 KiB
TypeScript
import type { TabsProps } from 'react-aria-components';
|
|
import { Tab as AriaTab, TabList, TabPanel, TabPanels, Tabs } from 'react-aria-components';
|
|
|
|
import { twMerge } from 'tailwind-merge';
|
|
|
|
type TabItem = {
|
|
key: string;
|
|
label: React.ReactNode;
|
|
children: React.ReactNode;
|
|
disabled?: boolean;
|
|
};
|
|
|
|
// type TabProps = {
|
|
// items: TabItem[];
|
|
// activeKey?: string;
|
|
// onClick?: (key: string) => void;
|
|
// className?: string;
|
|
// };
|
|
|
|
/**
|
|
* @desc 탭 컴포넌트
|
|
* @param items 탭 아이템 목록
|
|
* @param activeKey 현재 활성화된 탭의 키
|
|
* @param onClick 탭 변경 이벤트
|
|
* @param className 추가 클래스명
|
|
*/
|
|
export interface TabProps extends Omit<TabsProps, 'className' | 'children'> {
|
|
className?: string;
|
|
items: TabItem[];
|
|
tabPanelClassName?: string;
|
|
tabPanelsClassName?: string;
|
|
}
|
|
export const Tab = ({ items, className, tabPanelClassName, tabPanelsClassName, ...restProps }: TabProps) => {
|
|
return (
|
|
<Tabs className={twMerge('flex flex-col gap-4', className)} {...restProps}>
|
|
<TabList className="flex items-center text-lg font-medium cursor-pointer" items={items}>
|
|
{(item) => (
|
|
<AriaTab
|
|
id={item.key}
|
|
className="relative px-7.5 text-dabeeo-black-47 data-[selected=true]:text-primary first:pl-1.5 data-[selected=true]:font-bold after:absolute after:right-0 after:top-1/2 after:-translate-y-1/2 after:h-[18px] after:w-px after:bg-gray-300 last:after:hidden outline-none data-focus-visible:ring-2 data-focus-visible:ring-offset-2 data-focus-visible:ring-primary"
|
|
>
|
|
{item.label}
|
|
</AriaTab>
|
|
)}
|
|
</TabList>
|
|
<TabPanels className={tabPanelsClassName} items={items}>
|
|
{(item) => (
|
|
<TabPanel id={item.key} className={tabPanelClassName}>
|
|
{item.children}
|
|
</TabPanel>
|
|
)}
|
|
</TabPanels>
|
|
</Tabs>
|
|
);
|
|
};
|