diff --git a/CLAUDE.md b/CLAUDE.md
index 846ffe0f..53e6a54f 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -81,7 +81,7 @@ CQRS, a repository/DI framework, a router library, a generic CRUD-router factory
| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| ORM | SQLAlchemy 2.0 `select()` | `db.query(...)` |
| Request body | a Pydantic model | `payload: dict` |
-| Request SIZE | nothing — `bodylimit` caps every route (SEC-20); need more? add a ceiling to `ROUTE_MAX_BODY_BYTES` | `capped_body` on a route that does not read raw bytes itself |
+| Request SIZE | nothing — `bodylimit` caps every route (SEC-20); need more? add a ceiling to `ROUTE_MAX_BODY_BYTES` | `capped_body` on a route that does not read raw bytes itself |
| Ownership check | `owned_or_404` / `get_or_404` | ad-hoc `_own_playlist`/`_owned`/`_own_job` |
| Admin gate import | `app.auth` | the `app.routes.admin` re-export |
| Upstream failure status | `422` with JSON detail | `502` (reserve 502 for raw byte-proxies) |
@@ -92,7 +92,7 @@ CQRS, a repository/DI framework, a router library, a generic CRUD-router factory
| Job status word | the `downloads/status.py` StrEnum | loose `"canceled"`/`"cancelled"` literals |
| Current time | inline `datetime.now(timezone.utc)` | new `now_utc`/`_now` helpers |
| FE per-account state | `usePref` | raw `readAccount`/`writeAccount` or bespoke hooks |
-| FE action button | `ui/Button` — pick a `SIZES` rung | a hand-rolled `
- : }
onClick={() => pauseResume.mutate(data.paused)}
disabled={pauseResume.isPending}
- className="glass-card glass-hover flex items-center gap-2 px-3 py-2 rounded-xl text-sm disabled:opacity-50 transition"
>
- {data.paused ? : }
{data.paused ? t("scheduler.resume") : t("scheduler.pause")}
-
+
diff --git a/frontend/src/components/SettingsPanel.tsx b/frontend/src/components/SettingsPanel.tsx
index c69407f3..fff99313 100644
--- a/frontend/src/components/SettingsPanel.tsx
+++ b/frontend/src/components/SettingsPanel.tsx
@@ -24,6 +24,7 @@ import { START_ON_HOME } from "./navigationInit";
import { usePrefs } from "./prefsContext";
import Tabs from "./ui/Tabs";
import { useMe } from "../lib/useMe";
+import { Pressable } from "./ui/Pressable";
// The Settings page edits server-persisted preferences. Each change applies locally for instant
// preview AND auto-saves (debounced) — no draft, no Save button; a small indicator flashes the
@@ -147,7 +148,7 @@ function Appearance({ prefs }: { prefs: PrefsController }) {
{SCHEMES.map((s) => (
- setTheme({ ...theme, scheme: s.id as Scheme })}
aria-label={s.name}
aria-pressed={theme.scheme === s.id}
@@ -293,7 +294,7 @@ function Notifications({ prefs }: { prefs: PrefsController }) {
/>
)}
-
notify({
level: "info",
@@ -302,10 +303,11 @@ function Notifications({ prefs }: { prefs: PrefsController }) {
sound: true,
})
}
- className="mt-2 text-sm text-accent hover:underline"
+ variant="link"
+ className="mt-2 text-sm"
>
{t("settings.notifications.sendTest")}
-
+
);
}
@@ -439,14 +441,15 @@ function SignInMethods({ me }: { me: Me }) {
{t("settings.account.googleLink.connected")}
) : (
- {
window.location.href = withActiveAccount("/auth/link");
}}
- className="shrink-0 glass-card glass-hover px-3 py-1.5 rounded-xl text-sm transition"
>
{t("settings.account.googleLink.connect")}
-
+
)}
)}
@@ -461,17 +464,19 @@ function SignInMethods({ me }: { me: Me }) {
: t("settings.account.password.unsetHint")}
- {
setOpen((o) => !o);
setErr(null);
}}
- className="shrink-0 glass-card glass-hover px-3 py-1.5 rounded-xl text-sm transition"
>
{me.has_password
? t("settings.account.password.change")
: t("settings.account.password.set")}
-
+
{open && (