From c3f17f1dd1099c244e36d09b14c3e131d703830e Mon Sep 17 00:00:00 2001 From: crupest Date: Sat, 26 Jun 2021 19:54:24 +0800 Subject: ... --- FrontEnd/src/index.css | 109 ++++++++++++++++----- FrontEnd/src/index.tsx | 4 - FrontEnd/src/palette.ts | 51 ++++++++-- FrontEnd/src/views/admin/AdminNav.tsx | 50 ++++------ FrontEnd/src/views/center/TimelineBoard.tsx | 4 +- FrontEnd/src/views/center/index.tsx | 2 +- FrontEnd/src/views/common/AppBar.css | 90 +++++++++++++++++ FrontEnd/src/views/common/AppBar.tsx | 2 +- FrontEnd/src/views/common/FullPage.tsx | 39 -------- FrontEnd/src/views/common/LoadingPage.tsx | 5 +- FrontEnd/src/views/common/SearchInput.css | 4 + FrontEnd/src/views/common/SearchInput.tsx | 2 + FrontEnd/src/views/common/TabPages.tsx | 58 ----------- FrontEnd/src/views/common/alert/alert.css | 4 + FrontEnd/src/views/common/alert/alert.sass | 15 --- FrontEnd/src/views/common/button/Button.css | 72 ++++++++++++++ FrontEnd/src/views/common/button/Button.tsx | 9 +- FrontEnd/src/views/common/button/FlatButton.css | 8 +- FrontEnd/src/views/common/button/TextButton.css | 8 +- .../src/views/common/dailog/FullPageDialog.tsx | 39 ++++++++ FrontEnd/src/views/common/index.css | 95 +----------------- FrontEnd/src/views/common/tab/TabPages.tsx | 58 +++++++++++ FrontEnd/src/views/common/tab/Tabs.tsx | 19 ++++ .../src/views/timeline-common/MarkdownPostEdit.tsx | 2 +- .../timeline-common/TimelinePageCardTemplate.tsx | 6 +- FrontEnd/src/views/timeline-common/index.css | 6 +- 26 files changed, 464 insertions(+), 297 deletions(-) create mode 100644 FrontEnd/src/views/common/AppBar.css delete mode 100644 FrontEnd/src/views/common/FullPage.tsx create mode 100644 FrontEnd/src/views/common/SearchInput.css delete mode 100644 FrontEnd/src/views/common/TabPages.tsx create mode 100644 FrontEnd/src/views/common/alert/alert.css delete mode 100644 FrontEnd/src/views/common/alert/alert.sass create mode 100644 FrontEnd/src/views/common/dailog/FullPageDialog.tsx create mode 100644 FrontEnd/src/views/common/tab/TabPages.tsx create mode 100644 FrontEnd/src/views/common/tab/Tabs.tsx (limited to 'FrontEnd/src') diff --git a/FrontEnd/src/index.css b/FrontEnd/src/index.css index 3ca9f10c..d4efabed 100644 --- a/FrontEnd/src/index.css +++ b/FrontEnd/src/index.css @@ -1,36 +1,101 @@ -@import url("./bootstrap-grid.css"); +@import "bootstrap/dist/css/bootstrap-reboot.css"; +@import "bootstrap/dist/css/bootstrap-grid.css"; +@import "bootstrap-icons/font/bootstrap-icons.css"; :root { --tl-background-color: #f8f9fa; --tl-primary-color: rgb(0, 123, 255); - --tl-primary-inactive-color: rgb(26, 136, 255); - --tl-primary-lighter-color: rgb(26, 136, 255); - --tl-primary-darker-color: rgb(0, 111, 230); + --tl-primary-l1-color: rgb(26, 136, 255); + --tl-primary-l2-color: rgb(51, 149, 255); + --tl-primary-l3-color: rgb(77, 163, 255); + --tl-primary-d1-color: rgb(0, 111, 230); + --tl-primary-d2-color: rgb(0, 98, 204); + --tl-primary-d3-color: rgb(0, 86, 179); + --tl-primary-f1-color: rgb(0, 111, 230); + --tl-primary-f2-color: rgb(0, 98, 204); + --tl-primary-f3-color: rgb(0, 86, 179); + --tl-primary-r1-color: rgb(26, 136, 255); + --tl-primary-r2-color: rgb(51, 149, 255); + --tl-primary-r3-color: rgb(77, 163, 255); --tl-primary-enhance-color: rgb(77, 163, 255); - --tl-primary-enhance-inactive-color: rgb(43, 145, 255); - --tl-primary-enhance-lighter-color: rgb(94, 172, 255); - --tl-primary-enhance-darker-color: rgb(43, 145, 255); + --tl-primary-enhance-l1-color: rgb(94, 172, 255); + --tl-primary-enhance-l2-color: rgb(112, 181, 255); + --tl-primary-enhance-l3-color: rgb(130, 190, 255); + --tl-primary-enhance-d1-color: rgb(43, 145, 255); + --tl-primary-enhance-d2-color: rgb(10, 128, 255); + --tl-primary-enhance-d3-color: rgb(0, 112, 232); + --tl-primary-enhance-f1-color: rgb(94, 172, 255); + --tl-primary-enhance-f2-color: rgb(112, 181, 255); + --tl-primary-enhance-f3-color: rgb(130, 190, 255); + --tl-primary-enhance-r1-color: rgb(43, 145, 255); + --tl-primary-enhance-r2-color: rgb(10, 128, 255); + --tl-primary-enhance-r3-color: rgb(0, 112, 232); --tl-secondary-color: rgb(255, 0, 250); - --tl-secondary-inactive-color: rgb(255, 26, 251); - --tl-secondary-lighter-color: rgb(255, 26, 251); - --tl-secondary-darker-color: rgb(230, 0, 225); + --tl-secondary-l1-color: rgb(255, 26, 251); + --tl-secondary-l2-color: rgb(255, 51, 251); + --tl-secondary-l3-color: rgb(255, 77, 252); + --tl-secondary-d1-color: rgb(230, 0, 225); + --tl-secondary-d2-color: rgb(204, 0, 200); + --tl-secondary-d3-color: rgb(179, 0, 175); + --tl-secondary-f1-color: rgb(230, 0, 225); + --tl-secondary-f2-color: rgb(204, 0, 200); + --tl-secondary-f3-color: rgb(179, 0, 175); + --tl-secondary-r1-color: rgb(255, 26, 251); + --tl-secondary-r2-color: rgb(255, 51, 251); + --tl-secondary-r3-color: rgb(255, 77, 252); --tl-text-primary-color: rgb(17, 17, 17); - --tl-text-primary-inactive-color: rgb(41, 41, 41); - --tl-text-primary-lighter-color: rgb(41, 41, 41); - --tl-text-primary-darker-color: rgb(15, 15, 15); + --tl-text-primary-l1-color: rgb(41, 41, 41); + --tl-text-primary-l2-color: rgb(65, 65, 65); + --tl-text-primary-l3-color: rgb(88, 88, 88); + --tl-text-primary-d1-color: rgb(15, 15, 15); + --tl-text-primary-d2-color: rgb(14, 14, 14); + --tl-text-primary-d3-color: rgb(12, 12, 12); + --tl-text-primary-f1-color: rgb(15, 15, 15); + --tl-text-primary-f2-color: rgb(14, 14, 14); + --tl-text-primary-f3-color: rgb(12, 12, 12); + --tl-text-primary-r1-color: rgb(41, 41, 41); + --tl-text-primary-r2-color: rgb(65, 65, 65); + --tl-text-primary-r3-color: rgb(88, 88, 88); --tl-text-on-primary-color: rgb(255, 255, 255); - --tl-text-on-primary-inactive-color: rgb(230, 230, 230); - --tl-text-on-primary-lighter-color: rgb(255, 255, 255); - --tl-text-on-primary-darker-color: rgb(230, 230, 230); + --tl-text-on-primary-l1-color: rgb(255, 255, 255); + --tl-text-on-primary-l2-color: rgb(255, 255, 255); + --tl-text-on-primary-l3-color: rgb(255, 255, 255); + --tl-text-on-primary-d1-color: rgb(230, 230, 230); + --tl-text-on-primary-d2-color: rgb(204, 204, 204); + --tl-text-on-primary-d3-color: rgb(179, 179, 179); + --tl-text-on-primary-f1-color: rgb(255, 255, 255); + --tl-text-on-primary-f2-color: rgb(255, 255, 255); + --tl-text-on-primary-f3-color: rgb(255, 255, 255); + --tl-text-on-primary-r1-color: rgb(230, 230, 230); + --tl-text-on-primary-r2-color: rgb(204, 204, 204); + --tl-text-on-primary-r3-color: rgb(179, 179, 179); --tl-danger-color: rgb(255, 0, 0); - --tl-danger-inactive-color: rgb(255, 26, 26); - --tl-danger-lighter-color: rgb(255, 26, 26); - --tl-danger-darker-color: rgb(230, 0, 0); + --tl-danger-l1-color: rgb(255, 26, 26); + --tl-danger-l2-color: rgb(255, 51, 51); + --tl-danger-l3-color: rgb(255, 77, 77); + --tl-danger-d1-color: rgb(230, 0, 0); + --tl-danger-d2-color: rgb(204, 0, 0); + --tl-danger-d3-color: rgb(179, 0, 0); + --tl-danger-f1-color: rgb(230, 0, 0); + --tl-danger-f2-color: rgb(204, 0, 0); + --tl-danger-f3-color: rgb(179, 0, 0); + --tl-danger-r1-color: rgb(255, 26, 26); + --tl-danger-r2-color: rgb(255, 51, 51); + --tl-danger-r3-color: rgb(255, 77, 77); --tl-success-color: rgb(0, 128, 0); - --tl-success-inactive-color: rgb(0, 166, 0); - --tl-success-lighter-color: rgb(0, 166, 0); - --tl-success-darker-color: rgb(0, 115, 0); + --tl-success-l1-color: rgb(0, 166, 0); + --tl-success-l2-color: rgb(0, 204, 0); + --tl-success-l3-color: rgb(0, 243, 0); + --tl-success-d1-color: rgb(0, 115, 0); + --tl-success-d2-color: rgb(0, 102, 0); + --tl-success-d3-color: rgb(0, 90, 0); + --tl-success-f1-color: rgb(0, 115, 0); + --tl-success-f2-color: rgb(0, 102, 0); + --tl-success-f3-color: rgb(0, 90, 0); + --tl-success-r1-color: rgb(0, 166, 0); + --tl-success-r2-color: rgb(0, 204, 0); + --tl-success-r3-color: rgb(0, 243, 0); } body { diff --git a/FrontEnd/src/index.tsx b/FrontEnd/src/index.tsx index 156fb2d9..e2132de0 100644 --- a/FrontEnd/src/index.tsx +++ b/FrontEnd/src/index.tsx @@ -3,10 +3,6 @@ import "core-js/modules/es.promise"; import "core-js/modules/es.array.iterator"; import "pepjs"; -import "bootstrap/dist/css/bootstrap-reboot.css"; -import "bootstrap/dist/css/bootstrap-grid.css"; -import "bootstrap-icons/font/bootstrap-icons.css"; - import React from "react"; import ReactDOM from "react-dom"; diff --git a/FrontEnd/src/palette.ts b/FrontEnd/src/palette.ts index ab3d6b54..fa99364f 100644 --- a/FrontEnd/src/palette.ts +++ b/FrontEnd/src/palette.ts @@ -15,9 +15,18 @@ function darkenBy(color: Color, ratio: number): Color { export interface PaletteColor { color: string; - lighter: string; - darker: string; - inactive: string; + l1: string; + l2: string; + l3: string; + d1: string; + d2: string; + d3: string; + f1: string; + f2: string; + f3: string; + r1: string; + r2: string; + r3: string; [key: string]: string; } @@ -37,13 +46,34 @@ export type Palette = Record; export function generatePaletteColor(color: string): PaletteColor { const c = Color(color); + const light = c.lightness() > 60; + const l1 = lightenBy(c, 0.1).rgb().toString(); + const l2 = lightenBy(c, 0.2).rgb().toString(); + const l3 = lightenBy(c, 0.3).rgb().toString(); + const d1 = darkenBy(c, 0.1).rgb().toString(); + const d2 = darkenBy(c, 0.2).rgb().toString(); + const d3 = darkenBy(c, 0.3).rgb().toString(); + const f1 = light ? l1 : d1; + const f2 = light ? l2 : d2; + const f3 = light ? l3 : d3; + const r1 = light ? d1 : l1; + const r2 = light ? d2 : l2; + const r3 = light ? d3 : l3; + return { color: c.rgb().toString(), - inactive: (c.lightness() > 60 ? darkenBy(c, 0.1) : lightenBy(c, 0.1)) - .rgb() - .toString(), - lighter: lightenBy(c, 0.1).rgb().toString(), - darker: darkenBy(c, 0.1).rgb().toString(), + l1, + l2, + l3, + d1, + d2, + d3, + f1, + f2, + f3, + r1, + r2, + r3, }; } @@ -91,7 +121,10 @@ export function generatePaletteCSS(palette: Palette): string { } const paletteSubject: BehaviorSubject = - new BehaviorSubject(null); + new BehaviorSubject( + // generatePalette({ primary: "rgb(0, 123, 255)" }) + null + ); export const palette$: Observable = paletteSubject.asObservable(); diff --git a/FrontEnd/src/views/admin/AdminNav.tsx b/FrontEnd/src/views/admin/AdminNav.tsx index 47e2138f..8b4c5fda 100644 --- a/FrontEnd/src/views/admin/AdminNav.tsx +++ b/FrontEnd/src/views/admin/AdminNav.tsx @@ -1,43 +1,29 @@ import React from "react"; -import { Nav } from "react-bootstrap"; -import { useTranslation } from "react-i18next"; -import { useHistory, useRouteMatch } from "react-router"; +import { useRouteMatch } from "react-router"; + +import Tabs from "../common/tab/Tabs"; const AdminNav: React.FC = () => { const match = useRouteMatch<{ name: string }>(); - const history = useHistory(); - - const { t } = useTranslation(); const name = match.params.name; - function toggle(newTab: string): void { - history.push(`/admin/${newTab}`); - } - return ( - + ); }; diff --git a/FrontEnd/src/views/center/TimelineBoard.tsx b/FrontEnd/src/views/center/TimelineBoard.tsx index d6f6228d..d7aa39ab 100644 --- a/FrontEnd/src/views/center/TimelineBoard.tsx +++ b/FrontEnd/src/views/center/TimelineBoard.tsx @@ -1,7 +1,6 @@ import React from "react"; import classnames from "classnames"; import { Link } from "react-router-dom"; -import { Spinner } from "react-bootstrap"; import { HttpTimelineInfo } from "@/http/timeline"; @@ -10,6 +9,7 @@ import UserTimelineLogo from "../common/UserTimelineLogo"; import LoadFailReload from "../common/LoadFailReload"; import FlatButton from "../common/button/FlatButton"; import Card from "../common/Card"; +import Spinner from "../common/Spinner"; interface TimelineBoardItemProps { timeline: HttpTimelineInfo; @@ -249,7 +249,7 @@ const TimelineBoardUI: React.FC = (props) => { if (timelines === "loading") { return (
- +
); } else if (timelines === "offline") { diff --git a/FrontEnd/src/views/center/index.tsx b/FrontEnd/src/views/center/index.tsx index dfad082a..77bb6ec8 100644 --- a/FrontEnd/src/views/center/index.tsx +++ b/FrontEnd/src/views/center/index.tsx @@ -21,7 +21,7 @@ const HomePage: React.FC = () => { return ( <> -
+
{ const { t } = useTranslation(); diff --git a/FrontEnd/src/views/common/FullPage.tsx b/FrontEnd/src/views/common/FullPage.tsx deleted file mode 100644 index 1b59045a..00000000 --- a/FrontEnd/src/views/common/FullPage.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import React from "react"; -import classnames from "classnames"; - -export interface FullPageProps { - show: boolean; - onBack: () => void; - contentContainerClassName?: string; -} - -const FullPage: React.FC = ({ - show, - onBack, - children, - contentContainerClassName, -}) => { - return ( -
-
- -
-
- {children} -
-
- ); -}; - -export default FullPage; diff --git a/FrontEnd/src/views/common/LoadingPage.tsx b/FrontEnd/src/views/common/LoadingPage.tsx index 590fafa0..8c1e681a 100644 --- a/FrontEnd/src/views/common/LoadingPage.tsx +++ b/FrontEnd/src/views/common/LoadingPage.tsx @@ -1,10 +1,11 @@ import React from "react"; -import { Spinner } from "react-bootstrap"; + +import Spinner from "./Spinner"; const LoadingPage: React.FC = () => { return (
- +
); }; diff --git a/FrontEnd/src/views/common/SearchInput.css b/FrontEnd/src/views/common/SearchInput.css new file mode 100644 index 00000000..2943b3a2 --- /dev/null +++ b/FrontEnd/src/views/common/SearchInput.css @@ -0,0 +1,4 @@ +.cru-search-input { + display: flex; + flex-wrap: wrap; +} diff --git a/FrontEnd/src/views/common/SearchInput.tsx b/FrontEnd/src/views/common/SearchInput.tsx index fff11b95..da3f1c19 100644 --- a/FrontEnd/src/views/common/SearchInput.tsx +++ b/FrontEnd/src/views/common/SearchInput.tsx @@ -4,6 +4,8 @@ import { useTranslation } from "react-i18next"; import LoadingButton from "./button/LoadingButton"; +import "./SearchInput.css"; + export interface SearchInputProps { value: string; onChange: (value: string) => void; diff --git a/FrontEnd/src/views/common/TabPages.tsx b/FrontEnd/src/views/common/TabPages.tsx deleted file mode 100644 index b7a9fb36..00000000 --- a/FrontEnd/src/views/common/TabPages.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import React from "react"; -import { useTranslation } from "react-i18next"; - -import { convertI18nText, I18nText, UiLogicError } from "@/common"; - -export interface TabPage { - id: string; - tabText: I18nText; - page: React.ReactNode; -} - -export interface TabPagesProps { - pages: TabPage[]; - actions?: React.ReactNode; - className?: string; - style?: React.CSSProperties; - navClassName?: string; - navStyle?: React.CSSProperties; - pageContainerClassName?: string; - pageContainerStyle?: React.CSSProperties; -} - -const TabPages: React.FC = ({ - pages, - actions, - className, - style, - navClassName, - navStyle, - pageContainerClassName, - pageContainerStyle, -}) => { - // TODO: - - if (pages.length === 0) { - throw new UiLogicError("Page list can't be empty."); - } - - const { t } = useTranslation(); - - const [tab, setTab] = React.useState(pages[0].id); - - const currentPage = pages.find((p) => p.id === tab); - - if (currentPage == null) { - throw new UiLogicError("Current tab value is bad."); - } - - return ( -
-
- {currentPage.page} -
-
- ); -}; - -export default TabPages; diff --git a/FrontEnd/src/views/common/alert/alert.css b/FrontEnd/src/views/common/alert/alert.css new file mode 100644 index 00000000..12ce294e --- /dev/null +++ b/FrontEnd/src/views/common/alert/alert.css @@ -0,0 +1,4 @@ +.alert-container { + position: fixed; + z-index: 1040; +} diff --git a/FrontEnd/src/views/common/alert/alert.sass b/FrontEnd/src/views/common/alert/alert.sass deleted file mode 100644 index c3560b87..00000000 --- a/FrontEnd/src/views/common/alert/alert.sass +++ /dev/null @@ -1,15 +0,0 @@ -.alert-container - position: fixed - z-index: $zindex-popover - -@include media-breakpoint-up(sm) - .alert-container - bottom: 0 - right: 0 - -@include media-breakpoint-down(sm) - .alert-container - bottom: 0 - right: 0 - left: 0 - text-align: center diff --git a/FrontEnd/src/views/common/button/Button.css b/FrontEnd/src/views/common/button/Button.css index e69de29b..b6df222f 100644 --- a/FrontEnd/src/views/common/button/Button.css +++ b/FrontEnd/src/views/common/button/Button.css @@ -0,0 +1,72 @@ +.cru-button { + color: white; + cursor: pointer; + padding: 0.2em 0.5em; + border-radius: 0.2em; + border: none; + transition: all 0.6s; +} + +.cru-button.primary { + background-color: var(--tl-primary-color); +} + +.cru-button.primary:hover { + background-color: var(--tl-primary-f1-color); +} + +.cru-button.primary:active { + background-color: var(--tl-primary-f2-color); +} + +.cru-button.primary.disabled { + background-color: var(--tl-primary-f3-color); +} + +.cru-button.secondary { + background-color: var(--tl-secondary-color); +} + +.cru-button.secondary:hover { + background-color: var(--tl-secondary-f1-color); +} + +.cru-button.secondary:active { + background-color: var(--tl-secondary-f2-color); +} + +.cru-button.secondary.disabled { + background-color: var(--tl-secondary-f3-color); +} + +.cru-button.success { + background-color: var(--tl-success-color); +} + +.cru-button.success:hover { + background-color: var(--tl-success-f1-color); +} + +.cru-button.success:active { + background-color: var(--tl-success-f2-color); +} + +.cru-button.success.disabled { + background-color: var(--tl-success-f3-color); +} + +.cru-button.danger { + background-color: var(--tl-danger-color); +} + +.cru-button.danger:hover { + background-color: var(--tl-danger-f1-color); +} + +.cru-button.danger:active { + background-color: var(--tl-danger-f2-color); +} + +.cru-button.danger.disabled { + background-color: var(--tl-danger-f3-color); +} diff --git a/FrontEnd/src/views/common/button/Button.tsx b/FrontEnd/src/views/common/button/Button.tsx index 11710647..a39ef8a7 100644 --- a/FrontEnd/src/views/common/button/Button.tsx +++ b/FrontEnd/src/views/common/button/Button.tsx @@ -6,16 +6,19 @@ import { calculateProps, CommonButtonProps } from "./common"; import "./Button.css"; function _Button( - props: CommonButtonProps & { customButtonClassName?: string }, + props: CommonButtonProps & { + outline?: boolean; + customButtonClassName?: string; + }, ref: React.ForwardedRef ): React.ReactElement | null { const { t } = useTranslation(); - const { customButtonClassName, ...otherProps } = props; + const { customButtonClassName, outline, ...otherProps } = props; const { newProps, children } = calculateProps( otherProps, - customButtonClassName ?? "cru-button", + customButtonClassName ?? "cru-button" + (outline ? " outline" : ""), t ); diff --git a/FrontEnd/src/views/common/button/FlatButton.css b/FrontEnd/src/views/common/button/FlatButton.css index 522563b9..c3c0dbb3 100644 --- a/FrontEnd/src/views/common/button/FlatButton.css +++ b/FrontEnd/src/views/common/button/FlatButton.css @@ -20,7 +20,7 @@ } .cru-flat-button.primary.disabled { - color: var(--tl-primary-lighter-color); + color: var(--tl-primary-l1-color); } .cru-flat-button.secondary { @@ -28,7 +28,7 @@ } .cru-flat-button.secondary.disabled { - color: var(--tl-secondary-lighter-color); + color: var(--tl-secondary-l1-color); } .cru-flat-button.success { @@ -36,7 +36,7 @@ } .cru-flat-button.success.disabled { - color: var(--tl-success-lighter-color); + color: var(--tl-success-l1-color); } .cru-flat-button.danger { @@ -44,5 +44,5 @@ } .cru-flat-button.danger.disabled { - color: var(--tl-danger-ligher-color); + color: var(--tl-danger-l1-color); } diff --git a/FrontEnd/src/views/common/button/TextButton.css b/FrontEnd/src/views/common/button/TextButton.css index dc5abaaa..d267fb38 100644 --- a/FrontEnd/src/views/common/button/TextButton.css +++ b/FrontEnd/src/views/common/button/TextButton.css @@ -8,7 +8,7 @@ } .cru-text-button.primary:hover { - color: var(--tl-primary-lighter-color); + color: var(--tl-primary-l1-color); } .cru-text-button.secondary { @@ -16,7 +16,7 @@ } .cru-text-button.secondary:hover { - color: var(--tl-secondary-lighter-color); + color: var(--tl-secondary-l1-color); } .cru-text-button.success { @@ -24,7 +24,7 @@ } .cru-text-button.success:hover { - color: var(--tl-success-lighter-color); + color: var(--tl-success-l1-color); } .cru-text-button.danger { @@ -32,5 +32,5 @@ } .cru-text-button.danger:hover { - color: var(--tl-danger-lighter-color); + color: var(--tl-danger-l1-color); } diff --git a/FrontEnd/src/views/common/dailog/FullPageDialog.tsx b/FrontEnd/src/views/common/dailog/FullPageDialog.tsx new file mode 100644 index 00000000..88c90bbc --- /dev/null +++ b/FrontEnd/src/views/common/dailog/FullPageDialog.tsx @@ -0,0 +1,39 @@ +import React from "react"; +import classnames from "classnames"; + +export interface FullPageDialogProps { + show: boolean; + onBack: () => void; + contentContainerClassName?: string; +} + +const FullPageDialog: React.FC = ({ + show, + onBack, + children, + contentContainerClassName, +}) => { + return ( +
+
+ +
+
+ {children} +
+
+ ); +}; + +export default FullPageDialog; diff --git a/FrontEnd/src/views/common/index.css b/FrontEnd/src/views/common/index.css index bfd82b58..f580c781 100644 --- a/FrontEnd/src/views/common/index.css +++ b/FrontEnd/src/views/common/index.css @@ -37,96 +37,6 @@ touch-action: none; } -.app-bar { - display: flex; - align-items: center; - height: 56px; - position: fixed; - z-index: 1030; - top: 0; - left: 0; - right: 0; - background-color: var(--tl-primary-color); - transition: background-color 1s; -} -.app-bar a { - color: var(--tl-text-on-primary-inactive-color); - text-decoration: none; - margin: 0 1em; -} -.app-bar a:hover { - color: var(--tl-text-on-primary-color); -} -.app-bar a.active { - color: var(--tl-text-on-primary-color); -} - -.app-bar-brand { - display: flex; - align-items: center; -} - -.app-bar-brand-icon { - height: 2em; -} - -.app-bar-main-area { - display: flex; - flex-grow: 1; -} - -.app-bar-link-area { - display: flex; - align-items: center; - flex-shrink: 0; -} - -.app-bar-user-area { - display: flex; - align-items: center; - flex-shrink: 0; - margin-left: auto; -} - -.small-screen .app-bar-main-area { - position: absolute; - top: 56px; - left: 0; - right: 0; - transform-origin: top; - transition: transform 0.6s, background-color 1s; - background-color: var(--tl-primary-color); - flex-direction: column; -} -.small-screen .app-bar-main-area.app-bar-collapse { - transform: scale(1, 0); -} -.small-screen .app-bar-main-area a { - text-align: left; - padding: 0.5em 0.5em; -} -.small-screen .app-bar-link-area { - flex-direction: column; - align-items: stretch; -} -.small-screen .app-bar-user-area { - flex-direction: column; - align-items: stretch; - margin-left: unset; -} -.small-screen .app-bar-avatar { - align-self: flex-end; -} - -.app-bar-toggler { - margin-left: auto; - font-size: 2em; - margin-right: 1em; - color: var(--tl-text-on-primary-color); - cursor: pointer; - user-select: none; -} - .cru-skeleton { padding: 0 1em; } @@ -247,10 +157,7 @@ align-items: center; } -.cru-search-input { - display: flex; - flex-wrap: wrap; -} + .alert-container { position: fixed; diff --git a/FrontEnd/src/views/common/tab/TabPages.tsx b/FrontEnd/src/views/common/tab/TabPages.tsx new file mode 100644 index 00000000..b7a9fb36 --- /dev/null +++ b/FrontEnd/src/views/common/tab/TabPages.tsx @@ -0,0 +1,58 @@ +import React from "react"; +import { useTranslation } from "react-i18next"; + +import { convertI18nText, I18nText, UiLogicError } from "@/common"; + +export interface TabPage { + id: string; + tabText: I18nText; + page: React.ReactNode; +} + +export interface TabPagesProps { + pages: TabPage[]; + actions?: React.ReactNode; + className?: string; + style?: React.CSSProperties; + navClassName?: string; + navStyle?: React.CSSProperties; + pageContainerClassName?: string; + pageContainerStyle?: React.CSSProperties; +} + +const TabPages: React.FC = ({ + pages, + actions, + className, + style, + navClassName, + navStyle, + pageContainerClassName, + pageContainerStyle, +}) => { + // TODO: + + if (pages.length === 0) { + throw new UiLogicError("Page list can't be empty."); + } + + const { t } = useTranslation(); + + const [tab, setTab] = React.useState(pages[0].id); + + const currentPage = pages.find((p) => p.id === tab); + + if (currentPage == null) { + throw new UiLogicError("Current tab value is bad."); + } + + return ( +
+
+ {currentPage.page} +
+
+ ); +}; + +export default TabPages; diff --git a/FrontEnd/src/views/common/tab/Tabs.tsx b/FrontEnd/src/views/common/tab/Tabs.tsx new file mode 100644 index 00000000..29ebcbd8 --- /dev/null +++ b/FrontEnd/src/views/common/tab/Tabs.tsx @@ -0,0 +1,19 @@ +import React from "react"; + +import { I18nText } from "@/common"; + +export interface Tab { + name: string; + text: I18nText; + link?: string; + onClick?: () => void; +} + +export interface TabsProps { + activeTabName?: string; + tabs: Tab[]; +} + +export default function Tabs(props: TabsProps): React.ReactElement | null { + return
; +} diff --git a/FrontEnd/src/views/timeline-common/MarkdownPostEdit.tsx b/FrontEnd/src/views/timeline-common/MarkdownPostEdit.tsx index 9f0753b9..b16bf43d 100644 --- a/FrontEnd/src/views/timeline-common/MarkdownPostEdit.tsx +++ b/FrontEnd/src/views/timeline-common/MarkdownPostEdit.tsx @@ -9,7 +9,7 @@ import { getHttpTimelineClient, HttpTimelinePostInfo } from "@/http/timeline"; import TimelinePostBuilder from "@/services/TimelinePostBuilder"; import FlatButton from "../common/button/FlatButton"; -import TabPages from "../common/TabPages"; +import TabPages from "../common/tab/TabPages"; import ConfirmDialog from "../common/dailog/ConfirmDialog"; import Spinner from "../common/Spinner"; diff --git a/FrontEnd/src/views/timeline-common/TimelinePageCardTemplate.tsx b/FrontEnd/src/views/timeline-common/TimelinePageCardTemplate.tsx index 851dfa55..78057be2 100644 --- a/FrontEnd/src/views/timeline-common/TimelinePageCardTemplate.tsx +++ b/FrontEnd/src/views/timeline-common/TimelinePageCardTemplate.tsx @@ -18,7 +18,7 @@ import { TimelineMemberDialog } from "./TimelineMember"; import TimelinePropertyChangeDialog from "./TimelinePropertyChangeDialog"; import ConnectionStatusBadge from "./ConnectionStatusBadge"; import { MenuItems, PopupMenu } from "../common/Menu"; -import FullPage from "../common/FullPage"; +import FullPageDialog from "../common/dailog/FullPageDialog"; import Card from "../common/Card"; export interface TimelineCardTemplateProps extends TimelinePageCardProps { @@ -120,13 +120,13 @@ const TimelinePageCardTemplate: React.FC = ({
{isSmallScreen ? ( - {content} - + ) : (
{content}
)} diff --git a/FrontEnd/src/views/timeline-common/index.css b/FrontEnd/src/views/timeline-common/index.css index e38d0ba7..b78564a3 100644 --- a/FrontEnd/src/views/timeline-common/index.css +++ b/FrontEnd/src/views/timeline-common/index.css @@ -13,19 +13,19 @@ @keyframes timeline-line-node-noncurrent { to { - box-shadow: 0 0 20px 3px var(--tl-primary-lighter-color); + box-shadow: 0 0 20px 3px var(--tl-primary-l1-color); } } @keyframes timeline-line-node-current { to { - box-shadow: 0 0 20px 3px var(--tl-primary-enhance-lighter-color); + box-shadow: 0 0 20px 3px var(--tl-primary-enhance-l1-color); } } @keyframes timeline-line-node-loading { to { - box-shadow: 0 0 20px 3px var(--tl-primary-lighter-color); + box-shadow: 0 0 20px 3px var(--tl-primary-l1-color); } } -- cgit v1.2.3