aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/layouts/SiteSettings.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/layouts/SiteSettings.tsx')
-rw-r--r--src/layouts/SiteSettings.tsx73
1 files changed, 73 insertions, 0 deletions
diff --git a/src/layouts/SiteSettings.tsx b/src/layouts/SiteSettings.tsx
new file mode 100644
index 0000000..5c0eef8
--- /dev/null
+++ b/src/layouts/SiteSettings.tsx
@@ -0,0 +1,73 @@
+import { useRef } from 'react'
+import {
+ ActionIcon, Drawer, SegmentedControl, Stack, Text, Tooltip,
+ useMantineColorScheme, useMatches,
+} from '@mantine/core'
+import { GearIcon } from '@phosphor-icons/react'
+import { useNavigate, useSearchParams } from 'react-router'
+import classes from './SiteSettings.module.css'
+
+export function SiteSettings() {
+ const { colorScheme, setColorScheme } = useMantineColorScheme()
+ const size = useMatches({ base: '100%', sm: 'sm' })
+ const [searchParams, setSearchParams] = useSearchParams()
+ const navigate = useNavigate()
+ const openedHere = useRef(false)
+ const opened = searchParams.get('settings') === 'appearance'
+
+ function open() {
+ if (opened) return
+ openedHere.current = true
+ setSearchParams((previous) => {
+ const next = new URLSearchParams(previous)
+ next.set('settings', 'appearance')
+ return next
+ }, { preventScrollReset: true })
+ }
+
+ function close() {
+ if (openedHere.current) {
+ openedHere.current = false
+ void navigate(-1)
+ return
+ }
+
+ // 直接访问或刷新设置链接时,关闭抽屉不应离开当前页面。
+ setSearchParams((previous) => {
+ const next = new URLSearchParams(previous)
+ next.delete('settings')
+ return next
+ }, { replace: true, preventScrollReset: true })
+ }
+
+ return (
+ <>
+ <Tooltip label="网站设置" events={{ hover: true, focus: true, touch: false }}>
+ <ActionIcon className={classes.trigger} variant="subtle" color="gray" size="xl"
+ aria-label="打开网站设置" aria-haspopup="dialog" aria-expanded={opened} onClick={open}>
+ <GearIcon size={22} aria-hidden="true" />
+ </ActionIcon>
+ </Tooltip>
+ <Drawer opened={opened} onClose={close} title="网站设置" position="right" size={size}
+ closeButtonProps={{ 'aria-label': '关闭网站设置', size: 'lg' }}
+ classNames={{ header: classes.header, body: classes.body }}>
+ <Stack gap="md">
+ <Text id="site-color-scheme-label" fw={600}>外观模式</Text>
+ <SegmentedControl
+ aria-labelledby="site-color-scheme-label"
+ value={colorScheme}
+ data={[
+ { value: 'light', label: '亮色' },
+ { value: 'dark', label: '暗色' },
+ { value: 'auto', label: '跟随系统' },
+ ]}
+ onChange={(value) => {
+ if (value === 'light' || value === 'dark' || value === 'auto') setColorScheme(value)
+ }}
+ />
+ <Text size="sm" c="dimmed">设置即时生效并自动保存。选择“跟随系统”时,外观随设备主题变化。</Text>
+ </Stack>
+ </Drawer>
+ </>
+ )
+}