refactor: Remove neutral contrast theme adjustment and improve floating menu event handling by delaying listeners and checking for unmounted elements.

This commit is contained in:
2025-11-25 14:12:53 +01:00
parent 30602e6b66
commit 2c42e63bab
4 changed files with 27 additions and 95 deletions
+2 -44
View File
@@ -9,7 +9,6 @@ import React, {
import {
DARK_MODE_MEDIA_QUERY,
DEFAULT_NEUTRAL_CHROMA,
DEFAULT_NEUTRAL_CONTRAST,
DEFAULT_NEUTRAL_HUE,
DEFAULT_THEME_MODE,
SIDEBAR_COLLAPSE_STORAGE_KEY,
@@ -26,9 +25,6 @@ interface SidebarContextValue {
neutralChroma: number;
setNeutralChroma: (value: number | string) => void;
resetNeutralChroma: () => void;
neutralContrast: number;
setNeutralContrast: (value: number | string) => void;
resetNeutralContrast: () => void;
themeMode: ThemeMode;
setThemeMode: (mode: ThemeMode) => void;
cycleThemeMode: () => void;
@@ -43,7 +39,6 @@ const loadInitialThemeSettings = () => {
const defaults = {
neutralHue: DEFAULT_NEUTRAL_HUE,
neutralChroma: DEFAULT_NEUTRAL_CHROMA,
neutralContrast: DEFAULT_NEUTRAL_CONTRAST,
mode: DEFAULT_THEME_MODE,
};
@@ -68,14 +63,12 @@ const loadInitialThemeSettings = () => {
return {
neutralHue: Number.isNaN(parsed) ? defaults.neutralHue : parsed,
neutralChroma: readNumberVar('--neutral-chroma', defaults.neutralChroma),
neutralContrast: readNumberVar('--neutral-contrast', defaults.neutralContrast),
};
};
const rootValues = loadFromRoot();
let neutralHueValue = rootValues.neutralHue;
let neutralChromaValue = rootValues.neutralChroma;
let neutralContrastValue = rootValues.neutralContrast;
let modeValue = defaults.mode;
const composite = window.localStorage.getItem(THEME_STORAGE_KEY);
@@ -90,10 +83,7 @@ const loadInitialThemeSettings = () => {
if (!Number.isNaN(storedChroma)) {
neutralChromaValue = Math.min(Math.max(storedChroma, 0), 1);
}
const storedContrast = Number.parseFloat(parsed?.neutralContrast);
if (!Number.isNaN(storedContrast)) {
neutralContrastValue = Math.min(Math.max(storedContrast, 0), 1);
}
const storedMode = parsed?.mode;
if (THEME_MODES.includes(storedMode)) {
modeValue = storedMode;
@@ -118,7 +108,6 @@ const loadInitialThemeSettings = () => {
return {
neutralHue: neutralHueValue,
neutralChroma: neutralChromaValue,
neutralContrast: neutralContrastValue,
mode: modeValue,
};
};
@@ -143,7 +132,6 @@ export const SidebarProvider = ({ initialCollapsed = false, children }) => {
const initialTheme = useMemo(() => loadInitialThemeSettings(), []);
const [neutralHue, setNeutralHueState] = useState(initialTheme.neutralHue);
const [neutralChroma, setNeutralChromaState] = useState(initialTheme.neutralChroma);
const [neutralContrast, setNeutralContrastState] = useState(initialTheme.neutralContrast);
const [themeMode, setThemeModeState] = useState(initialTheme.mode);
const [systemPrefersDark, setSystemPrefersDark] = useState(() => {
if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') {
@@ -160,10 +148,6 @@ export const SidebarProvider = ({ initialCollapsed = false, children }) => {
document.documentElement.style.setProperty('--neutral-chroma', String(neutralChroma));
}, [neutralChroma]);
useEffect(() => {
document.documentElement.style.setProperty('--neutral-contrast', String(neutralContrast));
}, [neutralContrast]);
useEffect(() => {
if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') {
return () => undefined;
@@ -198,7 +182,6 @@ export const SidebarProvider = ({ initialCollapsed = false, children }) => {
const payload = JSON.stringify({
neutralHue,
neutralChroma,
neutralContrast,
mode: themeMode,
});
window.localStorage.setItem(THEME_STORAGE_KEY, payload);
@@ -207,7 +190,7 @@ export const SidebarProvider = ({ initialCollapsed = false, children }) => {
} catch (error) {
console.warn('[theme] failed to persist theme settings', error);
}
}, [neutralHue, neutralChroma, neutralContrast, themeMode]);
}, [neutralHue, neutralChroma, themeMode]);
const setNeutralHue = useCallback((value) => {
setNeutralHueState((prev) => {
@@ -241,24 +224,6 @@ export const SidebarProvider = ({ initialCollapsed = false, children }) => {
setNeutralChromaState(DEFAULT_NEUTRAL_CHROMA);
}, []);
const setNeutralContrast = useCallback((value) => {
setNeutralContrastState((prev) => {
if (value === '' || value === null || value === undefined) {
return DEFAULT_NEUTRAL_CONTRAST;
}
const parsed = Number(value);
if (Number.isNaN(parsed)) {
return prev;
}
const clamped = Math.min(Math.max(parsed, 0), 1);
return Math.round(clamped * 1000) / 1000;
});
}, []);
const resetNeutralContrast = useCallback(() => {
setNeutralContrastState(DEFAULT_NEUTRAL_CONTRAST);
}, []);
const resetNeutralHue = useCallback(() => {
setNeutralHueState(DEFAULT_NEUTRAL_HUE);
}, []);
@@ -296,18 +261,14 @@ export const SidebarProvider = ({ initialCollapsed = false, children }) => {
setNeutralHue,
neutralChroma,
setNeutralChroma,
neutralContrast,
setNeutralContrast,
resetNeutralHue,
resetNeutralChroma,
resetNeutralContrast,
themeMode,
setThemeMode,
cycleThemeMode,
themeModes: THEME_MODES,
defaultNeutralHue: DEFAULT_NEUTRAL_HUE,
defaultNeutralChroma: DEFAULT_NEUTRAL_CHROMA,
defaultNeutralContrast: DEFAULT_NEUTRAL_CONTRAST,
}),
[
collapsed,
@@ -316,11 +277,8 @@ export const SidebarProvider = ({ initialCollapsed = false, children }) => {
setNeutralHue,
neutralChroma,
setNeutralChroma,
neutralContrast,
setNeutralContrast,
resetNeutralHue,
resetNeutralChroma,
resetNeutralContrast,
themeMode,
setThemeMode,
cycleThemeMode,