diff options
author | crupest <crupest@outlook.com> | 2021-07-01 17:54:04 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2021-07-01 17:54:04 +0800 |
commit | 88851e84f070207581f5dfa78a94e52194a2281b (patch) | |
tree | f9a0c2be1df48d7be842a8db66fb44b24d570bd7 /FrontEnd/src/views/common | |
parent | 672778ca5d9de5513c86d70394b2dd048639cdea (diff) | |
download | timeline-88851e84f070207581f5dfa78a94e52194a2281b.tar.gz timeline-88851e84f070207581f5dfa78a94e52194a2281b.tar.bz2 timeline-88851e84f070207581f5dfa78a94e52194a2281b.zip |
...
Diffstat (limited to 'FrontEnd/src/views/common')
-rw-r--r-- | FrontEnd/src/views/common/Skeleton.css | 14 | ||||
-rw-r--r-- | FrontEnd/src/views/common/Skeleton.tsx | 4 | ||||
-rw-r--r-- | FrontEnd/src/views/common/index.css | 23 | ||||
-rw-r--r-- | FrontEnd/src/views/common/tab/TabPages.tsx | 33 | ||||
-rw-r--r-- | FrontEnd/src/views/common/tab/Tabs.css | 31 | ||||
-rw-r--r-- | FrontEnd/src/views/common/tab/Tabs.tsx | 47 |
6 files changed, 125 insertions, 27 deletions
diff --git a/FrontEnd/src/views/common/Skeleton.css b/FrontEnd/src/views/common/Skeleton.css new file mode 100644 index 00000000..db1a1c34 --- /dev/null +++ b/FrontEnd/src/views/common/Skeleton.css @@ -0,0 +1,14 @@ +.cru-skeleton {
+ padding: 0 1em;
+}
+
+.cru-skeleton-line {
+ height: 1em;
+ background-color: #e6e6e6;
+ margin: 0.7em 0;
+ border-radius: 0.2em;
+}
+
+.cru-skeleton-line.last {
+ width: 50%;
+}
diff --git a/FrontEnd/src/views/common/Skeleton.tsx b/FrontEnd/src/views/common/Skeleton.tsx index 14886c71..58d34215 100644 --- a/FrontEnd/src/views/common/Skeleton.tsx +++ b/FrontEnd/src/views/common/Skeleton.tsx @@ -1,6 +1,8 @@ import React from "react"; import classnames from "classnames"; -import { range } from "lodash"; +import range from "lodash/range"; + +import "./Skeleton.css"; export interface SkeletonProps { lineNumber?: number; diff --git a/FrontEnd/src/views/common/index.css b/FrontEnd/src/views/common/index.css index 62167cfc..529e0e51 100644 --- a/FrontEnd/src/views/common/index.css +++ b/FrontEnd/src/views/common/index.css @@ -108,6 +108,10 @@ color: var(--cru-danger-color);
}
+.cru-text-center {
+ text-align: center;
+}
+
.cru-text-end {
text-align: end;
}
@@ -128,6 +132,11 @@ clear: both;
}
+.cru-fill-parent {
+ width: 100%;
+ height: 100%;
+}
+
.icon-button {
font-size: 1.4rem;
cursor: pointer;
@@ -160,20 +169,6 @@ border-radius: 50%;
}
-.cru-skeleton {
- padding: 0 1em;
-}
-
-.cru-skeleton-line {
- height: 1em;
- background-color: #e6e6e6;
- margin: 0.7em 0;
- border-radius: 0.2em;
-}
-.cru-skeleton-line.last {
- width: 50%;
-}
-
.cru-tab-pages-action-area {
display: flex;
align-items: center;
diff --git a/FrontEnd/src/views/common/tab/TabPages.tsx b/FrontEnd/src/views/common/tab/TabPages.tsx index b7a9fb36..677f558a 100644 --- a/FrontEnd/src/views/common/tab/TabPages.tsx +++ b/FrontEnd/src/views/common/tab/TabPages.tsx @@ -1,17 +1,19 @@ import React from "react"; -import { useTranslation } from "react-i18next"; -import { convertI18nText, I18nText, UiLogicError } from "@/common"; +import { I18nText, UiLogicError } from "@/common"; + +import Tabs from "./Tabs"; export interface TabPage { - id: string; - tabText: I18nText; + name: string; + text: I18nText; page: React.ReactNode; } export interface TabPagesProps { pages: TabPage[]; actions?: React.ReactNode; + dense?: boolean; className?: string; style?: React.CSSProperties; navClassName?: string; @@ -23,6 +25,7 @@ export interface TabPagesProps { const TabPages: React.FC<TabPagesProps> = ({ pages, actions, + dense, className, style, navClassName, @@ -30,17 +33,13 @@ const TabPages: React.FC<TabPagesProps> = ({ pageContainerClassName, pageContainerStyle, }) => { - // TODO: - if (pages.length === 0) { throw new UiLogicError("Page list can't be empty."); } - const { t } = useTranslation(); - - const [tab, setTab] = React.useState<string>(pages[0].id); + const [tab, setTab] = React.useState<string>(pages[0].name); - const currentPage = pages.find((p) => p.id === tab); + const currentPage = pages.find((p) => p.name === tab); if (currentPage == null) { throw new UiLogicError("Current tab value is bad."); @@ -48,6 +47,20 @@ const TabPages: React.FC<TabPagesProps> = ({ return ( <div className={className} style={style}> + <Tabs + tabs={pages.map((page) => ({ + name: page.name, + text: page.text, + onClick: () => { + setTab(page.name); + }, + }))} + dense={dense} + activeTabName={tab} + className={navClassName} + style={navStyle} + actions={actions} + /> <div className={pageContainerClassName} style={pageContainerStyle}> {currentPage.page} </div> diff --git a/FrontEnd/src/views/common/tab/Tabs.css b/FrontEnd/src/views/common/tab/Tabs.css new file mode 100644 index 00000000..53505a3c --- /dev/null +++ b/FrontEnd/src/views/common/tab/Tabs.css @@ -0,0 +1,31 @@ +.cru-nav {
+ border-bottom: var(--cru-background-2-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:not(.active) {
+ color: var(--cru-primary-r2-color);
+}
+
+.cru-nav-action-area {
+ margin-left: auto;
+}
diff --git a/FrontEnd/src/views/common/tab/Tabs.tsx b/FrontEnd/src/views/common/tab/Tabs.tsx index 29ebcbd8..701b4073 100644 --- a/FrontEnd/src/views/common/tab/Tabs.tsx +++ b/FrontEnd/src/views/common/tab/Tabs.tsx @@ -1,6 +1,11 @@ import React from "react"; +import { Link } from "react-router-dom"; +import { useTranslation } from "react-i18next"; +import classnames from "classnames"; -import { I18nText } from "@/common"; +import { convertI18nText, I18nText } from "@/common"; + +import "./Tabs.css"; export interface Tab { name: string; @@ -11,9 +16,47 @@ export interface Tab { 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 { - return <div></div>; + 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> + ); } |