diff options
author | crupest <crupest@outlook.com> | 2023-08-31 19:18:48 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2023-08-31 19:18:48 +0800 |
commit | a1f69d978426c6a4cb7e8f3116e087553dbbffd5 (patch) | |
tree | 506eb8fc76336ea2941c373aad570c73ede577e3 /FrontEnd/src/components | |
parent | 1a543da5a018d1a99b51bfe5d7d90edff0502a11 (diff) | |
download | timeline-a1f69d978426c6a4cb7e8f3116e087553dbbffd5.tar.gz timeline-a1f69d978426c6a4cb7e8f3116e087553dbbffd5.tar.bz2 timeline-a1f69d978426c6a4cb7e8f3116e087553dbbffd5.zip |
...
Diffstat (limited to 'FrontEnd/src/components')
-rw-r--r-- | FrontEnd/src/components/tab/TabBar.css | 38 | ||||
-rw-r--r-- | FrontEnd/src/components/tab/TabBar.tsx | 69 | ||||
-rw-r--r-- | FrontEnd/src/components/tab/TabPages.css | 0 | ||||
-rw-r--r-- | FrontEnd/src/components/tab/TabPages.tsx | 56 | ||||
-rw-r--r-- | FrontEnd/src/components/tab/Tabs.css | 33 | ||||
-rw-r--r-- | FrontEnd/src/components/tab/Tabs.tsx | 62 | ||||
-rw-r--r-- | FrontEnd/src/components/tab/index.ts | 2 |
7 files changed, 132 insertions, 128 deletions
diff --git a/FrontEnd/src/components/tab/TabBar.css b/FrontEnd/src/components/tab/TabBar.css new file mode 100644 index 00000000..09d48c59 --- /dev/null +++ b/FrontEnd/src/components/tab/TabBar.css @@ -0,0 +1,38 @@ +.cru-tab-bar {
+ border-bottom: var(--cru-clickable-normal-color) 1px solid;
+ display: flex;
+}
+
+.cru-tab-bar-tab-area {
+ display: flex;
+ align-items: center;
+ gap: 0.5em;
+ border: var(--cru-clickable-normal-color) 1px solid;
+ border-bottom: none;
+ border-top-left-radius: 5px;
+ border-top-right-radius: 5px;
+ padding: 0.2em 0.5em;
+}
+
+.cru-tab-bar-item {
+ color: var(--cru-clickable-normal-color);
+ transition: all 0.5s;
+ border-radius: 5px;
+ cursor: pointer;
+ padding: 0.3em 1em;
+}
+
+.cru-tab-bar-item:hover {
+ color: var(--cru-push-button-text-color);
+ background-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..e69de29b --- /dev/null +++ b/FrontEnd/src/components/tab/TabPages.css diff --git a/FrontEnd/src/components/tab/TabPages.tsx b/FrontEnd/src/components/tab/TabPages.tsx index 6a5f4469..ab45ffdf 100644 --- a/FrontEnd/src/components/tab/TabPages.tsx +++ b/FrontEnd/src/components/tab/TabPages.tsx @@ -1,52 +1,43 @@ -import * as React from "react"; +import { ReactNode, useState } from "react"; +import classNames from "classnames"; -import { I18nText, UiLogicError } from "~src/common"; +import { Text, UiLogicError } from "../common"; -import Tabs from "./Tabs"; +import Tabs from "./TabBar"; -export interface TabPage { +import "./TabPages.css"; + +interface TabPage { name: string; - text: I18nText; - page: React.ReactNode; + text: Text; + page: ReactNode; } -export interface TabPagesProps { +interface TabPagesProps { pages: TabPage[]; - actions?: React.ReactNode; + actions?: ReactNode; dense?: boolean; className?: string; - style?: React.CSSProperties; - navClassName?: string; - navStyle?: React.CSSProperties; + tabBarClassName?: string; pageContainerClassName?: string; - pageContainerStyle?: React.CSSProperties; } -const TabPages: React.FC<TabPagesProps> = ({ +export default function TabPages({ pages, actions, dense, className, - style, - navClassName, - navStyle, + tabBarClassName, pageContainerClassName, - pageContainerStyle, -}) => { - if (pages.length === 0) { - throw new UiLogicError("Page list can't be empty."); - } - - const [tab, setTab] = React.useState<string>(pages[0].name); +}: TabPagesProps) { + const [tab, setTab] = useState<string>(pages[0].name); const currentPage = pages.find((p) => p.name === tab); - if (currentPage == null) { - throw new UiLogicError("Current tab value is bad."); - } + if (currentPage == null) throw new UiLogicError(); return ( - <div className={className} style={style}> + <div className={className}> <Tabs tabs={pages.map((page) => ({ name: page.name, @@ -57,15 +48,14 @@ const TabPages: React.FC<TabPagesProps> = ({ }))} dense={dense} activeTabName={tab} - className={navClassName} - style={navStyle} + className={tabBarClassName} actions={actions} /> - <div className={pageContainerClassName} style={pageContainerStyle}> + <div + className={classNames("cru-tab-page-container", pageContainerClassName)} + > {currentPage.page} </div> </div> ); -}; - -export default TabPages; +} diff --git a/FrontEnd/src/components/tab/Tabs.css b/FrontEnd/src/components/tab/Tabs.css deleted file mode 100644 index 395d16a7..00000000 --- a/FrontEnd/src/components/tab/Tabs.css +++ /dev/null @@ -1,33 +0,0 @@ -.cru-nav {
- border-bottom: var(--cru-primary-color) 1px solid;
- display: flex;
-}
-
-.cru-nav-item {
- color: var(--cru-primary-color);
- border: var(--cru-background-2-color) 0.5px solid;
- border-bottom: none;
- padding: 0.5em 1.5em;
- border-top-left-radius: 5px;
- border-top-right-radius: 5px;
- transition: all 0.5s;
- cursor: pointer;
-}
-
-.cru-nav.dense .cru-nav-item {
- padding: 0.2em 1em;
-}
-
-.cru-nav-item:hover {
- background-color: var(--cru-background-1-color);
-}
-
-.cru-nav-item.active {
- color: var(--cru-primary-t-color);
- background-color: var(--cru-primary-color);
- border-color: var(--cru-primary-color);
-}
-
-.cru-nav-action-area {
- margin-left: auto;
-}
diff --git a/FrontEnd/src/components/tab/Tabs.tsx b/FrontEnd/src/components/tab/Tabs.tsx deleted file mode 100644 index dc8d9c01..00000000 --- a/FrontEnd/src/components/tab/Tabs.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import * as React from "react"; -import { Link } from "react-router-dom"; -import { useTranslation } from "react-i18next"; -import classnames from "classnames"; - -import { convertI18nText, I18nText } from "~src/common"; - -import "./Tabs.css"; - -export interface Tab { - name: string; - text: I18nText; - link?: string; - onClick?: () => void; -} - -export interface TabsProps { - activeTabName?: string; - actions?: React.ReactNode; - dense?: boolean; - tabs: Tab[]; - className?: string; - style?: React.CSSProperties; -} - -export default function Tabs(props: TabsProps): React.ReactElement | null { - const { tabs, activeTabName, className, style, dense, actions } = props; - - const { t } = useTranslation(); - - return ( - <div - className={classnames("cru-nav", dense && "dense", className)} - style={style} - > - {tabs.map((tab) => { - const active = activeTabName === tab.name; - const className = classnames("cru-nav-item", active && "active"); - - if (tab.link != null) { - return ( - <Link - key={tab.name} - to={tab.link} - onClick={tab.onClick} - className={className} - > - {convertI18nText(tab.text, t)} - </Link> - ); - } else { - return ( - <span key={tab.name} onClick={tab.onClick} className={className}> - {convertI18nText(tab.text, t)} - </span> - ); - } - })} - <div className="cru-nav-action-area">{actions}</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"; |