From 0493df2e751963447fd32267c7cf658155d998de Mon Sep 17 00:00:00 2001 From: shayan khaleghparast Date: Tue, 16 Jan 2024 12:12:46 +0800 Subject: [PATCH 1/8] feat: added tab component --- .../PrimaryTabs/PrimaryTabList.scss | 33 +++++ lib/components/PrimaryTabs/PrimaryTabList.tsx | 29 ++++ .../PrimaryTabs/PrimaryTabPanel.tsx | 7 + .../PrimaryTabs/PrimaryTabPanels.tsx | 18 +++ lib/components/PrimaryTabs/PrimaryTabs.tsx | 34 +++++ lib/components/PrimaryTabs/index.ts | 6 + lib/components/Tabs/Tab.tsx | 11 ++ lib/components/Tabs/TabTitle.tsx | 31 ++++ lib/components/Tabs/Tabs.scss | 25 ++++ lib/components/Tabs/Tabs.tsx | 33 +++++ lib/components/Tabs/index.tsx | 2 + lib/main.ts | 4 +- package-lock.json | 132 +++++++++--------- src/main.tsx | 30 +++- 14 files changed, 326 insertions(+), 69 deletions(-) create mode 100644 lib/components/PrimaryTabs/PrimaryTabList.scss create mode 100644 lib/components/PrimaryTabs/PrimaryTabList.tsx create mode 100644 lib/components/PrimaryTabs/PrimaryTabPanel.tsx create mode 100644 lib/components/PrimaryTabs/PrimaryTabPanels.tsx create mode 100644 lib/components/PrimaryTabs/PrimaryTabs.tsx create mode 100644 lib/components/PrimaryTabs/index.ts create mode 100644 lib/components/Tabs/Tab.tsx create mode 100644 lib/components/Tabs/TabTitle.tsx create mode 100644 lib/components/Tabs/Tabs.scss create mode 100644 lib/components/Tabs/Tabs.tsx create mode 100644 lib/components/Tabs/index.tsx diff --git a/lib/components/PrimaryTabs/PrimaryTabList.scss b/lib/components/PrimaryTabs/PrimaryTabList.scss new file mode 100644 index 00000000..65a409cf --- /dev/null +++ b/lib/components/PrimaryTabs/PrimaryTabList.scss @@ -0,0 +1,33 @@ +.derivs-tabs { + &-list { + display: grid; + grid-auto-columns: 1fr; + position: relative; + background-color: #f2f3f4; + height: 5rem; + border-radius: 0.7rem; + + &-item { + background: inherit; + border: none; + grid-row: 1; + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; + font-size: 1.6rem; + + &--active { + font-weight: bold; + background-color: #ffffff; + margin: 0.6rem; + border-radius: 0.5rem; + color: var(--system-light-1-prominent-text, #333); + } + + &--disabled { + color: #999999; + } + } + } +} diff --git a/lib/components/PrimaryTabs/PrimaryTabList.tsx b/lib/components/PrimaryTabs/PrimaryTabList.tsx new file mode 100644 index 00000000..772961b1 --- /dev/null +++ b/lib/components/PrimaryTabs/PrimaryTabList.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import { useTabs } from './PrimaryTabs'; +import './PrimaryTabList.scss'; + +type PrimaryTabListProps = { + list: string[]; +}; + +const PrimaryTabList = ({ list }: PrimaryTabListProps) => { + const { activeTabIndex, setActiveTabIndex } = useTabs(); + + return ( +
+ {list.map((tab, i) => ( + + ))} +
+ ); +}; + +export default PrimaryTabList; diff --git a/lib/components/PrimaryTabs/PrimaryTabPanel.tsx b/lib/components/PrimaryTabs/PrimaryTabPanel.tsx new file mode 100644 index 00000000..3b773d4f --- /dev/null +++ b/lib/components/PrimaryTabs/PrimaryTabPanel.tsx @@ -0,0 +1,7 @@ +import React from 'react'; + +const PrimaryTabPanel = ({ children }: React.PropsWithChildren) => { + return
{children}
; +}; + +export default PrimaryTabPanel; diff --git a/lib/components/PrimaryTabs/PrimaryTabPanels.tsx b/lib/components/PrimaryTabs/PrimaryTabPanels.tsx new file mode 100644 index 00000000..30ebaa3b --- /dev/null +++ b/lib/components/PrimaryTabs/PrimaryTabPanels.tsx @@ -0,0 +1,18 @@ +import React, { Children } from 'react'; +import { useTabs } from './PrimaryTabs'; + +const PrimaryTabPanels = ({ children }: React.PropsWithChildren) => { + const { activeTabIndex } = useTabs(); + + return ( +
+ {Children.map(children, (child, index) => { + if (index !== activeTabIndex) return undefined; + + return child; + })} +
+ ); +}; + +export default PrimaryTabPanels; diff --git a/lib/components/PrimaryTabs/PrimaryTabs.tsx b/lib/components/PrimaryTabs/PrimaryTabs.tsx new file mode 100644 index 00000000..4e368608 --- /dev/null +++ b/lib/components/PrimaryTabs/PrimaryTabs.tsx @@ -0,0 +1,34 @@ +import React, { createContext, useContext, useState } from 'react'; + +type TTabContext = { + activeTabIndex: number; + setActiveTabIndex: React.Dispatch>; +}; + +const TabsContext = createContext(null); + +export const useTabs = () => { + const context = useContext(TabsContext); + + if (!context) { + throw new Error('Seems you forgot to wrap the components in ""'); + } + + return context; +}; + +type TTabsProps = { + className?: string; +}; + +export const PrimaryTabs = ({ children, className }: React.PropsWithChildren) => { + const [activeTabIndex, setActiveTabIndex] = useState(0); + + return ( + +
{children}
+
+ ); +}; + +export default PrimaryTabs; diff --git a/lib/components/PrimaryTabs/index.ts b/lib/components/PrimaryTabs/index.ts new file mode 100644 index 00000000..e3a3bfdd --- /dev/null +++ b/lib/components/PrimaryTabs/index.ts @@ -0,0 +1,6 @@ +import PrimaryTabList from './PrimaryTabList'; +import PrimaryTabPanel from './PrimaryTabPanel'; +import PrimaryTabPanels from './PrimaryTabPanels'; +import PrimaryTabs from './PrimaryTabs'; + +export { PrimaryTabList, PrimaryTabPanel, PrimaryTabPanels, PrimaryTabs }; diff --git a/lib/components/Tabs/Tab.tsx b/lib/components/Tabs/Tab.tsx new file mode 100644 index 00000000..ab7727f9 --- /dev/null +++ b/lib/components/Tabs/Tab.tsx @@ -0,0 +1,11 @@ +import React, { FC, ReactNode } from 'react'; + +type TabProps = { + children: ReactNode; + icon?: ReactNode; + title: string; +}; + +const Tab: FC = ({ children }) => <>{children}; + +export default Tab; diff --git a/lib/components/Tabs/TabTitle.tsx b/lib/components/Tabs/TabTitle.tsx new file mode 100644 index 00000000..ceaeb873 --- /dev/null +++ b/lib/components/Tabs/TabTitle.tsx @@ -0,0 +1,31 @@ +import React, { FC, useCallback } from 'react'; +import classNames from 'classnames'; +import { Text } from '../Text'; + +export type TabTitleProps = { + icon?: React.ReactNode; + index: number; + isActive?: boolean; + setSelectedTab: (index: number) => void; + title: string; +}; + +const TabTitle: FC = ({ icon, index, isActive, setSelectedTab, title }) => { + const handleOnClick = useCallback(() => { + setSelectedTab(index); + }, [setSelectedTab, index]); + + return ( + + ); +}; + +export default TabTitle; diff --git a/lib/components/Tabs/Tabs.scss b/lib/components/Tabs/Tabs.scss new file mode 100644 index 00000000..981999cb --- /dev/null +++ b/lib/components/Tabs/Tabs.scss @@ -0,0 +1,25 @@ +.derivs-tabs { + display: flex; + justify-content: center; + width: 100%; + + &__btn { + display: inline-flex; + gap: 0.8rem; + align-items: center; + justify-content: center; + width: 50%; + border: none; + border-bottom: 0.2rem solid var(--light-7-secondary-background, #f2f3f4); + background: none; + padding: 1rem 0; + cursor: pointer; + &--active { + width: 50%; + border: none; + border-bottom: 0.2rem solid var(--brand-coral, #ff444f); + background: none; + padding: 1rem 0; + } + } +} diff --git a/lib/components/Tabs/Tabs.tsx b/lib/components/Tabs/Tabs.tsx new file mode 100644 index 00000000..e6e88c19 --- /dev/null +++ b/lib/components/Tabs/Tabs.tsx @@ -0,0 +1,33 @@ +import React, { FC, ReactElement, useState } from 'react'; +import TabTitle, { TabTitleProps } from './TabTitle'; +import './Tabs.scss'; + +type TabsProps = { + children: ReactElement[]; + preSelectedTab?: number; + wrapperClassName?: string; +}; + +const Tabs: FC = ({ children, preSelectedTab, wrapperClassName }): JSX.Element => { + const [selectedTabIndex, setSelectedTabIndex] = useState(preSelectedTab || 0); + + return ( +
+
+ {children.map((item, index) => ( + + ))} +
+ {children[selectedTabIndex]} +
+ ); +}; + +export default Tabs; diff --git a/lib/components/Tabs/index.tsx b/lib/components/Tabs/index.tsx new file mode 100644 index 00000000..850dae89 --- /dev/null +++ b/lib/components/Tabs/index.tsx @@ -0,0 +1,2 @@ +export { default as Tab } from './Tab'; +export { default as Tabs } from './Tabs'; diff --git a/lib/main.ts b/lib/main.ts index 05e4661d..18dbcecc 100644 --- a/lib/main.ts +++ b/lib/main.ts @@ -1,3 +1,5 @@ export { Loader } from './components/Loader' export { Button } from './components/Button' -export { Text } from './components/Text' \ No newline at end of file +export { Text } from './components/Text' +export { Tab, Tabs } from './components/Tabs' +export { PrimaryTabList, PrimaryTabPanel, PrimaryTabPanels, PrimaryTabs } from './components/PrimaryTabs' \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index e874a0f7..689cd39e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1455,9 +1455,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.11.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.1.tgz", - "integrity": "sha512-DsXojJUES2M+FE8CpptJTKpg+r54moV9ZEncPstni1WHFmTcCzeFLnMFfyhCVS8XNOy/OQG+8lVxRLRrVHmV5A==", + "version": "20.11.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.3.tgz", + "integrity": "sha512-nrlmbvGPNGaj84IJZXMPhQuCMEVTT/hXZMJJG/aIqVL9fKxqk814sGGtJA4GI6hpJSLQjpi6cn0Qx9eOf9SDVg==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -1470,9 +1470,9 @@ "dev": true }, "node_modules/@types/react": { - "version": "18.2.47", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.47.tgz", - "integrity": "sha512-xquNkkOirwyCgoClNk85BjP+aqnIS+ckAJ8i37gAbDs14jfW/J23f2GItAf33oiUPQnqNMALiFeoM9Y5mbjpVQ==", + "version": "18.2.48", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.48.tgz", + "integrity": "sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==", "dev": true, "dependencies": { "@types/prop-types": "*", @@ -1502,16 +1502,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.18.1.tgz", - "integrity": "sha512-nISDRYnnIpk7VCFrGcu1rnZfM1Dh9LRHnfgdkjcbi/l7g16VYRri3TjXi9Ir4lOZSw5N/gnV/3H7jIPQ8Q4daA==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.19.0.tgz", + "integrity": "sha512-DUCUkQNklCQYnrBSSikjVChdc84/vMPDQSgJTHBZ64G9bA9w0Crc0rd2diujKbTdp6w2J47qkeHQLoi0rpLCdg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.18.1", - "@typescript-eslint/type-utils": "6.18.1", - "@typescript-eslint/utils": "6.18.1", - "@typescript-eslint/visitor-keys": "6.18.1", + "@typescript-eslint/scope-manager": "6.19.0", + "@typescript-eslint/type-utils": "6.19.0", + "@typescript-eslint/utils": "6.19.0", + "@typescript-eslint/visitor-keys": "6.19.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1537,15 +1537,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.18.1.tgz", - "integrity": "sha512-zct/MdJnVaRRNy9e84XnVtRv9Vf91/qqe+hZJtKanjojud4wAVy/7lXxJmMyX6X6J+xc6c//YEWvpeif8cAhWA==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.19.0.tgz", + "integrity": "sha512-1DyBLG5SH7PYCd00QlroiW60YJ4rWMuUGa/JBV0iZuqi4l4IK3twKPq5ZkEebmGqRjXWVgsUzfd3+nZveewgow==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.18.1", - "@typescript-eslint/types": "6.18.1", - "@typescript-eslint/typescript-estree": "6.18.1", - "@typescript-eslint/visitor-keys": "6.18.1", + "@typescript-eslint/scope-manager": "6.19.0", + "@typescript-eslint/types": "6.19.0", + "@typescript-eslint/typescript-estree": "6.19.0", + "@typescript-eslint/visitor-keys": "6.19.0", "debug": "^4.3.4" }, "engines": { @@ -1565,13 +1565,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.1.tgz", - "integrity": "sha512-BgdBwXPFmZzaZUuw6wKiHKIovms97a7eTImjkXCZE04TGHysG+0hDQPmygyvgtkoB/aOQwSM/nWv3LzrOIQOBw==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.0.tgz", + "integrity": "sha512-dO1XMhV2ehBI6QN8Ufi7I10wmUovmLU0Oru3n5LVlM2JuzB4M+dVphCPLkVpKvGij2j/pHBWuJ9piuXx+BhzxQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.1", - "@typescript-eslint/visitor-keys": "6.18.1" + "@typescript-eslint/types": "6.19.0", + "@typescript-eslint/visitor-keys": "6.19.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1582,13 +1582,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.18.1.tgz", - "integrity": "sha512-wyOSKhuzHeU/5pcRDP2G2Ndci+4g653V43gXTpt4nbyoIOAASkGDA9JIAgbQCdCkcr1MvpSYWzxTz0olCn8+/Q==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.19.0.tgz", + "integrity": "sha512-mcvS6WSWbjiSxKCwBcXtOM5pRkPQ6kcDds/juxcy/727IQr3xMEcwr/YLHW2A2+Fp5ql6khjbKBzOyjuPqGi/w==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.18.1", - "@typescript-eslint/utils": "6.18.1", + "@typescript-eslint/typescript-estree": "6.19.0", + "@typescript-eslint/utils": "6.19.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1609,9 +1609,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.1.tgz", - "integrity": "sha512-4TuMAe+tc5oA7wwfqMtB0Y5OrREPF1GeJBAjqwgZh1lEMH5PJQgWgHGfYufVB51LtjD+peZylmeyxUXPfENLCw==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.0.tgz", + "integrity": "sha512-lFviGV/vYhOy3m8BJ/nAKoAyNhInTdXpftonhWle66XHAtT1ouBlkjL496b5H5hb8dWXHwtypTqgtb/DEa+j5A==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1622,13 +1622,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.1.tgz", - "integrity": "sha512-fv9B94UAhywPRhUeeV/v+3SBDvcPiLxRZJw/xZeeGgRLQZ6rLMG+8krrJUyIf6s1ecWTzlsbp0rlw7n9sjufHA==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.0.tgz", + "integrity": "sha512-o/zefXIbbLBZ8YJ51NlkSAt2BamrK6XOmuxSR3hynMIzzyMY33KuJ9vuMdFSXW+H0tVvdF9qBPTHA91HDb4BIQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.1", - "@typescript-eslint/visitor-keys": "6.18.1", + "@typescript-eslint/types": "6.19.0", + "@typescript-eslint/visitor-keys": "6.19.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1650,17 +1650,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.1.tgz", - "integrity": "sha512-zZmTuVZvD1wpoceHvoQpOiewmWu3uP9FuTWo8vqpy2ffsmfCE8mklRPi+vmnIYAIk9t/4kOThri2QCDgor+OpQ==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.0.tgz", + "integrity": "sha512-QR41YXySiuN++/dC9UArYOg4X86OAYP83OWTewpVx5ct1IZhjjgTLocj7QNxGhWoTqknsgpl7L+hGygCO+sdYw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.18.1", - "@typescript-eslint/types": "6.18.1", - "@typescript-eslint/typescript-estree": "6.18.1", + "@typescript-eslint/scope-manager": "6.19.0", + "@typescript-eslint/types": "6.19.0", + "@typescript-eslint/typescript-estree": "6.19.0", "semver": "^7.5.4" }, "engines": { @@ -1675,12 +1675,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.1.tgz", - "integrity": "sha512-/kvt0C5lRqGoCfsbmm7/CwMqoSkY3zzHLIjdhHZQW3VFrnz7ATecOHR7nb7V+xn4286MBxfnQfQhAmCI0u+bJA==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.0.tgz", + "integrity": "sha512-hZaUCORLgubBvtGpp1JEFEazcuEdfxta9j4iUwdSAr7mEsYYAp3EAUyCZk3VEEqGj6W+AV4uWyrDGtrlawAsgQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/types": "6.19.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1745,26 +1745,26 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.4.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.13.tgz", - "integrity": "sha512-zGUdmB3j3Irn9z51GXLJ5s0EAHxmsm5/eXl0y6MBaajMeOAaiT4+zaDoxui4Ets98dwIRr8BBaqXXHtHSfm+KA==", + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.14.tgz", + "integrity": "sha512-ro4Zzl/MPdWs7XwxT7omHRxAjMbDFRZEEjD+2m3NBf8YzAe3HuoSEZosXQo+m1GQ1G3LQ1LdmNh1RKTYe+ssEg==", "dev": true, "dependencies": { "@babel/parser": "^7.23.6", - "@vue/shared": "3.4.13", + "@vue/shared": "3.4.14", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.0.2" } }, "node_modules/@vue/compiler-dom": { - "version": "3.4.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.13.tgz", - "integrity": "sha512-XSNbpr5Rs3kCfVAmBqMu/HDwOS+RL6y28ZZjDlnDUuf146pRWt2sQkwhsOYc9uu2lxjjJy2NcyOkK7MBLVEc7w==", + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.14.tgz", + "integrity": "sha512-nOZTY+veWNa0DKAceNWxorAbWm0INHdQq7cejFaWM1WYnoNSJbSEKYtE7Ir6lR/+mo9fttZpPVI9ZFGJ1juUEQ==", "dev": true, "dependencies": { - "@vue/compiler-core": "3.4.13", - "@vue/shared": "3.4.13" + "@vue/compiler-core": "3.4.14", + "@vue/shared": "3.4.14" } }, "node_modules/@vue/language-core": { @@ -1793,9 +1793,9 @@ } }, "node_modules/@vue/shared": { - "version": "3.4.13", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.13.tgz", - "integrity": "sha512-56crFKLPpzk85WXX1L1c0QzPOuoapWlPVys8eMG8kkRmqdMjWUqK8KpFdE2d7BQA4CEbXwyyHPq6MpFr8H9rcg==", + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.14.tgz", + "integrity": "sha512-nmi3BtLpvqXAWoRZ6HQ+pFJOHBU4UnH3vD3opgmwXac7vhaHKA9nj1VeGjMggdB9eLtW83eHyPCmOU1qzdsC7Q==", "dev": true }, "node_modules/@webassemblyjs/ast": { @@ -2394,9 +2394,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.630", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.630.tgz", - "integrity": "sha512-osHqhtjojpCsACVnuD11xO5g9xaCyw7Qqn/C2KParkMv42i8jrJJgx3g7mkHfpxwhy9MnOJr8+pKOdZ7qzgizg==", + "version": "1.4.632", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.632.tgz", + "integrity": "sha512-JGmudTwg7yxMYvR/gWbalqqQiyu7WTFv2Xu3vw4cJHXPFxNgAk0oy8UHaer8nLF4lZJa+rNoj6GsrKIVJTV6Tw==", "dev": true }, "node_modules/emoji-regex": { @@ -4675,9 +4675,9 @@ } }, "node_modules/vite-plugin-dts": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/vite-plugin-dts/-/vite-plugin-dts-3.7.0.tgz", - "integrity": "sha512-np1uPaYzu98AtPReB8zkMnbjwcNHOABsLhqVOf81b3ol9b5M2wPcAVs8oqPnOpr6Us+7yDXVauwkxsk5+ldmRA==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/vite-plugin-dts/-/vite-plugin-dts-3.7.1.tgz", + "integrity": "sha512-VZJckNFpVfRAkmOxhGT5OgTUVWVXxkNQqLpBUuiNGAr9HbtvmvsPLo2JB3Xhn+o/Z9+CT6YZfYa4bX9SGR5hNw==", "dev": true, "dependencies": { "@microsoft/api-extractor": "7.39.0", diff --git a/src/main.tsx b/src/main.tsx index 74cea1fa..0404512f 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,8 +1,10 @@ import React from 'react' import ReactDOM from 'react-dom/client' import { Loader } from '../dist/components/Loader'; -import {Button} from '../dist/components/Button'; -import {Text} from '../dist/components/Text'; +import { Button } from '../dist/components/Button'; +import { Text } from '../dist/components/Text'; +import { Tabs, Tab } from '../dist/components/Tabs'; +import {PrimaryTabList, PrimaryTabPanel, PrimaryTabPanels, PrimaryTabs} from '../dist/components/PrimaryTabs'; ReactDOM.createRoot(document.getElementById('root')!).render( @@ -10,6 +12,30 @@ ReactDOM.createRoot(document.getElementById('root')!).render( this is a Text + + + + test data for tab 1 + + + test data for tab 2 + + + + + + + + + primary tab 1 content + + + primary tab 2 content + + + + + , ) From f2f78e96d4de96a1b004bac1b6484fb2d01cae73 Mon Sep 17 00:00:00 2001 From: shayan khaleghparast Date: Tue, 16 Jan 2024 12:44:56 +0800 Subject: [PATCH 2/8] fix: added missing EOF new line --- lib/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/main.ts b/lib/main.ts index 18dbcecc..ed3ed117 100644 --- a/lib/main.ts +++ b/lib/main.ts @@ -2,4 +2,4 @@ export { Loader } from './components/Loader' export { Button } from './components/Button' export { Text } from './components/Text' export { Tab, Tabs } from './components/Tabs' -export { PrimaryTabList, PrimaryTabPanel, PrimaryTabPanels, PrimaryTabs } from './components/PrimaryTabs' \ No newline at end of file +export { PrimaryTabList, PrimaryTabPanel, PrimaryTabPanels, PrimaryTabs } from './components/PrimaryTabs' From 6f5c65878a84ca0483ff2452e6260707626f95fa Mon Sep 17 00:00:00 2001 From: shayan khaleghparast Date: Wed, 17 Jan 2024 11:22:23 +0800 Subject: [PATCH 3/8] refactor: refactored Tabs and replace classnames with clsx --- lib/components/Button/index.tsx | 4 +- lib/components/Loader/index.tsx | 4 +- .../PrimaryTabs/PrimaryTabList.scss | 33 ---------------- lib/components/PrimaryTabs/PrimaryTabList.tsx | 29 -------------- .../PrimaryTabs/PrimaryTabPanel.tsx | 7 ---- .../PrimaryTabs/PrimaryTabPanels.tsx | 18 --------- lib/components/PrimaryTabs/PrimaryTabs.tsx | 34 ---------------- lib/components/PrimaryTabs/index.ts | 6 --- lib/components/Tabs/TabTitle.tsx | 17 +++++--- lib/components/Tabs/Tabs.scss | 38 +++++++++++++++++- lib/components/Tabs/Tabs.tsx | 10 +++-- lib/components/Text/index.tsx | 4 +- lib/main.ts | 2 +- package-lock.json | 39 ++++++++++--------- package.json | 8 ++-- src/main.tsx | 31 +++++++-------- src/style.scss | 11 ++++++ vite.config.ts | 2 +- 18 files changed, 111 insertions(+), 186 deletions(-) delete mode 100644 lib/components/PrimaryTabs/PrimaryTabList.scss delete mode 100644 lib/components/PrimaryTabs/PrimaryTabList.tsx delete mode 100644 lib/components/PrimaryTabs/PrimaryTabPanel.tsx delete mode 100644 lib/components/PrimaryTabs/PrimaryTabPanels.tsx delete mode 100644 lib/components/PrimaryTabs/PrimaryTabs.tsx delete mode 100644 lib/components/PrimaryTabs/index.ts create mode 100644 src/style.scss diff --git a/lib/components/Button/index.tsx b/lib/components/Button/index.tsx index 49709f0f..ad4ba144 100644 --- a/lib/components/Button/index.tsx +++ b/lib/components/Button/index.tsx @@ -1,5 +1,5 @@ import { ComponentProps, CSSProperties, FC, PropsWithChildren, ReactElement } from 'react'; -import classNames from 'classnames'; +import clsx from 'clsx'; import { TGenericSizes } from '../../types'; import { Loader } from '../Loader'; import { Text } from '../Text'; @@ -42,7 +42,7 @@ export const Button: FC> = ({ }) => { const isContained = variant === 'contained'; - const buttonClassNames = classNames( + const buttonClassNames = clsx( 'derivs-button', `derivs-button__size--${size}`, `derivs-button__variant--${variant}`, diff --git a/lib/components/Loader/index.tsx b/lib/components/Loader/index.tsx index 613b8a9e..d300ad37 100644 --- a/lib/components/Loader/index.tsx +++ b/lib/components/Loader/index.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import classNames from 'classnames'; +import clsx from 'clsx'; import './Loader.scss'; type TProps = { @@ -10,7 +10,7 @@ type TProps = { export const Loader: React.FC = ({ color = '#85ACB0', isFullScreen = true, className }) => (
diff --git a/lib/components/PrimaryTabs/PrimaryTabList.scss b/lib/components/PrimaryTabs/PrimaryTabList.scss deleted file mode 100644 index 65a409cf..00000000 --- a/lib/components/PrimaryTabs/PrimaryTabList.scss +++ /dev/null @@ -1,33 +0,0 @@ -.derivs-tabs { - &-list { - display: grid; - grid-auto-columns: 1fr; - position: relative; - background-color: #f2f3f4; - height: 5rem; - border-radius: 0.7rem; - - &-item { - background: inherit; - border: none; - grid-row: 1; - display: flex; - justify-content: center; - align-items: center; - cursor: pointer; - font-size: 1.6rem; - - &--active { - font-weight: bold; - background-color: #ffffff; - margin: 0.6rem; - border-radius: 0.5rem; - color: var(--system-light-1-prominent-text, #333); - } - - &--disabled { - color: #999999; - } - } - } -} diff --git a/lib/components/PrimaryTabs/PrimaryTabList.tsx b/lib/components/PrimaryTabs/PrimaryTabList.tsx deleted file mode 100644 index 772961b1..00000000 --- a/lib/components/PrimaryTabs/PrimaryTabList.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from 'react'; -import { useTabs } from './PrimaryTabs'; -import './PrimaryTabList.scss'; - -type PrimaryTabListProps = { - list: string[]; -}; - -const PrimaryTabList = ({ list }: PrimaryTabListProps) => { - const { activeTabIndex, setActiveTabIndex } = useTabs(); - - return ( -
- {list.map((tab, i) => ( - - ))} -
- ); -}; - -export default PrimaryTabList; diff --git a/lib/components/PrimaryTabs/PrimaryTabPanel.tsx b/lib/components/PrimaryTabs/PrimaryTabPanel.tsx deleted file mode 100644 index 3b773d4f..00000000 --- a/lib/components/PrimaryTabs/PrimaryTabPanel.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react'; - -const PrimaryTabPanel = ({ children }: React.PropsWithChildren) => { - return
{children}
; -}; - -export default PrimaryTabPanel; diff --git a/lib/components/PrimaryTabs/PrimaryTabPanels.tsx b/lib/components/PrimaryTabs/PrimaryTabPanels.tsx deleted file mode 100644 index 30ebaa3b..00000000 --- a/lib/components/PrimaryTabs/PrimaryTabPanels.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import React, { Children } from 'react'; -import { useTabs } from './PrimaryTabs'; - -const PrimaryTabPanels = ({ children }: React.PropsWithChildren) => { - const { activeTabIndex } = useTabs(); - - return ( -
- {Children.map(children, (child, index) => { - if (index !== activeTabIndex) return undefined; - - return child; - })} -
- ); -}; - -export default PrimaryTabPanels; diff --git a/lib/components/PrimaryTabs/PrimaryTabs.tsx b/lib/components/PrimaryTabs/PrimaryTabs.tsx deleted file mode 100644 index 4e368608..00000000 --- a/lib/components/PrimaryTabs/PrimaryTabs.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React, { createContext, useContext, useState } from 'react'; - -type TTabContext = { - activeTabIndex: number; - setActiveTabIndex: React.Dispatch>; -}; - -const TabsContext = createContext(null); - -export const useTabs = () => { - const context = useContext(TabsContext); - - if (!context) { - throw new Error('Seems you forgot to wrap the components in ""'); - } - - return context; -}; - -type TTabsProps = { - className?: string; -}; - -export const PrimaryTabs = ({ children, className }: React.PropsWithChildren) => { - const [activeTabIndex, setActiveTabIndex] = useState(0); - - return ( - -
{children}
-
- ); -}; - -export default PrimaryTabs; diff --git a/lib/components/PrimaryTabs/index.ts b/lib/components/PrimaryTabs/index.ts deleted file mode 100644 index e3a3bfdd..00000000 --- a/lib/components/PrimaryTabs/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import PrimaryTabList from './PrimaryTabList'; -import PrimaryTabPanel from './PrimaryTabPanel'; -import PrimaryTabPanels from './PrimaryTabPanels'; -import PrimaryTabs from './PrimaryTabs'; - -export { PrimaryTabList, PrimaryTabPanel, PrimaryTabPanels, PrimaryTabs }; diff --git a/lib/components/Tabs/TabTitle.tsx b/lib/components/Tabs/TabTitle.tsx index ceaeb873..3da95335 100644 --- a/lib/components/Tabs/TabTitle.tsx +++ b/lib/components/Tabs/TabTitle.tsx @@ -1,5 +1,5 @@ import React, { FC, useCallback } from 'react'; -import classNames from 'classnames'; +import clsx from 'clsx'; import { Text } from '../Text'; export type TabTitleProps = { @@ -8,18 +8,25 @@ export type TabTitleProps = { isActive?: boolean; setSelectedTab: (index: number) => void; title: string; + className?: string; + variant: 'primary' | 'secondary'; }; -const TabTitle: FC = ({ icon, index, isActive, setSelectedTab, title }) => { +const TabTitle: FC = ({ icon, index, isActive, setSelectedTab, title,className,variant }) => { const handleOnClick = useCallback(() => { setSelectedTab(index); }, [setSelectedTab, index]); + const classNameVariants = { + primary : `derivs-primary-tabs__btn--active`, + secondary : `derivs-secondary-tabs__btn--active`, + } + return ( this is a Text - - + + test data for tab 1 - + test data for tab 2 - - - - - - primary tab 1 content - - - primary tab 2 content - - - + + + test data for tab 1 + + + test data for tab 2 + + diff --git a/src/style.scss b/src/style.scss new file mode 100644 index 00000000..f3f30df5 --- /dev/null +++ b/src/style.scss @@ -0,0 +1,11 @@ +.test { + background-color: purple; +} + +.test2{ + background-color: red; +} + +.test2 span{ + color: blue; +} \ No newline at end of file diff --git a/vite.config.ts b/vite.config.ts index a9281cc1..82fef373 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -32,7 +32,7 @@ export default defineConfig({ }, copyPublicDir: false, rollupOptions: { - external: ['react', 'react/jsx-runtime', 'classnames'], + external: ['react', 'react/jsx-runtime'], input: Object.fromEntries( glob.sync('lib/**/*.{ts,tsx}').map(file => { return [ From fe44da2099f54a949c778aae5bcd261d14fda7bb Mon Sep 17 00:00:00 2001 From: shayan khaleghparast Date: Wed, 17 Jan 2024 11:44:42 +0800 Subject: [PATCH 4/8] refactor: replaced tab index number with tab label --- lib/components/Tabs/TabTitle.tsx | 15 +++++++------- lib/components/Tabs/Tabs.tsx | 34 +++++++++++++++++--------------- src/main.tsx | 4 ++-- 3 files changed, 28 insertions(+), 25 deletions(-) diff --git a/lib/components/Tabs/TabTitle.tsx b/lib/components/Tabs/TabTitle.tsx index 3da95335..dad7f026 100644 --- a/lib/components/Tabs/TabTitle.tsx +++ b/lib/components/Tabs/TabTitle.tsx @@ -4,18 +4,19 @@ import { Text } from '../Text'; export type TabTitleProps = { icon?: React.ReactNode; - index: number; + activeTab: string; isActive?: boolean; - setSelectedTab: (index: number) => void; + setSelectedTab: (label: string) => void; title: string; className?: string; variant: 'primary' | 'secondary'; }; -const TabTitle: FC = ({ icon, index, isActive, setSelectedTab, title,className,variant }) => { - const handleOnClick = useCallback(() => { - setSelectedTab(index); - }, [setSelectedTab, index]); +const TabTitle: FC = ({ icon, activeTab, isActive, setSelectedTab, title,className,variant }) => { + const handleOnClick = useCallback((title: string) => { + console.log('title',title); + setSelectedTab(title); + }, [setSelectedTab, activeTab]); const classNameVariants = { primary : `derivs-primary-tabs__btn--active`, @@ -27,7 +28,7 @@ const TabTitle: FC = ({ icon, index, isActive, setSelectedTab, ti className={clsx(`derivs-${variant + '-'}tabs__btn`,{ [classNameVariants[variant]] : isActive, }, className)} - onClick={handleOnClick} + onClick={()=>handleOnClick(title)} > {icon} {title} diff --git a/lib/components/Tabs/Tabs.tsx b/lib/components/Tabs/Tabs.tsx index e3573b1f..5123c723 100644 --- a/lib/components/Tabs/Tabs.tsx +++ b/lib/components/Tabs/Tabs.tsx @@ -5,31 +5,33 @@ import './Tabs.scss'; type TabsProps = { children: ReactElement[]; - preSelectedTab?: number; + activeTab: string; wrapperClassName?: string; className?: string; variant?: 'primary' | 'secondary'; }; -const Tabs: FC = ({ children, preSelectedTab, wrapperClassName, className, variant='primary' }): JSX.Element => { - const [selectedTabIndex, setSelectedTabIndex] = useState(preSelectedTab || 0); +const Tabs: FC = ({ children, activeTab, wrapperClassName, className, variant = 'primary' }): JSX.Element => { + const [selectedTab, setSelectedTab] = useState(activeTab); return (
-
- {children.map((item, index) => ( - - ))} +
+ {children.map((item) => { + return ( + + ) + })}
- {children[selectedTabIndex]} + {children.find((item) => item.props.title === selectedTab)}
); }; diff --git a/src/main.tsx b/src/main.tsx index e0c482cc..2de9292a 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -14,7 +14,7 @@ ReactDOM.createRoot(document.getElementById('root')!).render( this is a Text - + test data for tab 1 @@ -23,7 +23,7 @@ ReactDOM.createRoot(document.getElementById('root')!).render( - + test data for tab 1 From 42ea14ff5ce44d788d03cd1aa360569b799a1a61 Mon Sep 17 00:00:00 2001 From: "Ali(Ako) Hosseini" Date: Wed, 17 Jan 2024 11:54:07 +0800 Subject: [PATCH 5/8] Update lib/components/Tabs/TabTitle.tsx --- lib/components/Tabs/TabTitle.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/components/Tabs/TabTitle.tsx b/lib/components/Tabs/TabTitle.tsx index dad7f026..91781418 100644 --- a/lib/components/Tabs/TabTitle.tsx +++ b/lib/components/Tabs/TabTitle.tsx @@ -6,7 +6,7 @@ export type TabTitleProps = { icon?: React.ReactNode; activeTab: string; isActive?: boolean; - setSelectedTab: (label: string) => void; + setSelectedTab: (title: string) => void; title: string; className?: string; variant: 'primary' | 'secondary'; From 9c4a1d1a18b197cd14086684a8b46a453fa4d45c Mon Sep 17 00:00:00 2001 From: "Ali(Ako) Hosseini" Date: Wed, 17 Jan 2024 11:54:21 +0800 Subject: [PATCH 6/8] remove unused console log --- lib/components/Tabs/TabTitle.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/components/Tabs/TabTitle.tsx b/lib/components/Tabs/TabTitle.tsx index 91781418..68426008 100644 --- a/lib/components/Tabs/TabTitle.tsx +++ b/lib/components/Tabs/TabTitle.tsx @@ -14,7 +14,6 @@ export type TabTitleProps = { const TabTitle: FC = ({ icon, activeTab, isActive, setSelectedTab, title,className,variant }) => { const handleOnClick = useCallback((title: string) => { - console.log('title',title); setSelectedTab(title); }, [setSelectedTab, activeTab]); From 7487bf93dee5cc23da24f7557b13cd433066a6d4 Mon Sep 17 00:00:00 2001 From: "Ali(Ako) Hosseini" Date: Wed, 17 Jan 2024 11:54:39 +0800 Subject: [PATCH 7/8] feat: add default value to tab --- lib/components/Tabs/Tabs.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/components/Tabs/Tabs.tsx b/lib/components/Tabs/Tabs.tsx index 5123c723..1fd86d23 100644 --- a/lib/components/Tabs/Tabs.tsx +++ b/lib/components/Tabs/Tabs.tsx @@ -12,7 +12,7 @@ type TabsProps = { }; const Tabs: FC = ({ children, activeTab, wrapperClassName, className, variant = 'primary' }): JSX.Element => { - const [selectedTab, setSelectedTab] = useState(activeTab); + const [selectedTab, setSelectedTab] = useState(activeTab || children[0].props.title); return (
From a5c71827c01db2479c20e9d2dc4e9d743017c785 Mon Sep 17 00:00:00 2001 From: "Ali(Ako) Hosseini" Date: Wed, 17 Jan 2024 11:54:54 +0800 Subject: [PATCH 8/8] feat: make active tab optional --- lib/components/Tabs/Tabs.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/components/Tabs/Tabs.tsx b/lib/components/Tabs/Tabs.tsx index 1fd86d23..f80399e5 100644 --- a/lib/components/Tabs/Tabs.tsx +++ b/lib/components/Tabs/Tabs.tsx @@ -5,7 +5,7 @@ import './Tabs.scss'; type TabsProps = { children: ReactElement[]; - activeTab: string; + activeTab?: string; wrapperClassName?: string; className?: string; variant?: 'primary' | 'secondary';