Skip to content

Commit

Permalink
feat: add Tabs components and related simple docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Ricy committed Jan 3, 2024
1 parent e8a8d60 commit 362b7fa
Show file tree
Hide file tree
Showing 11 changed files with 224 additions and 17 deletions.
Binary file modified .DS_Store
Binary file not shown.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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?

Expand Down
Binary file modified src/.DS_Store
Binary file not shown.
3 changes: 2 additions & 1 deletion src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
export default function Home() {
return (
<main>
<div className="text-48px">123</div>
<div className="text-48px">Custom UI</div>
<p>docs is developing</p>
</main>
);
}
29 changes: 29 additions & 0 deletions src/app/tab/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use client';
import Tabs from '@/components/Tabs';

const items = [
{
id: 1,
title: 'Tab 1',
children: <div>Tab 1 Content</div>,
},
{
id: 2,
title: 'Tab 2',
children: <div>Tab 2 Content</div>,
},
{
id: 3,
title: 'Tab 3',
children: <div>Tab 3 Content</div>,
},
];

const TabsPage: React.FC = () => {
return (
<div className="flex flex-col items-center justify-center gap-x-16px h-100vh">
<Tabs items={items} defaultActiveId={1} />
</div>
);
};
export default TabsPage;
Binary file modified src/components/.DS_Store
Binary file not shown.
12 changes: 12 additions & 0 deletions src/components/Tabs/TabContent/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { type PropsWithChildren } from 'react';

interface TabContentProps extends PropsWithChildren {
id: number;
activeId: number;
}

const TabContent: React.FC<TabContentProps> = ({ id, activeId, children }) => {
return activeId === id ? <>{children}</> : null;
};

export default TabContent;
37 changes: 37 additions & 0 deletions src/components/Tabs/TabNavItem/index.tsx
Original file line number Diff line number Diff line change
@@ -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<TabNavItemProps> = ({
id,
title,
activeId,
navItemClassName,
activeNavItemClassName = 'text-#FFA14A border-b-2px border-#FFA14A border-b-solid',
setActiveId,
}) => {
const handleClick = useCallback(() => {
setActiveId(id);
}, []);
return (
<div
className={cx(
'mr-32px h-full flex items-center text-14px leading-22px text-#595A5B cursor-pointer box-border',
navItemClassName,
id === activeId && activeNavItemClassName
)}
onClick={handleClick}
>
{title}
</div>
);
};

export default TabNavItem;
12 changes: 12 additions & 0 deletions src/components/Tabs/index.md
Original file line number Diff line number Diff line change
@@ -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. |



67 changes: 67 additions & 0 deletions src/components/Tabs/index.tsx
Original file line number Diff line number Diff line change
@@ -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<TabsProps> = ({
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 (
<div className={wrapperClassName}>
<div className={navClassName}>
{items.map((item) => (
<TabNavItem
title={item.title}
setActiveId={handleTabChange}
id={item.id}
activeId={activeId}
key={`${item.id}-tab`}
navItemClassName={navItemClassName}
activeNavItemClassName={activeNavItemClassName}
/>
))}
</div>
<div className={cx('py-12px w-full', bodyClassName)}>
{items.map((item) => (
<TabContent
activeId={activeId}
id={item.id}
children={item.children}
key={`${item.id}-content`}
/>
))}
</div>
</div>
);
};

export default Tabs;
79 changes: 64 additions & 15 deletions uno.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,47 +5,58 @@
.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;}
.right-0{right:0;}
.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;}
Expand All @@ -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;}
Expand Down

0 comments on commit 362b7fa

Please sign in to comment.