From 362b7fa75fd0ba97462f645c90ea9ab8773e7e23 Mon Sep 17 00:00:00 2001 From: Ricy <1932353948@qq.com> Date: Tue, 2 Jan 2024 21:57:04 -0800 Subject: [PATCH] feat: add Tabs components and related simple docs --- .DS_Store | Bin 8196 -> 8196 bytes README.md | 2 +- src/.DS_Store | Bin 6148 -> 6148 bytes src/app/page.tsx | 3 +- src/app/tab/page.tsx | 29 +++++++++ src/components/.DS_Store | Bin 8196 -> 8196 bytes src/components/Tabs/TabContent/index.tsx | 12 ++++ src/components/Tabs/TabNavItem/index.tsx | 37 +++++++++++ src/components/Tabs/index.md | 12 ++++ src/components/Tabs/index.tsx | 67 +++++++++++++++++++ uno.css | 79 ++++++++++++++++++----- 11 files changed, 224 insertions(+), 17 deletions(-) create mode 100644 src/app/tab/page.tsx create mode 100644 src/components/Tabs/TabContent/index.tsx create mode 100644 src/components/Tabs/TabNavItem/index.tsx create mode 100644 src/components/Tabs/index.md diff --git a/.DS_Store b/.DS_Store index 146db00ab688b8b0ce3d46e92ee051275c1fffea..2e5a14023b6f2010c1ef6f6ac4fd9f9ebee6716e 100644 GIT binary patch delta 21 ccmZp1XmQxELxjW3z(PmC*u--40TCB&08HlwZ2$lO delta 21 ccmZp1XmQxELxjV~%s@xM*u-M<0TCB&08E_*W&i*H diff --git a/README.md b/README.md index b43d312..1c3a65f 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ## curent develop plan * update current components -* Solve the conflicts and provide docs +* Solve the conflicts and provide docs( not only for demonstration, but also for self-use, lol) ## Why do I start the repo? diff --git a/src/.DS_Store b/src/.DS_Store index fafd883e15974ebfef8b89cbef417ad64dd788c5..55d4ea18369c2b5d669ba5d99a4cb81bf801dbcd 100644 GIT binary patch delta 21 ccmZoMXffE3$I4-5V4;M1& delta 21 ccmZoMXffE3$I4-3W}u^BY+|vwjI~b)07L=> -
123
+
Custom UI
+

docs is developing

); } diff --git a/src/app/tab/page.tsx b/src/app/tab/page.tsx new file mode 100644 index 0000000..207b36a --- /dev/null +++ b/src/app/tab/page.tsx @@ -0,0 +1,29 @@ +'use client'; +import Tabs from '@/components/Tabs'; + +const items = [ + { + id: 1, + title: 'Tab 1', + children:
Tab 1 Content
, + }, + { + id: 2, + title: 'Tab 2', + children:
Tab 2 Content
, + }, + { + id: 3, + title: 'Tab 3', + children:
Tab 3 Content
, + }, +]; + +const TabsPage: React.FC = () => { + return ( +
+ +
+ ); +}; +export default TabsPage; diff --git a/src/components/.DS_Store b/src/components/.DS_Store index bb96f65be71fdf400346a1b532a301017bd09bf3..8f3a8fe77aa398620f722f481b6174f0ef6b4620 100644 GIT binary patch delta 65 zcmZp1XmQxEOhlNAA%G!~A)O(UArDBG0O|b67X(E(8TtN$0mJ4+B5I7AKZtTOZDyDF O#xnV&$bTS@g9!k@!55eS delta 65 zcmZp1XmQxEOl0#d5hX@W7KRXpM1~}W;>o*3 = ({ id, activeId, children }) => { + return activeId === id ? <>{children} : null; +}; + +export default TabContent; diff --git a/src/components/Tabs/TabNavItem/index.tsx b/src/components/Tabs/TabNavItem/index.tsx new file mode 100644 index 0000000..2b7d762 --- /dev/null +++ b/src/components/Tabs/TabNavItem/index.tsx @@ -0,0 +1,37 @@ +import { useCallback } from 'react'; +import cx from 'clsx'; +interface TabNavItemProps { + id: number; + title: string; + activeId: number; + navItemClassName?: string; + activeNavItemClassName?: string; + setActiveId: (id: number) => void; +} + +const TabNavItem: React.FC = ({ + id, + title, + activeId, + navItemClassName, + activeNavItemClassName = 'text-#FFA14A border-b-2px border-#FFA14A border-b-solid', + setActiveId, +}) => { + const handleClick = useCallback(() => { + setActiveId(id); + }, []); + return ( +
+ {title} +
+ ); +}; + +export default TabNavItem; diff --git a/src/components/Tabs/index.md b/src/components/Tabs/index.md new file mode 100644 index 0000000..5805165 --- /dev/null +++ b/src/components/Tabs/index.md @@ -0,0 +1,12 @@ +Tabs organize and allow navigation between groups of content that are related and at the same level of hierarchy. + +| prop | type | default | description | +| ---------------- | ------ | ------- | ----------------------------------- | +| wrapperClassName | string | 'flex flex-col' | Class name for the wrapper element of navigation bar and each tab's content. | +| navClassName | string | 'flex flex-row h-36px border-b-1px border-b-solid border-#EBEDF0' | Class name for the navigation bar. | +| navItemClassName | string | '' | Class name used for modifying each navigation item. | +| navItemActiveClassName | string | 'text-#FFA14A border-b-2px border-#FFA14A border-b-solid' | Class name for the active navigation item. | +| bodyClassName | string | '' | Class name used for modifying the content area. | + + + diff --git a/src/components/Tabs/index.tsx b/src/components/Tabs/index.tsx index e69de29..53d770a 100644 --- a/src/components/Tabs/index.tsx +++ b/src/components/Tabs/index.tsx @@ -0,0 +1,67 @@ +import React, { useState, useCallback } from 'react'; +import cx from 'clsx'; +import TabNavItem from './TabNavItem'; +import TabContent from './TabContent'; + +export interface Item { + id: number; + title: string; + children: JSX.Element; +} + +interface TabsProps { + items: Item[]; + defaultActiveId: number; + wrapperClassName?: string; + navClassName?: string; + navItemClassName?: string; + activeNavItemClassName?: string; + bodyClassName?: string; + onTabChange?: (id: number) => void; +} + +const Tabs: React.FC = ({ + items, + defaultActiveId, + navClassName = 'flex flex-row h-36px border-b-1px border-b-solid border-#EBEDF0', + navItemClassName, + activeNavItemClassName, + bodyClassName, + wrapperClassName = 'flex flex-col', + onTabChange, +}) => { + const [activeId, setActiveId] = useState(defaultActiveId); + const handleTabChange = useCallback((id: number) => { + setActiveId(id); + onTabChange?.(id); + }, []); + return ( +
+
+ {items.map((item) => ( + + ))} +
+
+ {items.map((item) => ( + + ))} +
+
+ ); +}; + +export default Tabs; diff --git a/uno.css b/uno.css index b447b47..aae034b 100644 --- a/uno.css +++ b/uno.css @@ -5,7 +5,6 @@ .absolute{position:absolute;} .fixed{position:fixed;} .relative{position:relative;} -.static{position:static;} .bottom-0{bottom:0;} .left-0{left:0;} .right-\.5em{right:0.5em;} @@ -13,39 +12,51 @@ .right-1px{right:1px;} .top-\[5\%\]{top:5%;} .top-\[50\%\], -.top-1\/2{top:50%;} +.top-1\/2, +.top-50\%{top:50%;} .top-0{top:0;} -.z-\[200\]{z-index:200;} +.z-\[200\], +.z-200{z-index:200;} +.z-10{z-index:10;} +.z-100{z-index:100;} +.z-20{z-index:20;} .z-40{z-index:40;} .z-50{z-index:50;} -.mb-24px{margin-bottom:24px;} +.mx-24px{margin-left:24px;margin-right:24px;} +.mr-32px{margin-right:32px;} .mr-8px{margin-right:8px;} -.block{display:block;} -.display-none{display:none;} +.box-border{box-sizing:border-box;} +.display-none, +.hidden{display:none;} .h-\[16px\]{height:16px;} +.h-\[30px\]{height:30px;} .h-1\.3em{height:1.3em;} .h-1\.5em{height:1.5em;} .h-100vh, .h-screen{height:100vh;} +.h-18px{height:18px;} .h-24px{height:24px;} .h-300px{height:300px;} .h-32px{height:32px;} -.h-40px{height:40px;} +.h-36px{height:36px;} .h-48px{height:48px;} .h-6{height:1.5rem;} .h-64px{height:64px;} +.h-8px{height:8px;} .h-fit{height:fit-content;} .h-full{height:100%;} .max-w-\[560px\]{max-width:560px;} .w-\[16px\]{width:16px;} +.w-\[30px\]{width:30px;} .w-\[90vw\]{width:90vw;} .w-1\.3em{width:1.3em;} .w-1\.5em{width:1.5em;} +.w-18px{width:18px;} .w-2\/5{width:40%;} +.w-240px{width:240px;} .w-24px{width:24px;} .w-300px{width:300px;} .w-4\/5{width:80%;} -.w-40px{width:40px;} .w-6{width:1.5rem;} .w-64px{width:64px;} .w-fit{width:fit-content;} @@ -55,55 +66,93 @@ .flex-row{flex-direction:row;} .flex-col{flex-direction:column;} .-translate-y-\[calc\(50\%\+1px\)\]{--un-translate-y:calc(calc(50% + 1px) * -1);transform:translateX(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotateZ(var(--un-rotate-z)) skewX(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z));} -.-translate-y-1\/2{--un-translate-y:-50%;transform:translateX(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotateZ(var(--un-rotate-z)) skewX(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z));} -.transform{transform:translateX(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotateZ(var(--un-rotate-z)) skewX(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z));} +.-translate-y-1\/2, +.-translate-y-50\%{--un-translate-y:-50%;transform:translateX(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotateZ(var(--un-rotate-z)) skewX(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z));} .cursor-default{cursor:default;} .cursor-pointer{cursor:pointer;} .cursor-not-allowed{cursor:not-allowed;} +.resize{resize:both;} .items-center{align-items:center;} .justify-end{justify-content:flex-end;} .justify-center{justify-content:center;} .justify-between{justify-content:space-between;} .gap-\[12px\]{grid-gap:12px;gap:12px;} -.gap-16px{grid-gap:16px;gap:16px;} .gap-24px{grid-gap:24px;gap:24px;} .gap-x-16px{grid-column-gap:16px;column-gap:16px;} .gap-y-24px{grid-row-gap:24px;row-gap:24px;} .overflow-hidden{overflow:hidden;} +.border, .border-1px{border-width:1px;} +.border-b-1px{border-bottom-width:1px;} +.border-b-2px{border-bottom-width:2px;} +.border-b-3px{border-bottom-width:3px;} .border-\#000000, .border-black{--un-border-opacity:1;border-color:rgba(0,0,0,var(--un-border-opacity));} .border-\#1E8E3E{--un-border-opacity:1;border-color:rgba(30,142,62,var(--un-border-opacity));} -.rounded-\[8px\]{border-radius:8px;} +.border-\#DCDEE0{--un-border-opacity:1;border-color:rgba(220,222,224,var(--un-border-opacity));} +.border-\#EBEDF0{--un-border-opacity:1;border-color:rgba(235,237,240,var(--un-border-opacity));} +.border-\#FFA14A, +.hover\:border-\#FFA14A:hover{--un-border-opacity:1;border-color:rgba(255,161,74,var(--un-border-opacity));} +.hover\:border-\[\#ffffff\]:hover{--un-border-opacity:1;border-color:rgba(255,255,255,var(--un-border-opacity));} +.focus\:border-\#FFA14A:focus{--un-border-opacity:1;border-color:rgba(255,161,74,var(--un-border-opacity));} +.rounded-\[8px\], +.rounded-8px{border-radius:8px;} .rounded-2px{border-radius:2px;} .rounded-32px{border-radius:32px;} +.rounded-41px{border-radius:41px;} .rounded-full{border-radius:9999px;} +.rounded-l-41px{border-top-left-radius:41px;border-bottom-left-radius:41px;} .border-solid{border-style:solid;} +.border-b-solid{border-bottom-style:solid;} .bg-\[rgba\(0\,0\,0\,0\.6\)\]{--un-bg-opacity:0.6;background-color:rgba(0,0,0,var(--un-bg-opacity));} +.bg-\#323233{--un-bg-opacity:1;background-color:rgba(50,50,51,var(--un-bg-opacity));} +.bg-\#DCDEE0{--un-bg-opacity:1;background-color:rgba(220,222,224,var(--un-bg-opacity));} +.bg-\#F48A28{--un-bg-opacity:1;background-color:rgba(244,138,40,var(--un-bg-opacity));} +.bg-\#FFA14A{--un-bg-opacity:1;background-color:rgba(255,161,74,var(--un-bg-opacity));} .bg-\#ffffff, +.bg-\#FFFFFF, .bg-white{--un-bg-opacity:1;background-color:rgba(255,255,255,var(--un-bg-opacity));} .bg-\#fffffff{background-color:#fffffff;} .bg-black{--un-bg-opacity:1;background-color:rgba(0,0,0,var(--un-bg-opacity));} .bg-purple-500{--un-bg-opacity:1;background-color:rgba(168,85,247,var(--un-bg-opacity));} -.checked\:bg-\#ffa14a:checked, -.checked\:bg-\#FFA14A:checked{--un-bg-opacity:1;background-color:rgba(255,161,74,var(--un-bg-opacity));} +.hover\:bg-\#FFF6ED:hover{--un-bg-opacity:1;background-color:rgba(255,246,237,var(--un-bg-opacity));} .bg-opacity-40{--un-bg-opacity:0.4;} .fill-\#1E8E3E{--un-fill-opacity:1;fill:rgba(30,142,62,var(--un-fill-opacity));} .fill-\#595A5B{--un-fill-opacity:1;fill:rgba(89,90,91,var(--un-fill-opacity));} +.fill-white{--un-fill-opacity:1;fill:rgba(255,255,255,var(--un-fill-opacity));} +.hover\:stroke-\#F48A28:hover, +.stroke-\#F48A28{--un-stroke-opacity:1;stroke:rgba(244,138,40,var(--un-stroke-opacity));} +.stroke-\#FFA14A{--un-stroke-opacity:1;stroke:rgba(255,161,74,var(--un-stroke-opacity));} .p-\[28px\]{padding:28px;} .p-8px{padding:8px;} +.px{padding-left:1rem;padding-right:1rem;} .px-\[24px\]{padding-left:24px;padding-right:24px;} -.pt-40px{padding-top:40px;} +.px-8px{padding-left:8px;padding-right:8px;} +.py-12px{padding-top:12px;padding-bottom:12px;} +.pl-12px{padding-left:12px;} +.pr-7px{padding-right:7px;} .text-\.85em{font-size:0.85em;} .text-\[22px\]{font-size:22px;} .text-1\.4em{font-size:1.4em;} +.text-14px{font-size:14px;} .text-1em{font-size:1em;} .text-48px{font-size:48px;} .font-semibold{font-weight:600;} +.leading-22px{line-height:22px;} +.\!text-\#FFA14A{--un-text-opacity:1 !important;color:rgba(255,161,74,var(--un-text-opacity)) !important;} +.hover\:text-\#FFA14A:hover, +.text-\#FFA14A{--un-text-opacity:1;color:rgba(255,161,74,var(--un-text-opacity));} .text-\[\#303549\]{--un-text-opacity:1;color:rgba(48,53,73,var(--un-text-opacity));} .text-\#1E8E3E{--un-text-opacity:1;color:rgba(30,142,62,var(--un-text-opacity));} +.text-\#323233{--un-text-opacity:1;color:rgba(50,50,51,var(--un-text-opacity));} +.text-\#595A5B{--un-text-opacity:1;color:rgba(89,90,91,var(--un-text-opacity));} +.text-\#C1C2C5{--un-text-opacity:1;color:rgba(193,194,197,var(--un-text-opacity));} .text-\#D93026{--un-text-opacity:1;color:rgba(217,48,38,var(--un-text-opacity));} +.text-\#FFFFFF{--un-text-opacity:1;color:rgba(255,255,255,var(--un-text-opacity));} .text-black{--un-text-opacity:1;color:rgba(0,0,0,var(--un-text-opacity));} +.no-underline{text-decoration:none;} +.-tab{-moz-tab-size:-4;-o-tab-size:-4;tab-size:-4;} +.shadow-\[0px_2px_8px_0px_rgba\(0\,0\,0\,0\.12\)\]{--un-shadow:0px 2px 8px 0px var(--un-shadow-color, rgba(0,0,0,0.12));box-shadow:var(--un-ring-offset-shadow), var(--un-ring-shadow), var(--un-shadow);} .ring{--un-ring-width:1px;--un-ring-offset-shadow:var(--un-ring-inset) 0 0 0 var(--un-ring-offset-width) var(--un-ring-offset-color);--un-ring-shadow:var(--un-ring-inset) 0 0 0 calc(var(--un-ring-width) + var(--un-ring-offset-width)) var(--un-ring-color);box-shadow:var(--un-ring-offset-shadow), var(--un-ring-shadow), var(--un-shadow);} @media (min-width: 768px){ .md\:h-\[8px\]{height:8px;}