mirror of
https://github.com/usememos/memos.git
synced 2024-12-01 23:02:22 +03:00
feat: dark mode support for auth page (#569)
* feat: dark mode support for auth page * chore: update
This commit is contained in:
parent
2d5d734da4
commit
90c85103c3
53
web/src/components/ApperanceDropdownMenu.tsx
Normal file
53
web/src/components/ApperanceDropdownMenu.tsx
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import { Option, Select } from "@mui/joy";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
import Icon from "./Icon";
|
||||||
|
import { APPERANCE_OPTIONS } from "../helpers/consts";
|
||||||
|
import useApperance, { Apperance } from "../hooks/useApperance";
|
||||||
|
|
||||||
|
const ApperanceDropdownMenu = () => {
|
||||||
|
const [apperance, setApperance] = useApperance();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const apperanceOptionItems = [
|
||||||
|
[
|
||||||
|
APPERANCE_OPTIONS[0],
|
||||||
|
<>
|
||||||
|
<Icon.Feather className="w-4 h-4" />
|
||||||
|
<p>{t("setting.apperance-option.follow-system")}</p>
|
||||||
|
</>,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
APPERANCE_OPTIONS[1],
|
||||||
|
<>
|
||||||
|
<Icon.Sun className="w-4 h-4" />
|
||||||
|
<p>{t("setting.apperance-option.always-light")}</p>
|
||||||
|
</>,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
APPERANCE_OPTIONS[2],
|
||||||
|
<>
|
||||||
|
<Icon.Moon className="w-4 h-4" />
|
||||||
|
<p>{t("setting.apperance-option.always-dark")}</p>
|
||||||
|
</>,
|
||||||
|
],
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Select
|
||||||
|
className="w-56 text-sm"
|
||||||
|
value={apperance}
|
||||||
|
onChange={(_, value) => {
|
||||||
|
setApperance(value as Apperance);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{apperanceOptionItems.map((item) => (
|
||||||
|
<Option key={item[0]} value={item[0]}>
|
||||||
|
<span className="flex items-center gap-2">{item[1]}</span>
|
||||||
|
</Option>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ApperanceDropdownMenu;
|
@ -22,3 +22,6 @@ export const IS_FOLDING_ENABLED_DEFAULT_VALUE = true;
|
|||||||
export const SETTING_IS_FOLDING_ENABLED_KEY = "setting_IS_FOLDING_ENABLED";
|
export const SETTING_IS_FOLDING_ENABLED_KEY = "setting_IS_FOLDING_ENABLED";
|
||||||
|
|
||||||
export const TAB_SPACE_WIDTH = 2;
|
export const TAB_SPACE_WIDTH = 2;
|
||||||
|
|
||||||
|
export const APPERANCE_OPTIONS = ["auto", "light", "dark"] as const;
|
||||||
|
export const APPERANCE_OPTIONS_STORAGE_KEY = "setting_APPERANCE_OPTIONS";
|
||||||
|
28
web/src/hooks/useApperance.ts
Normal file
28
web/src/hooks/useApperance.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { useEffect } from "react";
|
||||||
|
import { useColorScheme } from "@mui/joy/styles";
|
||||||
|
|
||||||
|
import { APPERANCE_OPTIONS, APPERANCE_OPTIONS_STORAGE_KEY } from "../helpers/consts";
|
||||||
|
import useLocalStorage from "./useLocalStorage";
|
||||||
|
|
||||||
|
export type Apperance = typeof APPERANCE_OPTIONS[number];
|
||||||
|
|
||||||
|
const useApperance = () => {
|
||||||
|
const [apperance, setApperance] = useLocalStorage<Apperance>(APPERANCE_OPTIONS_STORAGE_KEY, APPERANCE_OPTIONS[0]);
|
||||||
|
|
||||||
|
const { setMode } = useColorScheme();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const root = document.documentElement;
|
||||||
|
if (apperance === "dark" || (apperance === "auto" && window.matchMedia("(prefers-color-scheme: dark)").matches)) {
|
||||||
|
root.classList.add("dark");
|
||||||
|
setMode("dark");
|
||||||
|
} else {
|
||||||
|
root.classList.remove("dark");
|
||||||
|
setMode("light");
|
||||||
|
}
|
||||||
|
}, [apperance]);
|
||||||
|
|
||||||
|
return [apperance, setApperance] as const;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useApperance;
|
@ -1,5 +1,5 @@
|
|||||||
.page-wrapper.auth {
|
.page-wrapper.auth {
|
||||||
@apply flex flex-row justify-center items-center w-full h-screen bg-white;
|
@apply flex flex-row justify-center items-center w-full h-screen bg-white dark:bg-zinc-900;
|
||||||
|
|
||||||
> .page-container {
|
> .page-container {
|
||||||
@apply w-80 max-w-full h-full py-4 flex flex-col justify-start items-center;
|
@apply w-80 max-w-full h-full py-4 flex flex-col justify-start items-center;
|
||||||
@ -11,15 +11,19 @@
|
|||||||
@apply flex flex-col justify-start items-start w-full mb-4;
|
@apply flex flex-col justify-start items-start w-full mb-4;
|
||||||
|
|
||||||
> .title-container {
|
> .title-container {
|
||||||
@apply w-full flex flex-row justify-between items-center;
|
@apply w-full flex flex-row justify-start items-center;
|
||||||
|
|
||||||
> .logo-img {
|
> .logo-img {
|
||||||
@apply h-20 w-auto;
|
@apply h-20 w-auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> .logo-text {
|
||||||
|
@apply text-4xl tracking-wide text-black dark:text-white;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .slogan-text {
|
> .slogan-text {
|
||||||
@apply text-sm text-gray-700;
|
@apply text-sm text-gray-700 dark:text-gray-200;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,7 +37,7 @@
|
|||||||
@apply absolute top-3 left-3 px-1 leading-10 flex-shrink-0 text-base cursor-text text-gray-400 bg-transparent transition-all select-none;
|
@apply absolute top-3 left-3 px-1 leading-10 flex-shrink-0 text-base cursor-text text-gray-400 bg-transparent transition-all select-none;
|
||||||
|
|
||||||
&.not-null {
|
&.not-null {
|
||||||
@apply text-sm top-0 z-10 leading-4 bg-white rounded;
|
@apply text-sm top-0 z-10 leading-4 bg-white dark:bg-zinc-800 rounded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +45,7 @@
|
|||||||
@apply py-2;
|
@apply py-2;
|
||||||
|
|
||||||
> input {
|
> input {
|
||||||
@apply w-full py-3 px-3 text-base shadow-inner rounded-lg border border-solid border-gray-400 hover:opacity-80;
|
@apply w-full py-3 px-3 text-base shadow-inner rounded-lg border border-solid border-gray-400 hover:opacity-80 dark:bg-zinc-800 dark:text-white;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -58,7 +62,7 @@
|
|||||||
@apply flex flex-row justify-center items-center px-1 py-2 text-sm rounded hover:opacity-80;
|
@apply flex flex-row justify-center items-center px-1 py-2 text-sm rounded hover:opacity-80;
|
||||||
|
|
||||||
&.signup-btn {
|
&.signup-btn {
|
||||||
@apply px-3;
|
@apply px-3 dark:text-white dark:opacity-70;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.signin-btn {
|
&.signin-btn {
|
||||||
|
@ -160,6 +160,11 @@
|
|||||||
"additional-script": "Additional script",
|
"additional-script": "Additional script",
|
||||||
"additional-style-placeholder": "Additional CSS codes",
|
"additional-style-placeholder": "Additional CSS codes",
|
||||||
"additional-script-placeholder": "Additional JavaScript codes"
|
"additional-script-placeholder": "Additional JavaScript codes"
|
||||||
|
},
|
||||||
|
"apperance-option": {
|
||||||
|
"follow-system": "Follow system",
|
||||||
|
"always-light": "Always light",
|
||||||
|
"always-dark": "Always dark"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"amount-text": {
|
"amount-text": {
|
||||||
|
@ -160,6 +160,11 @@
|
|||||||
"additional-script": "自定义脚本",
|
"additional-script": "自定义脚本",
|
||||||
"additional-style-placeholder": "自定义 CSS 代码",
|
"additional-style-placeholder": "自定义 CSS 代码",
|
||||||
"additional-script-placeholder": "自定义 JavaScript 代码"
|
"additional-script-placeholder": "自定义 JavaScript 代码"
|
||||||
|
},
|
||||||
|
"apperance-option": {
|
||||||
|
"follow-system": "跟随系统",
|
||||||
|
"always-light": "总是浅色",
|
||||||
|
"always-dark": "总是深色"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"amount-text": {
|
"amount-text": {
|
||||||
|
@ -9,6 +9,7 @@ import useLoading from "../hooks/useLoading";
|
|||||||
import { globalService, userService } from "../services";
|
import { globalService, userService } from "../services";
|
||||||
import Icon from "../components/Icon";
|
import Icon from "../components/Icon";
|
||||||
import toastHelper from "../components/Toast";
|
import toastHelper from "../components/Toast";
|
||||||
|
import ApperanceDropdownMenu from "../components/ApperanceDropdownMenu";
|
||||||
import "../less/auth.less";
|
import "../less/auth.less";
|
||||||
|
|
||||||
const validateConfig: ValidatorConfig = {
|
const validateConfig: ValidatorConfig = {
|
||||||
@ -113,7 +114,8 @@ const Auth = () => {
|
|||||||
<div className="auth-form-wrapper">
|
<div className="auth-form-wrapper">
|
||||||
<div className="page-header-container">
|
<div className="page-header-container">
|
||||||
<div className="title-container">
|
<div className="title-container">
|
||||||
<img className="logo-img" src="/logo-full.webp" alt="" />
|
<img className="logo-img" src="/logo.webp" alt="" />
|
||||||
|
<p className="logo-text">memos</p>
|
||||||
</div>
|
</div>
|
||||||
<p className="slogan-text">{t("slogan")}</p>
|
<p className="slogan-text">{t("slogan")}</p>
|
||||||
</div>
|
</div>
|
||||||
@ -160,7 +162,7 @@ const Auth = () => {
|
|||||||
{!systemStatus?.host && <p className="tip-text">{t("auth.host-tip")}</p>}
|
{!systemStatus?.host && <p className="tip-text">{t("auth.host-tip")}</p>}
|
||||||
</div>
|
</div>
|
||||||
<div className="footer-container">
|
<div className="footer-container">
|
||||||
<div className="w-full flex flex-row justify-center items-center">
|
<div className="w-full flex flex-row justify-center items-center gap-2">
|
||||||
<Select
|
<Select
|
||||||
className="w-40 text-sm"
|
className="w-40 text-sm"
|
||||||
startDecorator={<Icon.Globe className="w-4 h-auto" />}
|
startDecorator={<Icon.Globe className="w-4 h-auto" />}
|
||||||
@ -172,6 +174,7 @@ const Auth = () => {
|
|||||||
<Option value="vi">Tiếng Việt</Option>
|
<Option value="vi">Tiếng Việt</Option>
|
||||||
<Option value="fr">French</Option>
|
<Option value="fr">French</Option>
|
||||||
</Select>
|
</Select>
|
||||||
|
<ApperanceDropdownMenu />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
/* eslint-disable no-undef */
|
/* eslint-disable no-undef */
|
||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
content: ["./index.html", "./src/**/*.{js,ts,tsx}"],
|
content: ["./index.html", "./src/**/*.{js,ts,tsx}"],
|
||||||
|
darkMode: "class",
|
||||||
theme: {
|
theme: {
|
||||||
fontSize: {
|
fontSize: {
|
||||||
xs: ".75rem",
|
xs: ".75rem",
|
||||||
|
Loading…
Reference in New Issue
Block a user