diff --git a/frontend/extension/src/components/ShortcutView.tsx b/frontend/extension/src/components/ShortcutView.tsx index ac196d0..ecd1372 100644 --- a/frontend/extension/src/components/ShortcutView.tsx +++ b/frontend/extension/src/components/ShortcutView.tsx @@ -22,7 +22,7 @@ const ShortcutView = (props: Props) => { <>
@@ -42,13 +42,13 @@ const ShortcutView = (props: Props) => { onClick={handleShortcutLinkClick} >
- {shortcut.title} + {shortcut.title} {shortcut.title ? ( - (s/{shortcut.name}) + (s/{shortcut.name}) ) : ( <> - s/ - {shortcut.name} + s/ + {shortcut.name} )}
diff --git a/frontend/extension/src/hooks/useColorTheme.ts b/frontend/extension/src/hooks/useColorTheme.ts new file mode 100644 index 0000000..03b1d81 --- /dev/null +++ b/frontend/extension/src/hooks/useColorTheme.ts @@ -0,0 +1,43 @@ +import { useColorScheme } from "@mui/joy"; +import { useEffect } from "react"; + +const useColorTheme = () => { + const { mode: colorTheme, setMode: setColorTheme } = useColorScheme(); + + useEffect(() => { + const root = document.documentElement; + if (colorTheme === "light") { + root.classList.remove("dark"); + } else if (colorTheme === "dark") { + root.classList.add("dark"); + } else { + const darkMediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); + if (darkMediaQuery.matches) { + root.classList.add("dark"); + } else { + root.classList.remove("dark"); + } + + const handleColorSchemeChange = (e: MediaQueryListEvent) => { + if (e.matches) { + root.classList.add("dark"); + } else { + root.classList.remove("dark"); + } + }; + try { + darkMediaQuery.addEventListener("change", handleColorSchemeChange); + } catch (error) { + console.error("failed to initial color scheme listener", error); + } + + return () => { + darkMediaQuery.removeEventListener("change", handleColorSchemeChange); + }; + } + }, [colorTheme]); + + return { colorTheme, setColorTheme }; +}; + +export default useColorTheme; diff --git a/frontend/extension/src/options.tsx b/frontend/extension/src/options.tsx index 3ac4e55..3ed1d56 100644 --- a/frontend/extension/src/options.tsx +++ b/frontend/extension/src/options.tsx @@ -1,5 +1,5 @@ import type { Shortcut } from "@/types/proto/api/v2/shortcut_service"; -import { Button, Divider, Input } from "@mui/joy"; +import { Button, CssVarsProvider, Divider, Input, Select, Option } from "@mui/joy"; import { useStorage } from "@plasmohq/storage/hook"; import { useEffect, useState } from "react"; import { Toaster, toast } from "react-hot-toast"; @@ -7,6 +7,7 @@ import Icon from "./components/Icon"; import Logo from "./components/Logo"; import PullShortcutsButton from "./components/PullShortcutsButton"; import ShortcutsContainer from "./components/ShortcutsContainer"; +import useColorTheme from "./hooks/useColorTheme"; import "./style.css"; interface SettingState { @@ -14,7 +15,23 @@ interface SettingState { accessToken: string; } +const colorThemeOptions = [ + { + value: "system", + label: "System", + }, + { + value: "light", + label: "Light", + }, + { + value: "dark", + label: "Dark", + }, +]; + const IndexOptions = () => { + const { colorTheme, setColorTheme } = useColorTheme(); const [domain, setDomain] = useStorage("domain", (v) => (v ? v : "")); const [accessToken, setAccessToken] = useStorage("access_token", (v) => (v ? v : "")); const [settingState, setSettingState] = useState({ @@ -44,91 +61,119 @@ const IndexOptions = () => { toast.success("Setting saved"); }; + const handleSelectColorTheme = async (colorTheme: string) => { + setColorTheme(colorTheme as any); + }; + return ( - <> -
- +
+ -
-

- - Slash - / - Setting -

+
+

+ + Slash + / + Setting +

-
-
-
- Domain - {domain !== "" && ( - - Go to my Slash - - - )} -
-
- setPartialSettingState({ domain: e.target.value })} - /> -
+
+
+
+ Domain + {domain !== "" && ( + + Go to my Slash + + + )}
- -
- Access Token -
- setPartialSettingState({ accessToken: e.target.value })} - /> -
-
- -
- +
+ setPartialSettingState({ domain: e.target.value })} + />
- {isInitialized && ( - <> - +
+ Access Token +
+ setPartialSettingState({ accessToken: e.target.value })} + /> +
+
-

- Shortcuts - ({shortcuts.length}) - -

- - - )} +
+ +
+ + + +

Preference

+ +
+
+ Color Theme +
+ +
-
- - + {isInitialized && ( + <> + + +

+ Shortcuts + ({shortcuts.length}) + +

+ + + )} +
+
); }; -export default IndexOptions; +const Options = () => { + return ( + + + + + ); +}; + +export default Options; diff --git a/frontend/extension/src/popup.tsx b/frontend/extension/src/popup.tsx index 85f4cf7..67e8109 100644 --- a/frontend/extension/src/popup.tsx +++ b/frontend/extension/src/popup.tsx @@ -1,5 +1,5 @@ import type { Shortcut } from "@/types/proto/api/v2/shortcut_service"; -import { Button, Divider, IconButton } from "@mui/joy"; +import { Button, CssVarsProvider, Divider, IconButton } from "@mui/joy"; import { useStorage } from "@plasmohq/storage/hook"; import { Toaster } from "react-hot-toast"; import CreateShortcutsButton from "@/components/CreateShortcutsButton"; @@ -7,9 +7,11 @@ import Icon from "@/components/Icon"; import Logo from "@/components/Logo"; import PullShortcutsButton from "@/components/PullShortcutsButton"; import ShortcutsContainer from "@/components/ShortcutsContainer"; +import useColorTheme from "./hooks/useColorTheme"; import "./style.css"; const IndexPopup = () => { + useColorTheme(); const [domain] = useStorage("domain", ""); const [accessToken] = useStorage("access_token", ""); const [shortcuts] = useStorage("shortcuts", []); @@ -25,86 +27,84 @@ const IndexPopup = () => { }; return ( - <> -
-
-
- - Slash - {isInitialized && ( - <> - / - Shortcuts - ({shortcuts.length}) - - - )} -
-
{isInitialized && }
-
- -
- {isInitialized ? ( +
+
+
+ + Slash + {isInitialized && ( <> - {shortcuts.length !== 0 ? ( - - ) : ( -
-

No shortcut found.

-
- )} - - - -
-
- - - - - - -
- -
+ / + Shortcuts + ({shortcuts.length}) + - ) : ( -
- -

Please set your domain and access token first.

-
- - Or - -
-
)}
+
{isInitialized && }
- - +
+ {isInitialized ? ( + <> + {shortcuts.length !== 0 ? ( + + ) : ( +
+

No shortcut found.

+
+ )} + + + +
+
+ + + + + + +
+ +
+ + ) : ( +
+ +

Please set your domain and access token first.

+
+ + Or + +
+
+ )} +
+
); }; -export default IndexPopup; +const Popup = () => { + return ( + + + + + ); +}; + +export default Popup; diff --git a/frontend/extension/src/style.css b/frontend/extension/src/style.css index 6805d7b..cdb8517 100644 --- a/frontend/extension/src/style.css +++ b/frontend/extension/src/style.css @@ -5,7 +5,7 @@ body, html, #root { - @apply text-base; + @apply text-base dark:bg-zinc-900; font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Noto Sans", "Noto Sans CJK SC", "Microsoft YaHei UI", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";