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:
@@ -308,9 +308,6 @@ const Sidebar: React.FC<SidebarProps> = ({
|
||||
neutralChroma,
|
||||
setNeutralChroma,
|
||||
resetNeutralChroma,
|
||||
neutralContrast,
|
||||
setNeutralContrast,
|
||||
resetNeutralContrast,
|
||||
themeMode,
|
||||
cycleThemeMode,
|
||||
themeModes,
|
||||
@@ -343,7 +340,6 @@ const Sidebar: React.FC<SidebarProps> = ({
|
||||
}, [collapseSidebar]);
|
||||
const neutralHueInputId = useId();
|
||||
const neutralChromaInputId = useId();
|
||||
const neutralContrastInputId = useId();
|
||||
const sortedCorrespondents = useMemo<CorrespondentEntry[]>(() => {
|
||||
if (!Array.isArray(correspondents)) {
|
||||
return [];
|
||||
@@ -446,8 +442,7 @@ const Sidebar: React.FC<SidebarProps> = ({
|
||||
const handleThemeAdjustmentsReset = useCallback(() => {
|
||||
resetNeutralHue();
|
||||
resetNeutralChroma();
|
||||
resetNeutralContrast();
|
||||
}, [resetNeutralHue, resetNeutralChroma, resetNeutralContrast]);
|
||||
}, [resetNeutralHue, resetNeutralChroma]);
|
||||
|
||||
const handleNeutralHueChange = useCallback(
|
||||
(value: string) => {
|
||||
@@ -479,21 +474,6 @@ const Sidebar: React.FC<SidebarProps> = ({
|
||||
[resetNeutralChroma, setNeutralChroma],
|
||||
);
|
||||
|
||||
const handleNeutralContrastChange = useCallback(
|
||||
(value: string) => {
|
||||
if (value === '') {
|
||||
resetNeutralContrast();
|
||||
return;
|
||||
}
|
||||
const parsed = Number(value);
|
||||
if (Number.isNaN(parsed)) {
|
||||
return;
|
||||
}
|
||||
setNeutralContrast(parsed);
|
||||
},
|
||||
[resetNeutralContrast, setNeutralContrast],
|
||||
);
|
||||
|
||||
const formatSliderValue = useCallback((value: number | string) => {
|
||||
const parsed = Number(value);
|
||||
if (Number.isNaN(parsed)) {
|
||||
@@ -574,20 +554,6 @@ const Sidebar: React.FC<SidebarProps> = ({
|
||||
/>
|
||||
<span className="menu__slider-value">{formatSliderValue(neutralChroma)}</span>
|
||||
</label>
|
||||
<label className="menu__slider" htmlFor={neutralContrastInputId}>
|
||||
<span className="menu__slider-label">Contrast</span>
|
||||
<input
|
||||
id={neutralContrastInputId}
|
||||
type="range"
|
||||
min="0"
|
||||
max="1"
|
||||
step="0.01"
|
||||
value={neutralContrast}
|
||||
onChange={(event) => handleNeutralContrastChange(event.target.value)}
|
||||
onDoubleClick={resetNeutralContrast}
|
||||
/>
|
||||
<span className="menu__slider-value">{formatSliderValue(neutralContrast)}</span>
|
||||
</label>
|
||||
</div>
|
||||
)
|
||||
: null;
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user