fix(frontend): complete settings MVP structure
This commit is contained in:
@@ -23,15 +23,44 @@ function OptionIcon({ value }: { readonly value: ThemePreference }) {
|
||||
return <Monitor aria-hidden="true" />;
|
||||
}
|
||||
|
||||
export function ThemePreferenceMenu() {
|
||||
// The stored choice is browser state, not React state: read it through the
|
||||
// external store so the server snapshot stays "system" (no hydration
|
||||
// mismatch) and a change in another tab lands here too.
|
||||
const preference = useSyncExternalStore(
|
||||
function useThemePreference() {
|
||||
return useSyncExternalStore(
|
||||
subscribeThemePreference,
|
||||
readThemePreference,
|
||||
() => "system" as ThemePreference,
|
||||
);
|
||||
}
|
||||
|
||||
export function ThemePreferencePanel() {
|
||||
const preference = useThemePreference();
|
||||
|
||||
return (
|
||||
<section className="theme-preference-panel" aria-labelledby="theme-preference-title">
|
||||
<div className="section-heading">
|
||||
<b id="theme-preference-title">外观主题</b>
|
||||
<small>选择 Jyotisha 的显示方式</small>
|
||||
</div>
|
||||
<div className="theme-preference-options" role="group" aria-label="外观主题">
|
||||
{options.map((option) => (
|
||||
<button
|
||||
className="theme-preference-option"
|
||||
key={option.value}
|
||||
type="button"
|
||||
aria-pressed={preference === option.value}
|
||||
onClick={() => applyThemePreference(option.value)}
|
||||
>
|
||||
<OptionIcon value={option.value} />
|
||||
<span>{option.label}</span>
|
||||
{preference === option.value ? <Check aria-hidden="true" /> : null}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export function ThemePreferenceMenu() {
|
||||
const preference = useThemePreference();
|
||||
|
||||
return (
|
||||
<Menu.Group className="theme-menu">
|
||||
|
||||
Reference in New Issue
Block a user