fix(ui): stronger frosted glass + frosted settings backdrop; declutter header
- Increase .glass blur (32px) so overlay menus (account) read as proper frosted glass. - Blur the settings modal backdrop (overlay backdrop-blur) so the panel reliably frosts the content behind it instead of showing a sharp video through. - Remove the now-redundant header buttons (dark/light, color scheme, grid/list) — they live in Settings → Appearance. Header keeps search, sync, bell, account.
This commit is contained in:
parent
b7d448b403
commit
4a35e8b42a
4 changed files with 8 additions and 116 deletions
|
|
@ -132,12 +132,8 @@ export default function App() {
|
|||
<div className="h-screen flex flex-col bg-bg text-fg">
|
||||
<Header
|
||||
me={meQuery.data!}
|
||||
theme={theme}
|
||||
setTheme={setTheme}
|
||||
filters={filters}
|
||||
setFilters={setFilters}
|
||||
view={view}
|
||||
setView={changeView}
|
||||
page={page}
|
||||
setPage={setPage}
|
||||
onOpenSettings={() => setSettingsOpen(true)}
|
||||
|
|
|
|||
|
|
@ -1,98 +1,25 @@
|
|||
import { useRef, useState } from "react";
|
||||
import {
|
||||
Home,
|
||||
LayoutGrid,
|
||||
List,
|
||||
LogOut,
|
||||
Moon,
|
||||
Palette,
|
||||
Search,
|
||||
Settings,
|
||||
Shield,
|
||||
Sun,
|
||||
Tv,
|
||||
} from "lucide-react";
|
||||
import { SCHEMES, type Scheme, type ThemePrefs } from "../lib/theme";
|
||||
import { Home, LogOut, Search, Settings, Shield, Tv } from "lucide-react";
|
||||
import type { FeedFilters, Me } from "../lib/api";
|
||||
import type { Page } from "../lib/urlState";
|
||||
import SyncStatus from "./SyncStatus";
|
||||
import NotificationCenter from "./NotificationCenter";
|
||||
|
||||
function IconBtn(props: React.ButtonHTMLAttributes<HTMLButtonElement>) {
|
||||
const { className = "", ...rest } = props;
|
||||
return (
|
||||
<button
|
||||
{...rest}
|
||||
className={`p-2 rounded-lg text-muted hover:text-fg hover:bg-card transition ${className}`}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function ThemeMenu({
|
||||
theme,
|
||||
setTheme,
|
||||
}: {
|
||||
theme: ThemePrefs;
|
||||
setTheme: (t: ThemePrefs) => void;
|
||||
}) {
|
||||
return (
|
||||
<div className="glass absolute right-0 mt-2 w-60 rounded-xl p-3 z-30 animate-[popIn_0.16s_ease]">
|
||||
<div className="text-xs uppercase tracking-wide text-muted mb-2">Color scheme</div>
|
||||
<div className="grid grid-cols-4 gap-2 mb-3">
|
||||
{SCHEMES.map((s) => (
|
||||
<button
|
||||
key={s.id}
|
||||
onClick={() => setTheme({ ...theme, scheme: s.id as Scheme })}
|
||||
title={s.name}
|
||||
className={`h-9 rounded-lg border-2 transition ${
|
||||
theme.scheme === s.id ? "border-fg" : "border-transparent"
|
||||
}`}
|
||||
style={{ background: s.swatch }}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div className="text-xs uppercase tracking-wide text-muted mb-2">Text size</div>
|
||||
<input
|
||||
type="range"
|
||||
min={0.9}
|
||||
max={1.3}
|
||||
step={0.02}
|
||||
value={theme.fontScale}
|
||||
onChange={(e) => setTheme({ ...theme, fontScale: Number(e.target.value) })}
|
||||
className="w-full accent-accent"
|
||||
/>
|
||||
<div className="text-right text-xs text-muted">
|
||||
{Math.round(theme.fontScale * 100)}%
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Header({
|
||||
me,
|
||||
theme,
|
||||
setTheme,
|
||||
filters,
|
||||
setFilters,
|
||||
view,
|
||||
setView,
|
||||
page,
|
||||
setPage,
|
||||
onOpenSettings,
|
||||
}: {
|
||||
me: Me;
|
||||
theme: ThemePrefs;
|
||||
setTheme: (t: ThemePrefs) => void;
|
||||
filters: FeedFilters;
|
||||
setFilters: (f: FeedFilters) => void;
|
||||
view: "grid" | "list";
|
||||
setView: (v: "grid" | "list") => void;
|
||||
page: Page;
|
||||
setPage: (p: Page) => void;
|
||||
onOpenSettings: () => void;
|
||||
}) {
|
||||
const [menuOpen, setMenuOpen] = useState(false);
|
||||
|
||||
async function logout() {
|
||||
await fetch("/auth/logout", { method: "POST", credentials: "include" });
|
||||
location.reload();
|
||||
|
|
@ -125,34 +52,7 @@ export default function Header({
|
|||
)}
|
||||
|
||||
<div className="flex items-center gap-1">
|
||||
{page === "feed" && (
|
||||
<IconBtn
|
||||
onClick={() => setView(view === "grid" ? "list" : "grid")}
|
||||
title={view === "grid" ? "List view" : "Grid view"}
|
||||
>
|
||||
{view === "grid" ? <List className="w-5 h-5" /> : <LayoutGrid className="w-5 h-5" />}
|
||||
</IconBtn>
|
||||
)}
|
||||
<IconBtn
|
||||
onClick={() => setTheme({ ...theme, mode: theme.mode === "dark" ? "light" : "dark" })}
|
||||
title="Toggle dark / light"
|
||||
>
|
||||
{theme.mode === "dark" ? <Sun className="w-5 h-5" /> : <Moon className="w-5 h-5" />}
|
||||
</IconBtn>
|
||||
<div className="relative">
|
||||
<IconBtn onClick={() => setMenuOpen((o) => !o)} title="Theme">
|
||||
<Palette className="w-5 h-5" />
|
||||
</IconBtn>
|
||||
{menuOpen && (
|
||||
<>
|
||||
<div className="fixed inset-0 z-20" onClick={() => setMenuOpen(false)} />
|
||||
<ThemeMenu theme={theme} setTheme={setTheme} />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<NotificationCenter filters={filters} setFilters={setFilters} />
|
||||
|
||||
<div className="pl-1">
|
||||
<AccountMenu
|
||||
me={me}
|
||||
|
|
@ -205,11 +105,7 @@ function AccountMenu({
|
|||
"w-full flex items-center gap-2 text-sm px-2 py-2 rounded-lg text-muted hover:text-fg hover:bg-card transition";
|
||||
|
||||
return (
|
||||
<div
|
||||
className="relative"
|
||||
onMouseEnter={openNow}
|
||||
onMouseLeave={closeSoon}
|
||||
>
|
||||
<div className="relative" onMouseEnter={openNow} onMouseLeave={closeSoon}>
|
||||
<button
|
||||
onClick={() => setOpen((o) => !o)}
|
||||
title={me.email}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ export default function SettingsPanel({
|
|||
return (
|
||||
<div className="fixed inset-0 z-40 flex justify-end">
|
||||
<div
|
||||
className={`absolute inset-0 bg-black/40 ${
|
||||
className={`absolute inset-0 bg-black/30 backdrop-blur-lg ${
|
||||
closing ? "animate-[overlayOut_0.19s_ease_forwards]" : "animate-[overlayIn_0.2s_ease]"
|
||||
}`}
|
||||
onClick={close}
|
||||
|
|
|
|||
|
|
@ -32,11 +32,11 @@ body {
|
|||
|
||||
/* ===== Liquid-glass surface system (theme-aware, GPU-light) ===== */
|
||||
.glass {
|
||||
/* Mostly opaque so overlay menus/panels stay readable over arbitrary content;
|
||||
the blur + slight translucency keep the glassy feel. */
|
||||
background: color-mix(in srgb, var(--surface) 90%, transparent);
|
||||
backdrop-filter: blur(24px) saturate(1.7);
|
||||
-webkit-backdrop-filter: blur(24px) saturate(1.7);
|
||||
/* Frosted overlay surface: strong blur so background content is an unreadable
|
||||
blur, plus enough opacity to stay legible over anything. */
|
||||
background: color-mix(in srgb, var(--surface) 86%, transparent);
|
||||
backdrop-filter: blur(32px) saturate(1.8);
|
||||
-webkit-backdrop-filter: blur(32px) saturate(1.8);
|
||||
border: 1px solid color-mix(in srgb, var(--border) 75%, transparent);
|
||||
box-shadow:
|
||||
inset 0 1px 0 color-mix(in srgb, #fff 15%, transparent),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue