aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/layouts/SiteSettings.tsx
blob: 5c0eef8f9de004b88b09e9d3aa3fa993257afc3f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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>
    </>
  )
}