From 0e183074b326cf04a23ae1f1ba8dcc56166df485 Mon Sep 17 00:00:00 2001 From: crupest Date: Thu, 20 Jul 2023 20:44:15 +0800 Subject: ... --- FrontEnd/src/pages/setting/index.css | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 FrontEnd/src/pages/setting/index.css (limited to 'FrontEnd/src/pages/setting/index.css') diff --git a/FrontEnd/src/pages/setting/index.css b/FrontEnd/src/pages/setting/index.css new file mode 100644 index 00000000..ccf7a97a --- /dev/null +++ b/FrontEnd/src/pages/setting/index.css @@ -0,0 +1,31 @@ +.change-avatar-cropper-row { + max-height: 400px; +} + +.change-avatar-img { + min-width: 50%; + max-width: 100%; + max-height: 400px; +} + +.settings-item { + padding: 0.5em 1em; + transition: background 0.3s; + border-bottom: 1px solid #e9ecef; + align-items: center; +} +.settings-item.first { + border-top: 1px solid #e9ecef; +} +.settings-item.clickable { + cursor: pointer; +} +.settings-item:hover { + background: #dee2e6; +} + +.register-code { + border: 1px solid black; + border-radius: 3px; + padding: 0.2em; +} \ No newline at end of file -- cgit v1.2.3 From d7b050ef7f047f841ffcda96fbdc9857574e97b9 Mon Sep 17 00:00:00 2001 From: crupest Date: Fri, 21 Jul 2023 17:02:05 +0800 Subject: ... --- FrontEnd/src/App.tsx | 8 +- FrontEnd/src/index.css | 1 - FrontEnd/src/pages/about/index.css | 1 - FrontEnd/src/pages/about/index.tsx | 5 +- FrontEnd/src/pages/setting/ChangeAvatarDialog.tsx | 6 +- .../src/pages/setting/ChangeNicknameDialog.tsx | 2 +- .../src/pages/setting/ChangePasswordDialog.tsx | 2 +- FrontEnd/src/pages/setting/index.css | 54 +++- FrontEnd/src/pages/setting/index.tsx | 171 +++++----- FrontEnd/src/views/common/Card.css | 8 +- FrontEnd/src/views/common/Card.tsx | 8 +- FrontEnd/src/views/common/Page.tsx | 15 + FrontEnd/src/views/common/index.css | 8 + FrontEnd/src/views/common/theme.css | 5 +- FrontEnd/src/views/settings/ChangeAvatarDialog.tsx | 354 --------------------- .../src/views/settings/ChangeNicknameDialog.tsx | 34 -- .../src/views/settings/ChangePasswordDialog.tsx | 69 ---- FrontEnd/src/views/settings/index.css | 31 -- FrontEnd/src/views/settings/index.tsx | 338 -------------------- 19 files changed, 182 insertions(+), 938 deletions(-) create mode 100644 FrontEnd/src/views/common/Page.tsx delete mode 100644 FrontEnd/src/views/settings/ChangeAvatarDialog.tsx delete mode 100644 FrontEnd/src/views/settings/ChangeNicknameDialog.tsx delete mode 100644 FrontEnd/src/views/settings/ChangePasswordDialog.tsx delete mode 100644 FrontEnd/src/views/settings/index.css delete mode 100644 FrontEnd/src/views/settings/index.tsx (limited to 'FrontEnd/src/pages/setting/index.css') diff --git a/FrontEnd/src/App.tsx b/FrontEnd/src/App.tsx index 07a8780f..92fe0652 100644 --- a/FrontEnd/src/App.tsx +++ b/FrontEnd/src/App.tsx @@ -4,11 +4,11 @@ import { BrowserRouter, Route, Routes } from "react-router-dom"; import AppBar from "./views/common/AppBar"; import NotFoundPage from "./pages/404"; import LoadingPage from "./views/common/LoadingPage"; -import About from "./pages/about"; +import AboutPage from "./pages/about"; +import SettingPage from "./pages/setting"; import Center from "./views/center"; import Login from "./views/login"; import Register from "./views/register"; -import Settings from "./views/settings"; import TimelinePage from "./views/timeline"; import Search from "./views/search"; import Admin from "./views/admin"; @@ -24,8 +24,8 @@ export default function App() { } /> } /> } /> - } /> - } /> + } /> + } /> } /> } /> } /> diff --git a/FrontEnd/src/index.css b/FrontEnd/src/index.css index 3478db05..49791c23 100644 --- a/FrontEnd/src/index.css +++ b/FrontEnd/src/index.css @@ -1,4 +1,3 @@ -@import "npm:bootstrap/dist/css/bootstrap-grid.css"; @import "npm:bootstrap-icons/font/bootstrap-icons.css"; @import "./views/common/index.css"; diff --git a/FrontEnd/src/pages/about/index.css b/FrontEnd/src/pages/about/index.css index 487f4a0a..1ce7a7c8 100644 --- a/FrontEnd/src/pages/about/index.css +++ b/FrontEnd/src/pages/about/index.css @@ -1,5 +1,4 @@ .about-page { - padding: 1em 2em; line-height: 1.5; } diff --git a/FrontEnd/src/pages/about/index.tsx b/FrontEnd/src/pages/about/index.tsx index afd4de34..acec1735 100644 --- a/FrontEnd/src/pages/about/index.tsx +++ b/FrontEnd/src/pages/about/index.tsx @@ -1,6 +1,7 @@ import "./index.css"; import { useC } from "@/common"; +import Page from "@/views/common/Page"; interface Credit { name: string; @@ -52,7 +53,7 @@ export default function AboutPage() { const c = useC(); return ( -
+

{c("about.credits.title")}

{c("about.credits.content")}

{c("about.credits.frontend")}

@@ -81,6 +82,6 @@ export default function AboutPage() { })}
  • ...
  • -
    + ); } diff --git a/FrontEnd/src/pages/setting/ChangeAvatarDialog.tsx b/FrontEnd/src/pages/setting/ChangeAvatarDialog.tsx index 44bd2c68..b2a4e2a8 100644 --- a/FrontEnd/src/pages/setting/ChangeAvatarDialog.tsx +++ b/FrontEnd/src/pages/setting/ChangeAvatarDialog.tsx @@ -9,9 +9,9 @@ import { useUser } from "@/services/user"; import { getHttpUserClient } from "@/http/user"; -import ImageCropper, { Clip, applyClipToImage } from "../common/ImageCropper"; -import Button from "../common/button/Button"; -import Dialog from "../common/dialog/Dialog"; +import ImageCropper, { Clip, applyClipToImage } from "@/views/common/ImageCropper"; +import Button from "@/views/common/button/Button"; +import Dialog from "@/views/common/dialog/Dialog"; export interface ChangeAvatarDialogProps { open: boolean; diff --git a/FrontEnd/src/pages/setting/ChangeNicknameDialog.tsx b/FrontEnd/src/pages/setting/ChangeNicknameDialog.tsx index 7ba12de8..11c86222 100644 --- a/FrontEnd/src/pages/setting/ChangeNicknameDialog.tsx +++ b/FrontEnd/src/pages/setting/ChangeNicknameDialog.tsx @@ -2,7 +2,7 @@ import { getHttpUserClient } from "@/http/user"; import { useUser } from "@/services/user"; import * as React from "react"; -import OperationDialog from "../common/dialog/OperationDialog"; +import OperationDialog from "@/views/common/dialog/OperationDialog"; export interface ChangeNicknameDialogProps { open: boolean; diff --git a/FrontEnd/src/pages/setting/ChangePasswordDialog.tsx b/FrontEnd/src/pages/setting/ChangePasswordDialog.tsx index a34ca4a7..a523b454 100644 --- a/FrontEnd/src/pages/setting/ChangePasswordDialog.tsx +++ b/FrontEnd/src/pages/setting/ChangePasswordDialog.tsx @@ -4,7 +4,7 @@ import { useNavigate } from "react-router-dom"; import { userService } from "@/services/user"; -import OperationDialog from "../common/dialog/OperationDialog"; +import OperationDialog from "@/views/common/dialog/OperationDialog"; export interface ChangePasswordDialogProps { open: boolean; diff --git a/FrontEnd/src/pages/setting/index.css b/FrontEnd/src/pages/setting/index.css index ccf7a97a..af5ccf20 100644 --- a/FrontEnd/src/pages/setting/index.css +++ b/FrontEnd/src/pages/setting/index.css @@ -1,3 +1,5 @@ +/* TODO: Make item prettier. */ + .change-avatar-cropper-row { max-height: 400px; } @@ -8,20 +10,56 @@ max-height: 400px; } -.settings-item { +.setting-section { + padding: 1em 0; + margin: 1em 0; +} + +.setting-section-title { + padding: 0 1em; +} + +.setting-section-item-area { + margin-top: 1em; + border-top: 1px solid var(--cru-key-container-color); +} + +.setting-item-container { padding: 0.5em 1em; - transition: background 0.3s; - border-bottom: 1px solid #e9ecef; + transition: background-color 0.3s; + color: var(--cru-surface-on-color); + background-color: var(--cru-surface-color); + border-bottom: 1px solid var(--cru-key-container-color); + display: flex; align-items: center; } -.settings-item.first { - border-top: 1px solid #e9ecef; + +.setting-item-container:hover { + background-color: var(--cru-key-container-1-color); + border-bottom-color: var(--cru-key-container-1-color); +} + +.setting-item-label-sub { + color: var(--cru-secondary-text-color); } -.settings-item.clickable { + +.setting-item-container.setting-type-button { cursor: pointer; } -.settings-item:hover { - background: #dee2e6; + +.setting-item-container.setting-type-button.danger { + color: var(--cru-danger-color); +} + + +@media (max-width: 576) { + .setting-item-container.setting-type-select { + flex-direction: column; + } + + .setting-item-container.setting-type-select .setting-item-value-area { + margin-top: 1em; + } } .register-code { diff --git a/FrontEnd/src/pages/setting/index.tsx b/FrontEnd/src/pages/setting/index.tsx index 4e28585e..5d6dcbc0 100644 --- a/FrontEnd/src/pages/setting/index.tsx +++ b/FrontEnd/src/pages/setting/index.tsx @@ -11,11 +11,11 @@ import classNames from "classnames"; import { useC, Text } from "@/common"; import { useUser, userService } from "@/services/user"; import { getHttpUserClient } from "@/http/user"; -import { TimelineVisibility } from "@/http/timeline"; import ConfirmDialog from "@/views/common/dialog/ConfirmDialog"; import Card from "@/views/common/Card"; import Spinner from "@/views/common/Spinner"; +import Page from "@/views/common/Page"; import ChangePasswordDialog from "./ChangePasswordDialog"; import ChangeAvatarDialog from "./ChangeAvatarDialog"; import ChangeNicknameDialog from "./ChangeNicknameDialog"; @@ -24,9 +24,9 @@ import "./index.css"; import { pushAlert } from "@/services/alert"; interface SettingSectionProps - extends Omit, "title"> { + extends Omit, "title"> { title: Text; - children: ReactNode; + children?: ReactNode; } function SettingSection({ @@ -40,7 +40,7 @@ function SettingSection({ return (

    {c(title)}

    - {children} +
    {children}
    ); } @@ -115,6 +115,7 @@ function SelectSettingsItem({ ) : ( - - -
    -
    -
    - - ); - } else if (state === "crop") { - if (fileUrl == null) { - throw new UiLogicError(); - } - return ( - <> -
    -
    - -
    -
    - {t("settings.dialogChangeAvatar.prompt.crop")} -
    -
    -
    -
    -
    - - ); - } else if (state === "processcrop") { - return ( - <> -
    -
    - {t("settings.dialogChangeAvatar.prompt.processingCrop")} -
    -
    -
    -
    -
    - - ); - } else if (state === "preview") { - return ( - <> -
    - {createPreviewRow()} -
    - {t("settings.dialogChangeAvatar.prompt.preview")} -
    -
    -
    -
    -
    - - ); - } else if (state === "uploading") { - return ( - <> -
    - {createPreviewRow()} -
    - {t("settings.dialogChangeAvatar.prompt.uploading")} -
    -
    - - ); - } else if (state === "success") { - return ( - <> -
    -
    - {t("operationDialog.success")} -
    -
    -
    -
    -
    - - ); - } else { - return ( - <> -
    - {createPreviewRow()} -
    {trueMessage}
    -
    -
    -
    -
    - - ); - } - })()} - - ); -}; - -export default ChangeAvatarDialog; diff --git a/FrontEnd/src/views/settings/ChangeNicknameDialog.tsx b/FrontEnd/src/views/settings/ChangeNicknameDialog.tsx deleted file mode 100644 index 7ba12de8..00000000 --- a/FrontEnd/src/views/settings/ChangeNicknameDialog.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { getHttpUserClient } from "@/http/user"; -import { useUser } from "@/services/user"; -import * as React from "react"; - -import OperationDialog from "../common/dialog/OperationDialog"; - -export interface ChangeNicknameDialogProps { - open: boolean; - close: () => void; -} - -const ChangeNicknameDialog: React.FC = (props) => { - const user = useUser(); - - if (user == null) return null; - - return ( - { - return getHttpUserClient().patch(user.username, { - nickname: newNickname, - }); - }} - onClose={props.close} - /> - ); -}; - -export default ChangeNicknameDialog; diff --git a/FrontEnd/src/views/settings/ChangePasswordDialog.tsx b/FrontEnd/src/views/settings/ChangePasswordDialog.tsx deleted file mode 100644 index a34ca4a7..00000000 --- a/FrontEnd/src/views/settings/ChangePasswordDialog.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { useState } from "react"; -import * as React from "react"; -import { useNavigate } from "react-router-dom"; - -import { userService } from "@/services/user"; - -import OperationDialog from "../common/dialog/OperationDialog"; - -export interface ChangePasswordDialogProps { - open: boolean; - close: () => void; -} - -const ChangePasswordDialog: React.FC = (props) => { - const navigate = useNavigate(); - - const [redirect, setRedirect] = useState(false); - - return ( - { - const result: Record = {}; - if (oldPassword === "") { - result[0] = "settings.dialogChangePassword.errorEmptyOldPassword"; - } - if (newPassword === "") { - result[1] = "settings.dialogChangePassword.errorEmptyNewPassword"; - } - if (retypedNewPassword !== newPassword) { - result[2] = "settings.dialogChangePassword.errorRetypeNotMatch"; - } - return result; - }} - onProcess={async ([oldPassword, newPassword]) => { - await userService.changePassword(oldPassword, newPassword); - setRedirect(true); - }} - onClose={() => { - props.close(); - if (redirect) { - navigate("/login"); - } - }} - /> - ); -}; - -export default ChangePasswordDialog; diff --git a/FrontEnd/src/views/settings/index.css b/FrontEnd/src/views/settings/index.css deleted file mode 100644 index ccf7a97a..00000000 --- a/FrontEnd/src/views/settings/index.css +++ /dev/null @@ -1,31 +0,0 @@ -.change-avatar-cropper-row { - max-height: 400px; -} - -.change-avatar-img { - min-width: 50%; - max-width: 100%; - max-height: 400px; -} - -.settings-item { - padding: 0.5em 1em; - transition: background 0.3s; - border-bottom: 1px solid #e9ecef; - align-items: center; -} -.settings-item.first { - border-top: 1px solid #e9ecef; -} -.settings-item.clickable { - cursor: pointer; -} -.settings-item:hover { - background: #dee2e6; -} - -.register-code { - border: 1px solid black; - border-radius: 3px; - padding: 0.2em; -} \ No newline at end of file diff --git a/FrontEnd/src/views/settings/index.tsx b/FrontEnd/src/views/settings/index.tsx deleted file mode 100644 index 6647826f..00000000 --- a/FrontEnd/src/views/settings/index.tsx +++ /dev/null @@ -1,338 +0,0 @@ -import { useState } from "react"; -import * as React from "react"; -import { useNavigate } from "react-router-dom"; -import { useTranslation } from "react-i18next"; -import classNames from "classnames"; - -import { convertI18nText, I18nText, UiLogicError } from "@/common"; -import { useUser, userService } from "@/services/user"; -import { getHttpUserClient } from "@/http/user"; -import { TimelineVisibility } from "@/http/timeline"; - -import ConfirmDialog from "../common/dialog/ConfirmDialog"; -import Card from "../common/Card"; -import Spinner from "../common/Spinner"; -import ChangePasswordDialog from "./ChangePasswordDialog"; -import ChangeAvatarDialog from "./ChangeAvatarDialog"; -import ChangeNicknameDialog from "./ChangeNicknameDialog"; - -import "./index.css"; -import { pushAlert } from "@/services/alert"; - -interface SettingSectionProps { - title: I18nText; - children: React.ReactNode; -} - -const SettingSection: React.FC = ({ title, children }) => { - const { t } = useTranslation(); - - return ( - -

    - {convertI18nText(title, t)} -

    - {children} -
    - ); -}; - -interface SettingItemContainerWithoutChildrenProps { - title: I18nText; - subtext?: I18nText; - first?: boolean; - danger?: boolean; - style?: React.CSSProperties; - className?: string; - onClick?: () => void; -} - -interface SettingItemContainerProps - extends SettingItemContainerWithoutChildrenProps { - children?: React.ReactNode; -} - -function SettingItemContainer({ - title, - subtext, - first, - danger, - children, - style, - className, - onClick, -}: SettingItemContainerProps): JSX.Element { - const { t } = useTranslation(); - - return ( -
    -
    -
    - {convertI18nText(title, t)} -
    - - {convertI18nText(subtext, t)} - -
    -
    {children}
    -
    - ); -} - -type ButtonSettingItemProps = SettingItemContainerWithoutChildrenProps; - -const ButtonSettingItem: React.FC = ({ ...props }) => { - return ; -}; - -interface SelectSettingItemProps - extends SettingItemContainerWithoutChildrenProps { - options: { - value: string; - label: I18nText; - }[]; - value?: string; - onSelect: (value: string) => void; -} - -const SelectSettingsItem: React.FC = ({ - options, - value, - onSelect, - ...props -}) => { - const { t } = useTranslation(); - - return ( - - {value == null ? ( - - ) : ( - - )} - - ); -}; - -const SettingsPage: React.FC = () => { - const { i18n } = useTranslation(); - const user = useUser(); - const navigate = useNavigate(); - - const [dialog, setDialog] = useState< - | null - | "changepassword" - | "changeavatar" - | "changenickname" - | "logout" - | "renewregistercode" - >(null); - - const [registerCode, setRegisterCode] = useState( - undefined, - ); - - const [bookmarkVisibility, setBookmarkVisibility] = - useState(); - - React.useEffect(() => { - if (user != null) { - void getHttpUserClient() - .getBookmarkVisibility(user.username) - .then(({ visibility }) => { - setBookmarkVisibility(visibility); - }); - } else { - setBookmarkVisibility(undefined); - } - }, [user]); - - React.useEffect(() => { - setRegisterCode(undefined); - }, [user]); - - React.useEffect(() => { - if (user != null && registerCode === undefined) { - void getHttpUserClient() - .getRegisterCode(user.username) - .then((code) => { - setRegisterCode(code.registerCode ?? null); - }); - } - }, [user, registerCode]); - - const language = i18n.language.slice(0, 2); - - return ( - <> -
    - {user ? ( - - setDialog("renewregistercode")} - > - {registerCode === undefined ? ( - - ) : registerCode === null ? ( - Noop - ) : ( - { - void navigator.clipboard - .writeText(registerCode) - .then(() => { - pushAlert({ - type: "success", - message: "settings.myRegisterCodeCopied", - }); - }); - event.stopPropagation(); - }} - > - {registerCode} - - )} - - setDialog("changeavatar")} - first - /> - setDialog("changenickname")} - /> - { - void getHttpUserClient() - .putBookmarkVisibility(user.username, { - visibility: value as TimelineVisibility, - }) - .then(() => { - setBookmarkVisibility(value as TimelineVisibility); - }); - }} - /> - setDialog("changepassword")} - danger - /> - { - setDialog("logout"); - }} - danger - /> - - ) : null} - - { - void i18n.changeLanguage(value); - }} - first - /> - -
    - setDialog(null)} - /> - setDialog(null)} - open={dialog === "logout"} - onConfirm={() => { - void userService.logout().then(() => { - navigate("/"); - }); - }} - /> - setDialog(null)} - open={dialog === "renewregistercode"} - onConfirm={() => { - if (user == null) throw new UiLogicError(); - void getHttpUserClient() - .renewRegisterCode(user.username) - .then(() => { - setRegisterCode(undefined); - }); - }} - /> - setDialog(null)} - /> - setDialog(null)} - /> - - ); -}; - -export default SettingsPage; -- cgit v1.2.3 From 4c4bb2d0a25702b840ef56e1e236498376f66bee Mon Sep 17 00:00:00 2001 From: crupest Date: Fri, 21 Jul 2023 17:07:28 +0800 Subject: ... --- FrontEnd/src/pages/setting/index.css | 23 ++++++++++++++++++----- FrontEnd/src/pages/setting/index.tsx | 1 + 2 files changed, 19 insertions(+), 5 deletions(-) (limited to 'FrontEnd/src/pages/setting/index.css') diff --git a/FrontEnd/src/pages/setting/index.css b/FrontEnd/src/pages/setting/index.css index af5ccf20..9458d937 100644 --- a/FrontEnd/src/pages/setting/index.css +++ b/FrontEnd/src/pages/setting/index.css @@ -43,6 +43,10 @@ color: var(--cru-secondary-text-color); } +.setting-item-value-area { + margin-left: auto; +} + .setting-item-container.setting-type-button { cursor: pointer; } @@ -51,6 +55,13 @@ color: var(--cru-danger-color); } +.register-code { + background: var(--cru-surface-container-highest-color); + border: 1px solid var(--cru-surface-container-highest-color); + border-radius: 3px; + padding: 0.2em; + cursor: pointer; +} @media (max-width: 576) { .setting-item-container.setting-type-select { @@ -60,10 +71,12 @@ .setting-item-container.setting-type-select .setting-item-value-area { margin-top: 1em; } -} -.register-code { - border: 1px solid black; - border-radius: 3px; - padding: 0.2em; + .register-code-setting-item { + flex-direction: column; + } + + .register-code-setting-item .register-code { + margin-top: 1em; + } } \ No newline at end of file diff --git a/FrontEnd/src/pages/setting/index.tsx b/FrontEnd/src/pages/setting/index.tsx index 5d6dcbc0..2599f2f5 100644 --- a/FrontEnd/src/pages/setting/index.tsx +++ b/FrontEnd/src/pages/setting/index.tsx @@ -158,6 +158,7 @@ function RegisterCodeSettingItem() { setDialogOpen(true)} > {registerCode === undefined ? ( -- cgit v1.2.3 From ae1b296b5e967d1e329f5a1e6165ca0f05dce0cb Mon Sep 17 00:00:00 2001 From: crupest Date: Fri, 21 Jul 2023 17:25:01 +0800 Subject: ... --- FrontEnd/src/pages/setting/index.css | 1 - FrontEnd/src/views/common/Card.css | 4 ---- FrontEnd/src/views/common/dialog/Dialog.css | 2 +- FrontEnd/src/views/common/dialog/Dialog.tsx | 20 +++++++++++++++----- 4 files changed, 16 insertions(+), 11 deletions(-) (limited to 'FrontEnd/src/pages/setting/index.css') diff --git a/FrontEnd/src/pages/setting/index.css b/FrontEnd/src/pages/setting/index.css index 9458d937..d9cba24f 100644 --- a/FrontEnd/src/pages/setting/index.css +++ b/FrontEnd/src/pages/setting/index.css @@ -36,7 +36,6 @@ .setting-item-container:hover { background-color: var(--cru-key-container-1-color); - border-bottom-color: var(--cru-key-container-1-color); } .setting-item-label-sub { diff --git a/FrontEnd/src/views/common/Card.css b/FrontEnd/src/views/common/Card.css index 5b3dbbe9..f4cdc31c 100644 --- a/FrontEnd/src/views/common/Card.css +++ b/FrontEnd/src/views/common/Card.css @@ -5,7 +5,3 @@ border-color: var(--cru-key-container-color); transition: all 0.3s; } - -.cru-card:hover { - border-color: var(--cru-key-1-color); -} \ No newline at end of file diff --git a/FrontEnd/src/views/common/dialog/Dialog.css b/FrontEnd/src/views/common/dialog/Dialog.css index 108bd823..99e1a516 100644 --- a/FrontEnd/src/views/common/dialog/Dialog.css +++ b/FrontEnd/src/views/common/dialog/Dialog.css @@ -27,7 +27,7 @@ margin: auto; - border: var(--cru-primary-color) 1px solid; + border: var(--cru-key-container-color) 1px solid; border-radius: 5px; padding: 1.5em; background-color: var(--cru-surface-color); diff --git a/FrontEnd/src/views/common/dialog/Dialog.tsx b/FrontEnd/src/views/common/dialog/Dialog.tsx index 79a31954..31dd113b 100644 --- a/FrontEnd/src/views/common/dialog/Dialog.tsx +++ b/FrontEnd/src/views/common/dialog/Dialog.tsx @@ -1,6 +1,9 @@ import { ReactNode } from "react"; import ReactDOM from "react-dom"; import { CSSTransition } from "react-transition-group"; +import classNames from "classnames"; + +import { ThemeColor } from "../common"; import "./Dialog.css"; @@ -11,14 +14,21 @@ if (optionalPortalElement == null) { const portalElement = optionalPortalElement; interface DialogProps { - onClose: () => void; open: boolean; + onClose: () => void; + color?: ThemeColor; children?: ReactNode; disableCloseOnClickOnOverlay?: boolean; } -export default function Dialog(props: DialogProps) { - const { open, onClose, children, disableCloseOnClickOnOverlay } = props; +export default function Dialog({ + open, + onClose, + color, + children, + disableCloseOnClickOnOverlay, +}: DialogProps) { + color = color ?? "primary"; return ReactDOM.createPortal(
    -
    +
    e.stopPropagation()} -- cgit v1.2.3 From 93bc2b9688ebc0dde2ae8d5cf3e3f2628d636ff0 Mon Sep 17 00:00:00 2001 From: crupest Date: Tue, 15 Aug 2023 01:16:37 +0800 Subject: ... --- FrontEnd/src/pages/setting/index.css | 26 ++++++----- FrontEnd/src/pages/setting/index.tsx | 6 +-- FrontEnd/src/pages/timeline/Timeline.css | 2 - FrontEnd/src/pages/timeline/Timeline.tsx | 4 +- FrontEnd/src/pages/timeline/TimelineCard.tsx | 2 +- FrontEnd/src/pages/timeline/TimelinePostCard.css | 3 +- FrontEnd/src/pages/timeline/TimelinePostCard.tsx | 2 +- FrontEnd/src/pages/timeline/index.tsx | 11 +---- FrontEnd/src/views/common/AppBar.css | 8 ++-- FrontEnd/src/views/common/Card.css | 3 +- FrontEnd/src/views/common/Card.tsx | 2 +- FrontEnd/src/views/common/button/Button.css | 3 +- FrontEnd/src/views/common/button/Button.tsx | 2 +- FrontEnd/src/views/common/button/IconButton.tsx | 2 +- FrontEnd/src/views/common/button/LoadingButton.tsx | 2 +- FrontEnd/src/views/common/index.css | 4 +- FrontEnd/src/views/common/theme.css | 50 ++++++++++++++++++++-- 17 files changed, 87 insertions(+), 45 deletions(-) (limited to 'FrontEnd/src/pages/setting/index.css') diff --git a/FrontEnd/src/pages/setting/index.css b/FrontEnd/src/pages/setting/index.css index d9cba24f..c1950f9c 100644 --- a/FrontEnd/src/pages/setting/index.css +++ b/FrontEnd/src/pages/setting/index.css @@ -17,29 +17,39 @@ .setting-section-title { padding: 0 1em; + color: white; } .setting-section-item-area { margin-top: 1em; - border-top: 1px solid var(--cru-key-container-color); + border-top: 1px solid var(--cru-secondary-color); } .setting-item-container { padding: 0.5em 1em; transition: background-color 0.3s; - color: var(--cru-surface-on-color); - background-color: var(--cru-surface-color); - border-bottom: 1px solid var(--cru-key-container-color); + background-color: var(--cru-background-color); + border-bottom: 1px solid var(--cru-secondary-color); display: flex; align-items: center; } .setting-item-container:hover { - background-color: var(--cru-key-container-1-color); + color: white; + background-color: var(--cru-secondary-color); +} + +.setting-item-container.danger { + color: var(--cru-danger-color); +} + +.setting-item-container.danger:hover { + color: white; + background-color: var(--cru-danger-color); } .setting-item-label-sub { - color: var(--cru-secondary-text-color); + color: var(--cru-text-secondary-color); } .setting-item-value-area { @@ -50,10 +60,6 @@ cursor: pointer; } -.setting-item-container.setting-type-button.danger { - color: var(--cru-danger-color); -} - .register-code { background: var(--cru-surface-container-highest-color); border: 1px solid var(--cru-surface-container-highest-color); diff --git a/FrontEnd/src/pages/setting/index.tsx b/FrontEnd/src/pages/setting/index.tsx index 8e8ae488..8673d55a 100644 --- a/FrontEnd/src/pages/setting/index.tsx +++ b/FrontEnd/src/pages/setting/index.tsx @@ -172,7 +172,7 @@ function RegisterCodeSettingItem() { onClick={(event) => { void navigator.clipboard.writeText(registerCode).then(() => { pushAlert({ - type: "success", + type: "create", message: "settings.myRegisterCodeCopied", }); }); @@ -249,7 +249,7 @@ export default function SettingPage() { return ( {user ? ( - + ) : null} - + diff --git a/FrontEnd/src/pages/timeline/Timeline.css b/FrontEnd/src/pages/timeline/Timeline.css index 30ad75c9..419ab9b1 100644 --- a/FrontEnd/src/pages/timeline/Timeline.css +++ b/FrontEnd/src/pages/timeline/Timeline.css @@ -1,5 +1,4 @@ .timeline { - --timeline-background-color: #f3f3f3; --timeline-shadow-color: #00000080; --timeline-post-line-color: #eadd2c; --timeline-post-line-shadow: 2px 1px 10px -1px var(--timeline-shadow-color); @@ -13,7 +12,6 @@ z-index: 0; position: relative; width: 100%; - background-color: var(--timeline-background-color); } @keyframes timeline-line-node { diff --git a/FrontEnd/src/pages/timeline/Timeline.tsx b/FrontEnd/src/pages/timeline/Timeline.tsx index d05336d7..3c9d73bf 100644 --- a/FrontEnd/src/pages/timeline/Timeline.tsx +++ b/FrontEnd/src/pages/timeline/Timeline.tsx @@ -156,7 +156,7 @@ export function Timeline(props: TimelineProps) { return
    Error.
    ; } return ( - <> +
    {timeline && (
    )} - +
    ); } diff --git a/FrontEnd/src/pages/timeline/TimelineCard.tsx b/FrontEnd/src/pages/timeline/TimelineCard.tsx index 04b34ec1..b287c620 100644 --- a/FrontEnd/src/pages/timeline/TimelineCard.tsx +++ b/FrontEnd/src/pages/timeline/TimelineCard.tsx @@ -123,7 +123,7 @@ export default function TimelineCard(props: TimelinePageCardProps) { return ( + {children} ); diff --git a/FrontEnd/src/pages/timeline/index.tsx b/FrontEnd/src/pages/timeline/index.tsx index 1dffdcc1..51cc37f0 100644 --- a/FrontEnd/src/pages/timeline/index.tsx +++ b/FrontEnd/src/pages/timeline/index.tsx @@ -1,11 +1,10 @@ -import * as React from "react"; import { useParams } from "react-router-dom"; import { UiLogicError } from "@/common"; import Timeline from "./Timeline"; -const TimelinePage: React.FC = () => { +export default function TimelinePage() { const { owner, timeline: timelineNameParam } = useParams(); if (owner == null || owner == "") @@ -13,11 +12,5 @@ const TimelinePage: React.FC = () => { const timeline = timelineNameParam || "self"; - return ( -
    - -
    - ); + return ; }; - -export default TimelinePage; diff --git a/FrontEnd/src/views/common/AppBar.css b/FrontEnd/src/views/common/AppBar.css index bd8d0986..2f2d4a1a 100644 --- a/FrontEnd/src/views/common/AppBar.css +++ b/FrontEnd/src/views/common/AppBar.css @@ -28,7 +28,7 @@ .app-bar a { background-color: var(--cru-primary-color); - color: var(--cru-primary-on-color); + color: var(--cru-push-button-text-color); text-decoration: none; display: flex; align-items: center; @@ -37,15 +37,15 @@ } .app-bar a:hover { - background-color: var(--cru-primary-1-color); + background-color: var(--cru-button-primary-hover-color); } .app-bar a:focus { - background-color: var(--cru-primary-1-color); + background-color: var(--cru-button-primary-focus-color); } .app-bar a:active { - background-color: var(--cru-primary-2-color); + background-color: var(--cru-button-primary-active-color); } .app-bar .app-bar-avatar img { diff --git a/FrontEnd/src/views/common/Card.css b/FrontEnd/src/views/common/Card.css index c677abd7..f391abc8 100644 --- a/FrontEnd/src/views/common/Card.css +++ b/FrontEnd/src/views/common/Card.css @@ -1,5 +1,6 @@ .cru-card { border-radius: var(--cru-card-border-radius); - background-color: var(--cru-key-container-color); + border: 1px solid var(--cru-card-border-color); + background-color: var(--cru-card-background-color); transition: all 0.3s; } \ No newline at end of file diff --git a/FrontEnd/src/views/common/Card.tsx b/FrontEnd/src/views/common/Card.tsx index 381e58e7..e1af13a9 100644 --- a/FrontEnd/src/views/common/Card.tsx +++ b/FrontEnd/src/views/common/Card.tsx @@ -19,7 +19,7 @@ export default function Card({ return (
    {children} diff --git a/FrontEnd/src/views/common/button/Button.css b/FrontEnd/src/views/common/button/Button.css index 4e755dba..b5a4e2f5 100644 --- a/FrontEnd/src/views/common/button/Button.css +++ b/FrontEnd/src/views/common/button/Button.css @@ -1,7 +1,7 @@ .cru-button { font-size: 1rem; padding: 0.4em 0.8em; - transition: all 0.5s; + transition: all 0.3s; border-radius: 0.2em; border: 1px solid; cursor: pointer; @@ -39,6 +39,7 @@ .cru-button.outline { color: var(--cru-button-normal-color); border-color: var(--cru-button-normal-color); + background-color: transparent; } .cru-button.outline:hover { diff --git a/FrontEnd/src/views/common/button/Button.tsx b/FrontEnd/src/views/common/button/Button.tsx index 02d00ee5..573055cf 100644 --- a/FrontEnd/src/views/common/button/Button.tsx +++ b/FrontEnd/src/views/common/button/Button.tsx @@ -33,8 +33,8 @@ export default function Button(props: ButtonProps) {
    ); }; + const buttonsMap: Record< + State, + ComponentPropsWithoutRef["buttons"] + > = { + select: [ + { + key: "cancel", + type: "normal", + props: { + outline: true, + color: "secondary", + text: "operationDialog.cancel", + onClick: close, + }, + }, + ], + crop: [ + { + key: "cancel", + type: "normal", + props: { + outline: true, + color: "secondary", + text: "operationDialog.cancel", + onClick: close, + }, + }, + { + key: "previous", + type: "normal", + props: { + outline: true, + color: "secondary", + text: "operationDialog.previousStep", + onClick: onCropPrevious, + }, + }, + { + key: "next", + type: "normal", + props: { + color: "primary", + text: "operationDialog.nextStep", + onClick: onCropNext, + disabled: cropImgElement == null || clip == null || clip.width === 0, + }, + }, + ], + }; + return ( - -

    - {t("settings.dialogChangeAvatar.title")} -

    -
    - {(() => { - if (state === "select") { - return ( - <> -
    + + + {(() => { + if (state === "select") { + return ( +
    - {t("settings.dialogChangeAvatar.prompt.select")} + {c("settings.dialogChangeAvatar.prompt.select")}
    = (props) => { />
    -
    -
    -
    - - ); - } else if (state === "crop") { - if (fileUrl == null) { - throw new UiLogicError(); - } - return ( - <> + ); + } else if (state === "crop") { + if (fileUrl == null) { + throw new UiLogicError(); + } + return (
    = (props) => { />
    - {t("settings.dialogChangeAvatar.prompt.crop")} + {c("settings.dialogChangeAvatar.prompt.crop")}
    -
    -
    -
    - - ); - } else if (state === "processcrop") { - return ( - <> -
    -
    - {t("settings.dialogChangeAvatar.prompt.processingCrop")} + ); + } else if (state === "process-crop") { + return ( + <> +
    +
    + {c("settings.dialogChangeAvatar.prompt.processingCrop")} +
    -
    -
    -
    -
    - - ); - } else if (state === "preview") { - return ( - <> -
    - {createPreviewRow()} -
    - {t("settings.dialogChangeAvatar.prompt.preview")} +
    +
    +
    -
    -
    -
    -
    - - ); - } else if (state === "uploading") { - return ( - <> -
    - {createPreviewRow()} -
    - {t("settings.dialogChangeAvatar.prompt.uploading")} + + ); + } else if (state === "preview") { + return ( + <> +
    + {createPreviewRow()} +
    + {t("settings.dialogChangeAvatar.prompt.preview")} +
    -
    - - ); - } else if (state === "success") { - return ( - <> -
    -
    - {t("operationDialog.success")} +
    +
    +
    -
    -
    -
    -
    - - ); - } else { - return ( - <> -
    - {createPreviewRow()} -
    {trueMessage}
    -
    -
    -
    -
    - - ); - } - })()} + + ); + } else if (state === "uploading") { + return ( + <> +
    + {createPreviewRow()} +
    + {t("settings.dialogChangeAvatar.prompt.uploading")} +
    +
    + + ); + } else if (state === "success") { + return ( + <> +
    +
    + {t("operationDialog.success")} +
    +
    +
    +
    +
    + + ); + } else { + return ( + <> +
    + {createPreviewRow()} +
    {trueMessage}
    +
    +
    +
    +
    + + ); + } + })()} +
    ); -}; - -export default ChangeAvatarDialog; +} diff --git a/FrontEnd/src/pages/setting/index.css b/FrontEnd/src/pages/setting/index.css index c1950f9c..8af65e93 100644 --- a/FrontEnd/src/pages/setting/index.css +++ b/FrontEnd/src/pages/setting/index.css @@ -61,8 +61,8 @@ } .register-code { - background: var(--cru-surface-container-highest-color); - border: 1px solid var(--cru-surface-container-highest-color); + background: var(--cru-text-primary-color); + color: var(--cru-background-color); border-radius: 3px; padding: 0.2em; cursor: pointer; -- cgit v1.2.3 From d6c1c9f2c9eddd7d6e4e91b2a9de71cfd9db6b73 Mon Sep 17 00:00:00 2001 From: crupest Date: Sat, 19 Aug 2023 02:13:26 +0800 Subject: ... --- FrontEnd/src/pages/setting/ChangeAvatarDialog.css | 21 ++ FrontEnd/src/pages/setting/ChangeAvatarDialog.tsx | 334 ++++++++------------- FrontEnd/src/pages/setting/index.css | 10 - FrontEnd/src/pages/setting/index.tsx | 63 ++-- FrontEnd/src/views/common/BlobImage.tsx | 33 +- FrontEnd/src/views/common/ImageCropper.tsx | 30 +- FrontEnd/src/views/common/button/ButtonRowV2.tsx | 143 +++++++++ FrontEnd/src/views/common/button/IconButton.tsx | 1 + FrontEnd/src/views/common/button/index.tsx | 10 +- .../src/views/common/dialog/DialogContainer.tsx | 71 +++-- 10 files changed, 413 insertions(+), 303 deletions(-) create mode 100644 FrontEnd/src/pages/setting/ChangeAvatarDialog.css create mode 100644 FrontEnd/src/views/common/button/ButtonRowV2.tsx (limited to 'FrontEnd/src/pages/setting/index.css') diff --git a/FrontEnd/src/pages/setting/ChangeAvatarDialog.css b/FrontEnd/src/pages/setting/ChangeAvatarDialog.css new file mode 100644 index 00000000..2aa0bb54 --- /dev/null +++ b/FrontEnd/src/pages/setting/ChangeAvatarDialog.css @@ -0,0 +1,21 @@ +.change-avatar-dialog-prompt { + margin: 0.5em 0; +} + +.change-avatar-dialog-prompt.success { + color: var(--cru-create-color); +} + +.change-avatar-dialog-prompt.error { + color: var(--cru-danger-color); +} + +.change-avatar-cropper { + max-height: 400px; +} + +.change-avatar-preview-image { + min-width: 50%; + max-width: 100%; + max-height: 300px; +} \ No newline at end of file diff --git a/FrontEnd/src/pages/setting/ChangeAvatarDialog.tsx b/FrontEnd/src/pages/setting/ChangeAvatarDialog.tsx index 7ac7dcad..f35fc5a7 100644 --- a/FrontEnd/src/pages/setting/ChangeAvatarDialog.tsx +++ b/FrontEnd/src/pages/setting/ChangeAvatarDialog.tsx @@ -1,10 +1,4 @@ -import { - useState, - useEffect, - ChangeEvent, - ComponentPropsWithoutRef, -} from "react"; -import { AxiosError } from "axios"; +import { useState, ChangeEvent, ComponentPropsWithoutRef } from "react"; import { useC, Text, UiLogicError } from "@/common"; @@ -16,11 +10,13 @@ import ImageCropper, { Clip, applyClipToImage, } from "@/views/common/ImageCropper"; -import Button from "@/views/common/button/Button"; -import ButtonRow from "@/views/common/button/ButtonRow"; +import BlobImage from "@/views/common/BlobImage"; +import ButtonRowV2 from "@/views/common/button/ButtonRowV2"; import Dialog from "@/views/common/dialog/Dialog"; import DialogContainer from "@/views/common/dialog/DialogContainer"; +import "./ChangeAvatarDialog.css"; + interface ChangeAvatarDialogProps { open: boolean; onClose: () => void; @@ -34,15 +30,6 @@ export default function ChangeAvatarDialog({ const user = useUser(); - const [file, setFile] = useState(null); - const [fileUrl, setFileUrl] = useState(null); - const [clip, setClip] = useState(null); - const [cropImgElement, setCropImgElement] = useState( - null, - ); - const [resultBlob, setResultBlob] = useState(null); - const [resultUrl, setResultUrl] = useState(null); - type State = | "select" | "crop" @@ -53,46 +40,22 @@ export default function ChangeAvatarDialog({ | "error"; const [state, setState] = useState("select"); + const [file, setFile] = useState(null); + const [clip, setClip] = useState(null); + const [cropImgElement, setCropImgElement] = useState( + null, + ); + const [resultBlob, setResultBlob] = useState(null); const [message, setMessage] = useState( "settings.dialogChangeAvatar.prompt.select", ); - const trueMessage = c(message); - const close = (): void => { - if (!(state === "uploading")) { + if (state !== "uploading") { onClose(); } }; - useEffect(() => { - if (file != null) { - const url = URL.createObjectURL(file); - setClip(null); - setFileUrl(url); - setState("crop"); - return () => { - URL.revokeObjectURL(url); - }; - } else { - setFileUrl(null); - setState("select"); - } - }, [file]); - - useEffect(() => { - if (resultBlob != null) { - const url = URL.createObjectURL(resultBlob); - setResultUrl(url); - setState("preview"); - return () => { - URL.revokeObjectURL(url); - }; - } else { - setResultUrl(null); - } - }, [resultBlob]); - const onSelectFile = (e: ChangeEvent): void => { const files = e.target.files; if (files == null || files.length === 0) { @@ -113,7 +76,9 @@ export default function ChangeAvatarDialog({ } setState("process-crop"); + void applyClipToImage(cropImgElement, clip, file.type).then((b) => { + setState("preview"); setResultBlob(b); }); }; @@ -124,7 +89,6 @@ export default function ChangeAvatarDialog({ }; const onPreviewPrevious = () => { - setResultBlob(null); setState("crop"); }; @@ -144,77 +108,80 @@ export default function ChangeAvatarDialog({ () => { setState("success"); }, - (e: unknown) => { + () => { setState("error"); - setMessage({ type: "custom", value: (e as AxiosError).message }); + setMessage("operationDialog.error"); }, ); }; - const createPreviewRow = (): React.ReactElement => { - if (resultUrl == null) { - throw new UiLogicError(); - } - return ( -
    -
    - {c("settings.dialogChangeAvatar.previewImgAlt") -
    -
    - ); - }; + const cancelButton = { + key: "cancel", + action: "secondary", + text: "operationDialog.cancel", + onClick: close, + } as const; + + const createPreviousButton = (onClick: () => void) => + ({ + key: "previous", + action: "secondary", + text: "operationDialog.previousStep", + onClick, + }) as const; const buttonsMap: Record< State, - ComponentPropsWithoutRef["buttons"] + ComponentPropsWithoutRef["buttons"] > = { select: [ + cancelButton, { - key: "cancel", - type: "normal", - props: { - outline: true, - color: "secondary", - text: "operationDialog.cancel", - onClick: close, - }, + key: "next", + action: "primary", + text: "operationDialog.nextStep", + onClick: () => setState("crop"), + disabled: file == null, }, ], crop: [ + cancelButton, + createPreviousButton(onCropPrevious), { - key: "cancel", - type: "normal", - props: { - outline: true, - color: "secondary", - text: "operationDialog.cancel", - onClick: close, - }, + key: "next", + action: "primary", + text: "operationDialog.nextStep", + onClick: onCropNext, + disabled: cropImgElement == null || clip == null || clip.width === 0, }, + ], + "process-crop": [cancelButton, createPreviousButton(onPreviewPrevious)], + preview: [ + cancelButton, + createPreviousButton(onPreviewPrevious), { - key: "previous", - type: "normal", - props: { - outline: true, - color: "secondary", - text: "operationDialog.previousStep", - onClick: onCropPrevious, - }, + key: "upload", + action: "primary", + text: "settings.dialogChangeAvatar.upload", + onClick: upload, }, + ], + uploading: [], + success: [ { - key: "next", - type: "normal", - props: { - color: "primary", - text: "operationDialog.nextStep", - onClick: onCropNext, - disabled: cropImgElement == null || clip == null || clip.width === 0, - }, + key: "ok", + text: "operationDialog.ok", + color: "create", + onClick: close, + }, + ], + error: [ + cancelButton, + { + key: "retry", + action: "primary", + text: "operationDialog.retry", + onClick: upload, }, ], }; @@ -224,150 +191,95 @@ export default function ChangeAvatarDialog({ {(() => { if (state === "select") { return ( -
    -
    +
    +
    {c("settings.dialogChangeAvatar.prompt.select")}
    -
    - -
    +
    ); } else if (state === "crop") { - if (fileUrl == null) { + if (file == null) { throw new UiLogicError(); } return ( -
    -
    - -
    -
    +
    + +
    {c("settings.dialogChangeAvatar.prompt.crop")}
    ); } else if (state === "process-crop") { return ( - <> -
    -
    - {c("settings.dialogChangeAvatar.prompt.processingCrop")} -
    +
    +
    + {c("settings.dialogChangeAvatar.prompt.processingCrop")}
    -
    -
    -
    - +
    ); } else if (state === "preview") { return ( - <> -
    - {createPreviewRow()} -
    - {t("settings.dialogChangeAvatar.prompt.preview")} -
    -
    -
    -
    -
    + ); +} diff --git a/FrontEnd/src/views/common/button/IconButton.tsx b/FrontEnd/src/views/common/button/IconButton.tsx index 60050e0d..126f4263 100644 --- a/FrontEnd/src/views/common/button/IconButton.tsx +++ b/FrontEnd/src/views/common/button/IconButton.tsx @@ -9,6 +9,7 @@ interface IconButtonProps extends ComponentPropsWithoutRef<"i"> { icon: string; color?: ThemeColor; large?: boolean; + disabled?: boolean; // TODO: Not implemented } export default function IconButton(props: IconButtonProps) { diff --git a/FrontEnd/src/views/common/button/index.tsx b/FrontEnd/src/views/common/button/index.tsx index 73038849..b5aa5470 100644 --- a/FrontEnd/src/views/common/button/index.tsx +++ b/FrontEnd/src/views/common/button/index.tsx @@ -3,5 +3,13 @@ import FlatButton from "./FlatButton"; import IconButton from "./IconButton"; import LoadingButton from "./LoadingButton"; import ButtonRow from "./ButtonRow"; +import ButtonRowV2 from "./ButtonRowV2"; -export { Button, FlatButton, IconButton, LoadingButton, ButtonRow }; +export { + Button, + FlatButton, + IconButton, + LoadingButton, + ButtonRow, + ButtonRowV2, +}; diff --git a/FrontEnd/src/views/common/dialog/DialogContainer.tsx b/FrontEnd/src/views/common/dialog/DialogContainer.tsx index b0a87ea5..afee2669 100644 --- a/FrontEnd/src/views/common/dialog/DialogContainer.tsx +++ b/FrontEnd/src/views/common/dialog/DialogContainer.tsx @@ -2,11 +2,11 @@ import { ComponentProps, Ref, ReactNode } from "react"; import classNames from "classnames"; import { ThemeColor, Text, useC } from "../common"; -import { ButtonRow } from "../button"; +import { ButtonRow, ButtonRowV2 } from "../button"; import "./DialogContainer.css"; -interface DialogContainerProps { +interface DialogContainerBaseProps { className?: string; title: Text; titleColor?: ThemeColor; @@ -14,25 +14,37 @@ interface DialogContainerProps { titleRef?: Ref; bodyContainerClassName?: string; bodyContainerRef?: Ref; - buttons: ComponentProps["buttons"]; buttonsClassName?: string; buttonsContainerRef?: ComponentProps["containerRef"]; children: ReactNode; } -export default function DialogContainer({ - className, - title, - titleColor, - titleClassName, - titleRef, - bodyContainerClassName, - bodyContainerRef, - buttons, - buttonsClassName, - buttonsContainerRef, - children, -}: DialogContainerProps) { +interface DialogContainerWithButtonsProps extends DialogContainerBaseProps { + buttons: ComponentProps["buttons"]; +} + +interface DialogContainerWithButtonsV2Props extends DialogContainerBaseProps { + buttonsV2: ComponentProps["buttons"]; +} + +type DialogContainerProps = + | DialogContainerWithButtonsProps + | DialogContainerWithButtonsV2Props; + +export default function DialogContainer(props: DialogContainerProps) { + const { + className, + title, + titleColor, + titleClassName, + titleRef, + bodyContainerClassName, + bodyContainerRef, + buttonsClassName, + buttonsContainerRef, + children, + } = props; + const c = useC(); return ( @@ -57,12 +69,27 @@ export default function DialogContainer({ {children}

    - + {"buttons" in props ? ( + + ) : ( + + )}
    ); } -- cgit v1.2.3 From 1f90dd29a2e1a11cf16857513f14bce3df68c1e1 Mon Sep 17 00:00:00 2001 From: crupest Date: Sat, 26 Aug 2023 16:28:39 +0800 Subject: ... --- FrontEnd/src/pages/setting/index.css | 25 +++-- FrontEnd/src/pages/setting/index.tsx | 9 +- FrontEnd/src/pages/timeline/CollapseButton.tsx | 18 ++-- FrontEnd/src/pages/timeline/TimelineCard.tsx | 1 + .../src/pages/timeline/TimelinePostCreateView.css | 4 +- FrontEnd/src/pages/timeline/TimelinePostView.tsx | 1 + FrontEnd/src/views/common/AppBar.css | 11 +- FrontEnd/src/views/common/AppBar.tsx | 9 +- FrontEnd/src/views/common/Card.css | 16 ++- FrontEnd/src/views/common/Card.tsx | 9 +- FrontEnd/src/views/common/button/Button.css | 38 +++---- FrontEnd/src/views/common/button/Button.tsx | 2 +- FrontEnd/src/views/common/button/FlatButton.css | 12 +-- FrontEnd/src/views/common/button/FlatButton.tsx | 2 +- FrontEnd/src/views/common/button/IconButton.css | 10 +- FrontEnd/src/views/common/button/IconButton.tsx | 4 +- FrontEnd/src/views/common/button/LoadingButton.css | 6 +- FrontEnd/src/views/common/button/LoadingButton.tsx | 2 +- FrontEnd/src/views/common/list/ListContainer.css | 2 +- .../src/views/common/list/ListItemContainer.css | 2 +- FrontEnd/src/views/common/theme.css | 113 +++++++++++---------- 21 files changed, 161 insertions(+), 135 deletions(-) (limited to 'FrontEnd/src/pages/setting/index.css') diff --git a/FrontEnd/src/pages/setting/index.css b/FrontEnd/src/pages/setting/index.css index 86ccf706..a8a44524 100644 --- a/FrontEnd/src/pages/setting/index.css +++ b/FrontEnd/src/pages/setting/index.css @@ -1,5 +1,3 @@ -/* TODO: Make item prettier. */ - .setting-section { padding: 1em 0; margin: 1em 0; @@ -7,35 +5,36 @@ .setting-section-title { padding: 0 1em; - color: white; } .setting-section-item-area { margin-top: 1em; - border-top: 1px solid var(--cru-secondary-color); + border-top: 1px solid var(--cru-primary-color); } .setting-item-container { padding: 0.5em 1em; transition: background-color 0.3s; - background-color: var(--cru-background-color); - border-bottom: 1px solid var(--cru-secondary-color); + background-color: var(--cru-clickable-grayscale-normal-color); + border-bottom: 1px solid var(--cru-clickable-grayscale-active-color); display: flex; align-items: center; } .setting-item-container:hover { - color: white; - background-color: var(--cru-secondary-color); + background-color: var(--cru-clickable-grayscale-hover-color); } -.setting-item-container.danger { - color: var(--cru-danger-color); +.setting-item-container:focus { + background-color: var(--cru-clickable-grayscale-focus-color); } -.setting-item-container.danger:hover { - color: white; - background-color: var(--cru-danger-color); +.setting-item-container:active { + background-color: var(--cru-clickable-grayscale-active-color); +} + +.setting-item-container.danger { + color: var(--cru-danger-color); } .setting-item-label-sub { diff --git a/FrontEnd/src/pages/setting/index.tsx b/FrontEnd/src/pages/setting/index.tsx index 4e0bf27e..50967a3c 100644 --- a/FrontEnd/src/pages/setting/index.tsx +++ b/FrontEnd/src/pages/setting/index.tsx @@ -247,9 +247,9 @@ export default function SettingPage() { ]); return ( - + {user ? ( - + ) : null} - + diff --git a/FrontEnd/src/pages/timeline/CollapseButton.tsx b/FrontEnd/src/pages/timeline/CollapseButton.tsx index 8270e160..14fc6bee 100644 --- a/FrontEnd/src/pages/timeline/CollapseButton.tsx +++ b/FrontEnd/src/pages/timeline/CollapseButton.tsx @@ -1,21 +1,25 @@ -import * as React from "react"; +import { CSSProperties } from "react"; import IconButton from "@/views/common/button/IconButton"; -const CollapseButton: React.FC<{ +export default function CollapseButton({ + collapse, + onClick, + className, + style, +}: { collapse: boolean; onClick: () => void; className?: string; - style?: React.CSSProperties; -}> = ({ collapse, onClick, className, style }) => { + style?: CSSProperties; +}) { return ( ); -}; - -export default CollapseButton; +} diff --git a/FrontEnd/src/pages/timeline/TimelineCard.tsx b/FrontEnd/src/pages/timeline/TimelineCard.tsx index 8557e5dd..ed34b4ba 100644 --- a/FrontEnd/src/pages/timeline/TimelineCard.tsx +++ b/FrontEnd/src/pages/timeline/TimelineCard.tsx @@ -112,6 +112,7 @@ export default function TimelineCard(props: TimelinePageCardProps) { containerClassName="d-inline" > diff --git a/FrontEnd/src/pages/timeline/TimelinePostCreateView.css b/FrontEnd/src/pages/timeline/TimelinePostCreateView.css index 2a433860..5986e566 100644 --- a/FrontEnd/src/pages/timeline/TimelinePostCreateView.css +++ b/FrontEnd/src/pages/timeline/TimelinePostCreateView.css @@ -24,11 +24,11 @@ } .timeline-post-create-edit-text:hover { - border-color: var(--cru-button-secondary-normal-color) + border-color: var(--cru-clickable-secondary-normal-color) } .timeline-post-create-edit-text:focus { - border-color: var(--cru-button-secondary-normal-color) + border-color: var(--cru-clickable-secondary-normal-color) } .timeline-post-create-image { diff --git a/FrontEnd/src/pages/timeline/TimelinePostView.tsx b/FrontEnd/src/pages/timeline/TimelinePostView.tsx index 07f2e0f0..afae5033 100644 --- a/FrontEnd/src/pages/timeline/TimelinePostView.tsx +++ b/FrontEnd/src/pages/timeline/TimelinePostView.tsx @@ -47,6 +47,7 @@ export default function TimelinePostView(props: TimelinePostViewProps) { {post.editable && ( { diff --git a/FrontEnd/src/views/common/AppBar.css b/FrontEnd/src/views/common/AppBar.css index 2f2d4a1a..a0d975b5 100644 --- a/FrontEnd/src/views/common/AppBar.css +++ b/FrontEnd/src/views/common/AppBar.css @@ -37,15 +37,20 @@ } .app-bar a:hover { - background-color: var(--cru-button-primary-hover-color); + background-color: var(--cru-clickable-primary-hover-color); } .app-bar a:focus { - background-color: var(--cru-button-primary-focus-color); + background-color: var(--cru-clickable-primary-focus-color); } .app-bar a:active { - background-color: var(--cru-button-primary-active-color); + background-color: var(--cru-clickable-primary-active-color); +} + +/* the current page */ +.app-bar a.active { + background-color: var(--cru-clickable-primary-focus-color); } .app-bar .app-bar-avatar img { diff --git a/FrontEnd/src/views/common/AppBar.tsx b/FrontEnd/src/views/common/AppBar.tsx index dacd608a..b9ea825b 100644 --- a/FrontEnd/src/views/common/AppBar.tsx +++ b/FrontEnd/src/views/common/AppBar.tsx @@ -59,7 +59,7 @@ export default function AppBar() { isCollapse && "collapse", )} > - + Timeline @@ -91,12 +91,7 @@ export default function AppBar() {
    {isMobile && ( - + )} ); diff --git a/FrontEnd/src/views/common/Card.css b/FrontEnd/src/views/common/Card.css index 301910c6..6d655eb9 100644 --- a/FrontEnd/src/views/common/Card.css +++ b/FrontEnd/src/views/common/Card.css @@ -1,10 +1,20 @@ .cru-card { border-radius: var(--cru-card-border-radius); - border: 2px solid var(--cru-card-border-color); - background-color: var(--cru-card-background-color); transition: all 0.3s; } -.cru-card-no-background { +.cru-card-background-none { + background-color: transparent; +} + +.cru-card-background-solid { background-color: var(--cru-background-color); } + +.cru-card-background-grayscale { + background-color: var(--cru-container-background-color); +} + +.cru-card-border-color { + border: 2px solid var(--cru-card-border-color); +} diff --git a/FrontEnd/src/views/common/Card.tsx b/FrontEnd/src/views/common/Card.tsx index fb29f728..a8f0d3cc 100644 --- a/FrontEnd/src/views/common/Card.tsx +++ b/FrontEnd/src/views/common/Card.tsx @@ -7,12 +7,14 @@ import "./Card.css"; interface CardProps extends ComponentPropsWithoutRef<"div"> { containerRef?: Ref; color?: ThemeColor; - noBackground?: boolean; + border?: "color" | "none"; + background?: "color" | "solid" | "grayscale" | "none"; } export default function Card({ color, - noBackground, + background, + border, className, children, containerRef, @@ -24,7 +26,8 @@ export default function Card({ className={classNames( "cru-card", `cru-card-${color ?? "primary"}`, - noBackground && "cru-card-no-background", + `cru-card-border-${border ?? "color"}`, + `cru-card-background-${background ?? "solid"}`, className, )} {...otherProps} diff --git a/FrontEnd/src/views/common/button/Button.css b/FrontEnd/src/views/common/button/Button.css index c6b180c4..1da70f0e 100644 --- a/FrontEnd/src/views/common/button/Button.css +++ b/FrontEnd/src/views/common/button/Button.css @@ -9,23 +9,23 @@ .cru-button:not(.outline) { color: var(--cru-push-button-text-color); - background-color: var(--cru-button-normal-color); - border-color: var(--cru-button-normal-color); + background-color: var(--cru-clickable-normal-color); + border-color: var(--cru-clickable-normal-color); } .cru-button:not(.outline):hover { - background-color: var(--cru-button-hover-color); - border-color: var(--cru-button-hover-color); + background-color: var(--cru-clickable-hover-color); + border-color: var(--cru-clickable-hover-color); } .cru-button:not(.outline):focus { - background-color: var(--cru-button-focus-color); - border-color: var(--cru-button-focus-color); + background-color: var(--cru-clickable-focus-color); + border-color: var(--cru-clickable-focus-color); } .cru-button:not(.outline):active { - background-color: var(--cru-button-active-color); - border-color: var(--cru-button-active-color); + background-color: var(--cru-clickable-active-color); + border-color: var(--cru-clickable-active-color); } .cru-button:not(.outline):disabled { @@ -37,28 +37,28 @@ .cru-button.outline { - color: var(--cru-button-normal-color); - border-color: var(--cru-button-normal-color); + color: var(--cru-clickable-normal-color); + border-color: var(--cru-clickable-normal-color); background-color: transparent; } .cru-button.outline:hover { - color: var(--cru-button-hover-color); - border-color: var(--cru-button-hover-color); + color: var(--cru-clickable-hover-color); + border-color: var(--cru-clickable-hover-color); } .cru-button.outline:focus { - color: var(--cru-button-focus-color); - border-color: var(--cru-button-focus-color); + color: var(--cru-clickable-focus-color); + border-color: var(--cru-clickable-focus-color); } .cru-button.outline:active { - color: var(--cru-button-active-color); - border-color: var(--cru-button-active-color); + color: var(--cru-clickable-active-color); + border-color: var(--cru-clickable-active-color); } .cru-button.outline:disabled { - color: var(--cru-button-disabled-color); - border-color: var(--cru-button-disabled-color); + color: var(--cru-clickable-disabled-color); + border-color: var(--cru-clickable-disabled-color); cursor: auto; -} \ No newline at end of file +} diff --git a/FrontEnd/src/views/common/button/Button.tsx b/FrontEnd/src/views/common/button/Button.tsx index 573055cf..6c38e130 100644 --- a/FrontEnd/src/views/common/button/Button.tsx +++ b/FrontEnd/src/views/common/button/Button.tsx @@ -34,7 +34,7 @@ export default function Button(props: ButtonProps) { ref={buttonRef} className={classNames( "cru-button", - `cru-button-${color ?? "primary"}`, + `cru-clickable-${color ?? "primary"}`, outline && "outline", className, )} diff --git a/FrontEnd/src/views/common/button/FlatButton.css b/FrontEnd/src/views/common/button/FlatButton.css index 7151f6de..2050946c 100644 --- a/FrontEnd/src/views/common/button/FlatButton.css +++ b/FrontEnd/src/views/common/button/FlatButton.css @@ -3,25 +3,25 @@ padding: 0.4em 0.8em; transition: all 0.5s; border-radius: 0.2em; - background-color: var(--cru-flat-button-background-normal-color); + background-color: var(--cru-clickable-grayscale-normal-color); border: 1px none; - color: var(--cru-button-normal-color); + color: var(--cru-clickable-normal-color); cursor: pointer; } .cru-flat-button:hover { - background-color: var(--cru-flat-button-background-hover-color); + background-color: var(--cru-clickable-grayscale-hover-color); } .cru-flat-button:focus { - background-color: var(--cru-flat-button-background-focus-color); + background-color: var(--cru-clickable-grayscale-focus-color); } .cru-flat-button:active { - background-color: var(--cru-flat-button-background-active-color); + background-color: var(--cru-clickable-grayscale-active-color); } .cru-flat-button:disabled { - color: var(--cru-button-disabled-color); + color: var(--cru-clickable-disabled-color); cursor: auto; } \ No newline at end of file diff --git a/FrontEnd/src/views/common/button/FlatButton.tsx b/FrontEnd/src/views/common/button/FlatButton.tsx index 20ca7432..9f074dd6 100644 --- a/FrontEnd/src/views/common/button/FlatButton.tsx +++ b/FrontEnd/src/views/common/button/FlatButton.tsx @@ -24,8 +24,8 @@ export default function FlatButton(props: FlatButtonProps) {