feat(web): connect quick share flow
Signed-off-by: JustMe <mr.toing@outlook.com>
This commit is contained in:
1 parent
53768a195d
commit
e02e024605
138 files changed
+10614
No files matched your search
@@ -0,0 +1,47 @@
|
||||
import { useCallback, useState } from 'react';
|
||||
import { setTheme, useTheme, type ThemePref } from '@/lib/theme';
|
||||
import { Button } from './Button';
|
||||
import { Icon, type IconName } from './Icon';
|
||||
import { Popover } from './Popover';
|
||||
import styles from './ThemeMenu.module.css';
|
||||
|
||||
const OPTIONS: { value: ThemePref; label: string; icon: IconName }[] = [
|
||||
{ value: 'system', label: '跟随系统', icon: 'auto' },
|
||||
{ value: 'light', label: '亮色', icon: 'sun' },
|
||||
{ value: 'dark', label: '暗色', icon: 'moon' },
|
||||
];
|
||||
|
||||
export function ThemeMenu() {
|
||||
const theme = useTheme();
|
||||
const [open, setOpen] = useState(false);
|
||||
const close = useCallback(() => setOpen(false), []);
|
||||
const current = OPTIONS.find((o) => o.value === theme) ?? OPTIONS[0];
|
||||
|
||||
return (
|
||||
<Popover
|
||||
open={open}
|
||||
onClose={close}
|
||||
trigger={<Button variant="ghost" icon={current?.icon ?? 'auto'} label="外观" onClick={() => setOpen((v) => !v)} />}
|
||||
>
|
||||
<div role="radiogroup" aria-label="外观">
|
||||
{OPTIONS.map((o) => (
|
||||
<button
|
||||
key={o.value}
|
||||
type="button"
|
||||
role="radio"
|
||||
aria-checked={o.value === theme}
|
||||
className={styles.item}
|
||||
onClick={() => {
|
||||
setTheme(o.value);
|
||||
close();
|
||||
}}
|
||||
>
|
||||
<Icon name={o.icon} size={18} />
|
||||
<span className={styles.label}>{o.label}</span>
|
||||
{o.value === theme ? <Icon name="check" size={16} /> : null}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user