diff options
author | crupest <crupest@outlook.com> | 2023-09-20 20:26:42 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-20 20:26:42 +0800 |
commit | f836d77e73f3ea0af45c5f71dae7268143d6d86f (patch) | |
tree | 573cfafd972106d69bef0d41ff5f270ec3c43ec2 /FrontEnd/src/components/tab | |
parent | 4a069bf1268f393d5467166356f691eb89963152 (diff) | |
parent | 901fe3d7c032d284da5c9bce24c4aaee9054c7ac (diff) | |
download | timeline-f836d77e73f3ea0af45c5f71dae7268143d6d86f.tar.gz timeline-f836d77e73f3ea0af45c5f71dae7268143d6d86f.tar.bz2 timeline-f836d77e73f3ea0af45c5f71dae7268143d6d86f.zip |
Merge pull request #1395 from crupest/dev
Refector 2023 v0.1
Diffstat (limited to 'FrontEnd/src/components/tab')
-rw-r--r-- | FrontEnd/src/components/tab/TabBar.css | 32 | ||||
-rw-r--r-- | FrontEnd/src/components/tab/TabBar.tsx | 69 | ||||
-rw-r--r-- | FrontEnd/src/components/tab/TabPages.css | 3 | ||||
-rw-r--r-- | FrontEnd/src/components/tab/TabPages.tsx | 61 | ||||
-rw-r--r-- | FrontEnd/src/components/tab/index.ts | 2 |
5 files changed, 167 insertions, 0 deletions
diff --git a/FrontEnd/src/components/tab/TabBar.css b/FrontEnd/src/components/tab/TabBar.css new file mode 100644 index 00000000..dc6970c7 --- /dev/null +++ b/FrontEnd/src/components/tab/TabBar.css @@ -0,0 +1,32 @@ +.cru-tab-bar {
+ display: flex;
+}
+
+.cru-tab-bar-tab-area {
+ display: flex;
+ align-items: center;
+ border: var(--cru-clickable-normal-color) 1.6px solid;
+ border-radius: 3px;
+ overflow: hidden;
+}
+
+.cru-tab-bar-item {
+ color: var(--cru-text-minor-color);
+ transition: all 0.2s;
+ cursor: pointer;
+ padding: 0.3em 1em;
+}
+
+.cru-tab-bar-item:hover {
+ color: var(--cru-clickable-normal-color);
+}
+
+.cru-tab-bar-item.active {
+ color: var(--cru-push-button-text-color);
+ background-color: var(--cru-clickable-normal-color);
+ border-color: var(--cru-primary-color);
+}
+
+.cru-tab-bar-action-area {
+ margin-left: auto;
+}
diff --git a/FrontEnd/src/components/tab/TabBar.tsx b/FrontEnd/src/components/tab/TabBar.tsx new file mode 100644 index 00000000..601f664d --- /dev/null +++ b/FrontEnd/src/components/tab/TabBar.tsx @@ -0,0 +1,69 @@ +import { ReactNode } from "react"; +import { Link } from "react-router-dom"; +import classNames from "classnames"; + +import { Text, ThemeColor, useC } from "../common"; + +import "./TabBar.css"; + +export interface Tab { + name: string; + text: Text; + link?: string; + onClick?: () => void; +} + +export interface TabsProps { + activeTabName?: string; + tabs: Tab[]; + color?: ThemeColor; + actions?: ReactNode; + dense?: boolean; + className?: string; +} + +export default function TabBar(props: TabsProps) { + const { tabs, color, activeTabName, className, dense, actions } = props; + + const c = useC(); + + return ( + <div + className={classNames( + "cru-tab-bar", + dense && "dense", + `cru-clickable-${color ?? "primary"}`, + className, + )} + > + <div className="cru-tab-bar-tab-area"> + {tabs.map((tab) => { + const { name, text, link, onClick } = tab; + + const active = activeTabName === name; + const className = classNames("cru-tab-bar-item", active && "active"); + + if (link != null) { + return ( + <Link + key={name} + to={link} + onClick={onClick} + className={className} + > + {c(text)} + </Link> + ); + } else { + return ( + <span key={name} onClick={onClick} className={className}> + {c(text)} + </span> + ); + } + })} + </div> + <div className="cru-tab-bar-action-area">{actions}</div> + </div> + ); +} diff --git a/FrontEnd/src/components/tab/TabPages.css b/FrontEnd/src/components/tab/TabPages.css new file mode 100644 index 00000000..c07d042e --- /dev/null +++ b/FrontEnd/src/components/tab/TabPages.css @@ -0,0 +1,3 @@ +.cru-tab-page-container { + padding-top: 0.5em; +} diff --git a/FrontEnd/src/components/tab/TabPages.tsx b/FrontEnd/src/components/tab/TabPages.tsx new file mode 100644 index 00000000..ab45ffdf --- /dev/null +++ b/FrontEnd/src/components/tab/TabPages.tsx @@ -0,0 +1,61 @@ +import { ReactNode, useState } from "react"; +import classNames from "classnames"; + +import { Text, UiLogicError } from "../common"; + +import Tabs from "./TabBar"; + +import "./TabPages.css"; + +interface TabPage { + name: string; + text: Text; + page: ReactNode; +} + +interface TabPagesProps { + pages: TabPage[]; + actions?: ReactNode; + dense?: boolean; + className?: string; + tabBarClassName?: string; + pageContainerClassName?: string; +} + +export default function TabPages({ + pages, + actions, + dense, + className, + tabBarClassName, + pageContainerClassName, +}: TabPagesProps) { + const [tab, setTab] = useState<string>(pages[0].name); + + const currentPage = pages.find((p) => p.name === tab); + + if (currentPage == null) throw new UiLogicError(); + + return ( + <div className={className}> + <Tabs + tabs={pages.map((page) => ({ + name: page.name, + text: page.text, + onClick: () => { + setTab(page.name); + }, + }))} + dense={dense} + activeTabName={tab} + className={tabBarClassName} + actions={actions} + /> + <div + className={classNames("cru-tab-page-container", pageContainerClassName)} + > + {currentPage.page} + </div> + </div> + ); +} diff --git a/FrontEnd/src/components/tab/index.ts b/FrontEnd/src/components/tab/index.ts new file mode 100644 index 00000000..43d545cc --- /dev/null +++ b/FrontEnd/src/components/tab/index.ts @@ -0,0 +1,2 @@ +export { default as TabBar } from "./TabBar"; +export { default as TabPages } from "./TabPages"; |