From f5dfd52f6efece2f4cad227044ecf4dd66301bbc Mon Sep 17 00:00:00 2001 From: crupest Date: Sat, 26 Aug 2023 21:36:58 +0800 Subject: ... --- FrontEnd/src/components/tab/TabPages.tsx | 71 ++++++++++++++++++++++++++++++++ FrontEnd/src/components/tab/Tabs.css | 33 +++++++++++++++ FrontEnd/src/components/tab/Tabs.tsx | 62 ++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+) create mode 100644 FrontEnd/src/components/tab/TabPages.tsx create mode 100644 FrontEnd/src/components/tab/Tabs.css create mode 100644 FrontEnd/src/components/tab/Tabs.tsx (limited to 'FrontEnd/src/components/tab') diff --git a/FrontEnd/src/components/tab/TabPages.tsx b/FrontEnd/src/components/tab/TabPages.tsx new file mode 100644 index 00000000..6a5f4469 --- /dev/null +++ b/FrontEnd/src/components/tab/TabPages.tsx @@ -0,0 +1,71 @@ +import * as React from "react"; + +import { I18nText, UiLogicError } from "~src/common"; + +import Tabs from "./Tabs"; + +export interface TabPage { + name: string; + text: I18nText; + page: React.ReactNode; +} + +export interface TabPagesProps { + pages: TabPage[]; + actions?: React.ReactNode; + dense?: boolean; + className?: string; + style?: React.CSSProperties; + navClassName?: string; + navStyle?: React.CSSProperties; + pageContainerClassName?: string; + pageContainerStyle?: React.CSSProperties; +} + +const TabPages: React.FC = ({ + pages, + actions, + dense, + className, + style, + navClassName, + navStyle, + pageContainerClassName, + pageContainerStyle, +}) => { + if (pages.length === 0) { + throw new UiLogicError("Page list can't be empty."); + } + + const [tab, setTab] = React.useState(pages[0].name); + + const currentPage = pages.find((p) => p.name === tab); + + if (currentPage == null) { + throw new UiLogicError("Current tab value is bad."); + } + + return ( +
+ ({ + name: page.name, + text: page.text, + onClick: () => { + setTab(page.name); + }, + }))} + dense={dense} + activeTabName={tab} + className={navClassName} + style={navStyle} + actions={actions} + /> +
+ {currentPage.page} +
+
+ ); +}; + +export default TabPages; diff --git a/FrontEnd/src/components/tab/Tabs.css b/FrontEnd/src/components/tab/Tabs.css new file mode 100644 index 00000000..395d16a7 --- /dev/null +++ b/FrontEnd/src/components/tab/Tabs.css @@ -0,0 +1,33 @@ +.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 new file mode 100644 index 00000000..dc8d9c01 --- /dev/null +++ b/FrontEnd/src/components/tab/Tabs.tsx @@ -0,0 +1,62 @@ +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 ( +
+ {tabs.map((tab) => { + const active = activeTabName === tab.name; + const className = classnames("cru-nav-item", active && "active"); + + if (tab.link != null) { + return ( + + {convertI18nText(tab.text, t)} + + ); + } else { + return ( + + {convertI18nText(tab.text, t)} + + ); + } + })} +
{actions}
+
+ ); +} -- cgit v1.2.3