feat(settings): theme scheduler, UI scale, CustomSelect scroll fix

- Time-based theme scheduler: auto-switches between day/night theme
  based on configurable times; setInterval re-checks every minute
- UI scale slider (80–150%) via CSS zoom on document root; preset
  buttons aligned to actual slider positions
- CustomSelect: scroll listener keeps dropdown anchored on scroll
- All features i18n in 7 languages

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Psychotoxical
2026-04-08 12:23:14 +02:00
parent f0b423ddc4
commit e64d151079
16 changed files with 285 additions and 10 deletions
+13 -3
View File
@@ -25,15 +25,14 @@ export default function CustomSelect({ value, options, onChange, className = '',
const selected = options.find(o => o.value === value);
useLayoutEffect(() => {
if (!open || !triggerRef.current) return;
const updateDropStyle = () => {
if (!triggerRef.current) return;
const rect = triggerRef.current.getBoundingClientRect();
const MARGIN = 6;
const maxH = 240;
const spaceBelow = window.innerHeight - rect.bottom - MARGIN;
const spaceAbove = rect.top - MARGIN;
const useAbove = spaceBelow < 80 && spaceAbove > spaceBelow;
setDropStyle({
position: 'fixed',
left: rect.left,
@@ -44,6 +43,17 @@ export default function CustomSelect({ value, options, onChange, className = '',
maxHeight: Math.min(maxH, useAbove ? spaceAbove : spaceBelow),
zIndex: 99998,
});
};
useLayoutEffect(() => {
if (!open) return;
updateDropStyle();
}, [open]);
useEffect(() => {
if (!open) return;
window.addEventListener('scroll', updateDropStyle, true);
return () => window.removeEventListener('scroll', updateDropStyle, true);
}, [open]);
useEffect(() => {
+1 -1
View File
@@ -9,7 +9,7 @@ interface ThemeDef {
accent: string;
}
const THEME_GROUPS: { group: string; themes: ThemeDef[] }[] = [
export const THEME_GROUPS: { group: string; themes: ThemeDef[] }[] = [
{
group: 'Games',
themes: [