Files
fusion/packages/dashboard/app/components/settings/sections/AppearanceSection.tsx

83 lines
2.8 KiB
TypeScript

/**
* Appearance section (U9 / KTD-10).
*
* Theme mode, color theme, dashboard font scale, language, and the
* session-banner suppression toggle. The three-tier device-local prefs
* (theme/language/font scale) keep their hooks in the shell — this section only
* relays their current values and change callbacks, mirroring the original
* inline JSX exactly (it both writes the modal form AND calls the write-through
* callback so the live UI updates immediately).
*/
import type { ReactNode } from "react";
import { useTranslation } from "react-i18next";
import type { ThemeMode, ColorTheme } from "@fusion/core";
import { ThemeSelector } from "../../ThemeSelector";
import { LanguageSelector } from "../../LanguageSelector";
import type { SectionBaseProps } from "./context";
export interface AppearanceSectionProps extends SectionBaseProps {
scopeBanner: ReactNode;
themeMode: ThemeMode;
colorTheme: ColorTheme;
dashboardFontScalePct: number;
onThemeModeChange?: (mode: ThemeMode) => void;
onColorThemeChange?: (theme: ColorTheme) => void;
onDashboardFontScaleChange?: (scalePct: number) => void;
sessionBannersHidden: boolean;
setSessionBannersHidden: (hidden: boolean) => void;
}
export function AppearanceSection({
scopeBanner,
setForm,
themeMode,
colorTheme,
dashboardFontScalePct,
onThemeModeChange,
onColorThemeChange,
onDashboardFontScaleChange,
sessionBannersHidden,
setSessionBannersHidden,
}: AppearanceSectionProps) {
const { t } = useTranslation("app");
return (
<>
{scopeBanner}
<h4 className="settings-section-heading">{t("settings.appearance.title", "Appearance")}</h4>
<ThemeSelector
themeMode={themeMode}
colorTheme={colorTheme}
dashboardFontScalePct={dashboardFontScalePct}
onThemeModeChange={(mode) => {
setForm((f) => ({ ...f, themeMode: mode }));
onThemeModeChange?.(mode);
}}
onColorThemeChange={(theme) => {
setForm((f) => ({ ...f, colorTheme: theme }));
onColorThemeChange?.(theme);
}}
onDashboardFontScaleChange={(scalePct) => {
setForm((f) => ({ ...f, dashboardFontScalePct: scalePct }));
onDashboardFontScaleChange?.(scalePct);
}}
/>
<LanguageSelector />
<div className="form-group">
<label className="checkbox-label">
<input
type="checkbox"
checked={sessionBannersHidden}
onChange={(e) => setSessionBannersHidden(e.target.checked)}
/>
<span>Hide AI session notification banners</span>
</label>
<small className="form-text text-muted">
Suppress the &ldquo;needs your input&rdquo; banner that appears when AI sessions are awaiting input or have failed.
</small>
</div>
</>
);
}
export default AppearanceSection;