From 717ff0fa27d8ad7cdd31f3001a321143a48a7891 Mon Sep 17 00:00:00 2001 From: sonnguyenkieio Date: Thu, 9 Sep 2021 15:42:19 +0700 Subject: [PATCH] :hammer: refactor: Tab Common --- .../common/TabCommon/TabCommon.module.scss | 46 +++---- src/components/common/TabCommon/TabCommon.tsx | 113 +++++++++++++----- .../components/TabItem/TabItem.module.scss | 13 ++ .../TabCommon/components/TabItem/TabItem.tsx | 31 +++++ .../components/TabPane/TabPane.module.scss | 23 ++++ .../TabCommon/components/TabPane/TabPane.tsx | 21 ++++ 6 files changed, 195 insertions(+), 52 deletions(-) create mode 100644 src/components/common/TabCommon/components/TabItem/TabItem.module.scss create mode 100644 src/components/common/TabCommon/components/TabItem/TabItem.tsx create mode 100644 src/components/common/TabCommon/components/TabPane/TabPane.module.scss create mode 100644 src/components/common/TabCommon/components/TabPane/TabPane.tsx diff --git a/src/components/common/TabCommon/TabCommon.module.scss b/src/components/common/TabCommon/TabCommon.module.scss index f794a841a..529d82f0d 100644 --- a/src/components/common/TabCommon/TabCommon.module.scss +++ b/src/components/common/TabCommon/TabCommon.module.scss @@ -1,22 +1,28 @@ + @import '../../../styles/utilities'; - -.tabCommon { - @apply flex; - position: relative; - border-bottom: 2px solid #FBFBFB; - padding-top: 1.6rem; - padding-bottom: 1.6rem; - width: 100%; - - .slider { - @apply inline-block; - height: .2rem; - border-radius: 3px; - background-color: var(--primary); - position: absolute; - z-index: 1200; - bottom: 0; - transition: all .4s linear; +.tabWapper{ + @apply flex flex-col w-full; + .tabHeader{ + @apply flex; + .tabList { + @apply flex; + position: relative; + border-bottom: 2px solid #FBFBFB; + padding: 0.8rem 0; + &.center{ + margin: auto; + } + + .slider { + @apply inline-block; + height: .2rem; + border-radius: 3px; + background-color: var(--primary); + position: absolute; + z-index: 1200; + bottom: 0; + transition: all .25s linear; + } + } } -} - +} \ No newline at end of file diff --git a/src/components/common/TabCommon/TabCommon.tsx b/src/components/common/TabCommon/TabCommon.tsx index 1b56d8a4b..9a65b7879 100644 --- a/src/components/common/TabCommon/TabCommon.tsx +++ b/src/components/common/TabCommon/TabCommon.tsx @@ -1,36 +1,85 @@ -import React, { RefObject, useEffect } from "react" -import s from './TabCommon.module.scss' - -import TabItem from './TabItem/TabItem' - -interface TabCommonProps { - tabs: {ref:RefObject, tabName: string, active: boolean, onClick: (tabIndex: number, tabPane?: string) => void}[]; - defaultActiveTab: number; - sliderRef : RefObject; - slideToTab: (ref: any) => void; -} - -const TabCommon = ({ tabs, defaultActiveTab, sliderRef, slideToTab } : TabCommonProps) => { - +import React, { + Children, + PropsWithChildren, + ReactElement, + useEffect, + useRef, + useState, + cloneElement, + } from 'react' + import s from './TabCommon.module.scss' + + import TabItem from './components/TabItem/TabItem' + import { TabPaneProps } from './components/TabPane/TabPane' + import classNames from 'classnames' + + interface TabCommonProps { + defaultActiveTab?: number + children: React.ReactNode + center?:boolean + } + + const TabCommon = ({ + defaultActiveTab = 0, + children, + center + }: TabCommonProps) => { + const [active, setActive] = useState(0) + const slider = useRef(null) + const headerRef = useRef(null) useEffect(() => { - slideToTab(tabs[defaultActiveTab].ref); + setActive(defaultActiveTab) }, []) - + + useEffect(() => { + slide(active) + }, [active]) + + function slide(index: number) { + const active = headerRef.current?.children + .item(index) + ?.getBoundingClientRect() + const header = headerRef.current?.getBoundingClientRect() + const current = slider.current + if (current && active && header) { + let width = active.width - 24 <= 0 ? 24 : active.width - 24 + let left = active.left - header.left + current.style.width = width.toString() + 'px' + current.style.left = left.toString() + 'px' + } + } + const onTabClick = (index: number) => { + setActive(index) + } return ( -
    - { - tabs.map((tab) => { - return ( -
  • - {tab.tabName} -
  • - ) - }) - } - -
    -
+
+
+
    + {Children.map(children, (tab, index) => { + let item = tab as ReactElement> + return ( +
  • + + {item.props.tabName} + +
  • + ) + })} +
    +
+
+
+ {Children.map(children, (tab, index) => { + let item = tab as ReactElement> + return cloneElement(item, { active:index===active }); + }) + }
+
) -} - -export default TabCommon; \ No newline at end of file + } + + export default TabCommon \ No newline at end of file diff --git a/src/components/common/TabCommon/components/TabItem/TabItem.module.scss b/src/components/common/TabCommon/components/TabItem/TabItem.module.scss new file mode 100644 index 000000000..e378955db --- /dev/null +++ b/src/components/common/TabCommon/components/TabItem/TabItem.module.scss @@ -0,0 +1,13 @@ +@import '../../../../../styles/utilities'; + +.tabItem { + margin-right:2.4rem; + padding: 0.8rem 0; + min-width: 2.4rem; + &:hover { + @apply cursor-pointer; + } + &.tabItemActive { + @apply font-bold; + } +} \ No newline at end of file diff --git a/src/components/common/TabCommon/components/TabItem/TabItem.tsx b/src/components/common/TabCommon/components/TabItem/TabItem.tsx new file mode 100644 index 000000000..fc9a20822 --- /dev/null +++ b/src/components/common/TabCommon/components/TabItem/TabItem.tsx @@ -0,0 +1,31 @@ +import classNames from 'classnames' +import React from 'react' +import s from './TabItem.module.scss' + +interface TabItemProps { + active: boolean + children: string + onClick?: (tabIndex: number) => void + tabIndex: number +} + +const TabItem = ({ + active = false, + children, + onClick, + tabIndex, +}: TabItemProps) => { + const handleClick = () => { + onClick && onClick(tabIndex) + } + return ( + + {children} + + ) +} + +export default TabItem \ No newline at end of file diff --git a/src/components/common/TabCommon/components/TabPane/TabPane.module.scss b/src/components/common/TabCommon/components/TabPane/TabPane.module.scss new file mode 100644 index 000000000..380472828 --- /dev/null +++ b/src/components/common/TabCommon/components/TabPane/TabPane.module.scss @@ -0,0 +1,23 @@ +@import "../../../../../styles/utilities"; +.tabPane { + @apply hidden; + transition: all 0.6s; + // animation-duration: 0.6s; + // animation-name: appear; + // @keyframes appear { + // from { + // margin-left: 100%; + // width: 200%; + // } + + // to { + // margin-left: 0%; + // width: 100%; + // } + // } + + + &.active { + @apply block; + } +} \ No newline at end of file diff --git a/src/components/common/TabCommon/components/TabPane/TabPane.tsx b/src/components/common/TabCommon/components/TabPane/TabPane.tsx new file mode 100644 index 000000000..c0c7d2efa --- /dev/null +++ b/src/components/common/TabCommon/components/TabPane/TabPane.tsx @@ -0,0 +1,21 @@ +import classNames from "classnames" +import React from "react" +import s from './TabPane.module.scss' + +export interface TabPaneProps { + active?: boolean; + children?: React.ReactNode; + tabName: string +} + +const TabPane = ({ active, children } : TabPaneProps) => { + return ( +
+ {children} +
+ ) +} + +export default TabPane \ No newline at end of file