feat(glass): user-facing Image-fade slider under Settings > Background image

Replaces the dev-only backdrop-fade knob with a real control: when Background
image is on (dark theme), a 0-100% 'Image fade' slider appears beneath it and
drives --bg-fade live (higher = fainter). Persists to DB + localStorage via the
existing theme prefs path (ThemePrefs.bgFade, applyTheme sets the CSS var).
Removed --bg-fade from the GlassTuner so the two don't fight over the var.
This commit is contained in:
npeter83 2026-07-12 22:24:09 +02:00
parent f9f90cf609
commit a187b2f475
6 changed files with 25 additions and 1 deletions

View file

@ -38,7 +38,6 @@ const SLIDERS: Slider[] = [
{ k: "--glass-inset", label: "Top highlight", min: 0, max: 40, step: 1, unit: "%", def: 15 },
{ k: "--glass-scrim", label: "Under-text scrim", min: 0, max: 85, step: 1, unit: "%", def: 30 },
{ k: "--ambient", label: "Ambient intensity", min: 0, max: 2, step: 0.05, unit: "", def: 1.1 },
{ k: "--bg-fade", label: "Backdrop fade", min: 40, max: 97, step: 1, unit: "%", def: 60 },
];
const PALETTE: { k: string; label: string }[] = [

View file

@ -169,6 +169,24 @@ function Appearance({ prefs }: { prefs: PrefsController }) {
onChange={(v) => setTheme({ ...theme, bgImage: v })}
/>
</SettingRow>
{theme.mode === "dark" && theme.bgImage && (
<div className="pl-1 pb-1">
<div className="flex items-center justify-between text-xs text-muted mb-1">
<span>{t("settings.appearance.backgroundFade")}</span>
<span className="tabular-nums">{theme.bgFade}%</span>
</div>
<input
type="range"
min={0}
max={100}
step={1}
value={theme.bgFade}
onChange={(e) => setTheme({ ...theme, bgFade: Number(e.target.value) })}
aria-label={t("settings.appearance.backgroundFade")}
className="w-full accent-accent"
/>
</div>
)}
<SettingRow label={t("settings.appearance.listView")} hint={t("settings.appearance.listViewHint")}>
<Switch
label={t("settings.appearance.listView")}

View file

@ -35,6 +35,7 @@
"darkMode": "Dunkler Modus",
"backgroundImage": "Hintergrundbild",
"backgroundImageHint": "Zeigt ein dezentes, themenbezogenes Hintergrundbild hinter der App, damit die Glasflächen etwas zum Brechen haben. Nur im dunklen Design; aus = einfarbig.",
"backgroundFade": "Bildabblendung",
"listView": "Listenansicht",
"listViewHint": "Zeigt den Feed als kompakte Liste statt als Kartenraster an.",
"performanceMode": "Leistungsmodus",

View file

@ -35,6 +35,7 @@
"darkMode": "Dark mode",
"backgroundImage": "Background image",
"backgroundImageHint": "Show a subtle per-theme backdrop image behind the app so the glass surfaces have something to refract. Dark theme only; off = flat colour.",
"backgroundFade": "Image fade",
"listView": "List view",
"listViewHint": "Show the feed as a compact list instead of a grid of cards.",
"performanceMode": "Performance mode",

View file

@ -35,6 +35,7 @@
"darkMode": "Sötét mód",
"backgroundImage": "Háttérkép",
"backgroundImageHint": "Halvány, témánkénti háttérkép az app mögött, hogy az üveges felületeknek legyen mit megtörniük. Csak sötét témában; kikapcsolva sima szín.",
"backgroundFade": "Kép elhalványítása",
"listView": "Listanézet",
"listViewHint": "A hírfolyam kompakt listaként jelenik meg a kártyarács helyett.",
"performanceMode": "Teljesítmény mód",

View file

@ -18,6 +18,8 @@ export interface ThemePrefs {
fontScale: number;
/** Show the per-scheme background image (dark theme only); off = flat colour. */
bgImage: boolean;
/** How strongly the background image is faded out, 0100% (higher = fainter). */
bgFade: number;
}
export const DEFAULT_THEME: ThemePrefs = {
@ -25,6 +27,7 @@ export const DEFAULT_THEME: ThemePrefs = {
scheme: "midnight",
fontScale: 1.06,
bgImage: true,
bgFade: 60,
};
export function applyTheme(t: ThemePrefs): void {
@ -32,6 +35,7 @@ export function applyTheme(t: ThemePrefs): void {
el.dataset.theme = t.mode;
el.dataset.scheme = t.scheme;
el.style.setProperty("--font-scale", String(t.fontScale));
if (typeof t.bgFade === "number") el.style.setProperty("--bg-fade", `${t.bgFade}%`);
}
export function loadLocalTheme(): ThemePrefs {