From 01cbe2b7139ca5959f8ec85396924afdb5bbbe2c Mon Sep 17 00:00:00 2001 From: Defectink Date: Fri, 29 Apr 2022 17:06:03 +0800 Subject: [PATCH] Add custom tab component --- components/RUA/tab/index.tsx | 73 ++++++++++++++++++++++++++++++++++++ pages/about.tsx | 3 ++ 2 files changed, 76 insertions(+) create mode 100644 components/RUA/tab/index.tsx diff --git a/components/RUA/tab/index.tsx b/components/RUA/tab/index.tsx new file mode 100644 index 0000000..5db7a83 --- /dev/null +++ b/components/RUA/tab/index.tsx @@ -0,0 +1,73 @@ +import classNames from 'classnames'; +import React, { useState } from 'react'; +import { useCallback } from 'react'; + +type Props = { + defaultValue: string | number; + children: React.ReactElement[]; +}; + +const Tab = ({ defaultValue, children }: Props) => { + const [currentValue, setCurrentValue] = useState(defaultValue); + const handleSwitch = useCallback((value: ItemProps['value']) => { + setCurrentValue(value); + }, []); + + // Pass current selected state to child + const childrenWithProps = React.Children.map(children, (child) => { + if (React.isValidElement(child)) { + return React.cloneElement(child, { + showContent: child.props.value === currentValue, + }); + } + return child; + }); + + return ( + <> +
+
    + {children.map((child) => ( +
  • handleSwitch(child.props.value)} + className={classNames( + 'px-4 py-4 rounded-t-lg', + child.props.value === currentValue && + 'text-teal-500 border-b-[3px] border-teal-500', + 'select-none cursor-pointer', + 'min-w-[76px] text-center', + 'hover:bg-gray-200 dark:hover:bg-rua-gray-800' + )} + > + {child.props.label} +
  • + ))} +
+ +
{childrenWithProps}
+
+ + ); +}; + +type ItemProps = { + value: string | number; + label: string | number; + showContent?: boolean; + children?: React.ReactNode; +}; + +Tab.Item = function TabItem({ showContent, children }: ItemProps) { + return ( + <> +
+ {children} +
+ + ); +}; + +export default Tab; diff --git a/pages/about.tsx b/pages/about.tsx index 25721ad..8babd24 100644 --- a/pages/about.tsx +++ b/pages/about.tsx @@ -3,6 +3,9 @@ import { NextPageWithLayout } from 'types'; import avatar from 'public/images/img/avatar.svg'; import Image from 'next/image'; import classNames from 'classnames'; +import Tab from 'components/RUA/tab'; + +const TabItem = Tab.Item; const MainLayout = dynamic(() => import('layouts/MainLayout'));