polish(layout): tidy filter header + sync status at higher browser zoom

- Filter header: show the active-filter count as a compact number pill instead of
  '{n} active' text, and keep the action buttons on one line (shrink-0 + nowrap) so
  nothing truncates or wraps in a narrow / zoomed-in sidebar (e.g. 125% browser zoom).
- Sync status: anchor the 'all synced' state with a small check icon so it no longer
  reads as orphaned text at the top of the nav rail.
This commit is contained in:
npeter83 2026-07-01 23:19:06 +02:00
parent 072b3296a3
commit c0487101fe
2 changed files with 19 additions and 12 deletions

View file

@ -541,21 +541,24 @@ export default function Sidebar({
> >
<ChevronLeft className="w-4 h-4" /> <ChevronLeft className="w-4 h-4" />
</button> </button>
<div className="text-sm font-semibold truncate"> <span className="text-sm font-semibold shrink-0">{t("sidebar.filters")}</span>
{t("sidebar.filters")} {activeCount > 0 && (
{activeCount > 0 && ( // Compact count pill (not "{n} active" text) so it never truncates or forces the
<span className="ml-1.5 text-xs font-medium text-accent"> // action buttons to wrap in a narrow / zoomed-in sidebar.
{t("sidebar.activeCount", { count: activeCount })} <span
</span> title={t("sidebar.activeCount", { count: activeCount })}
)} className="shrink-0 min-w-[18px] h-[18px] px-1.5 rounded-full bg-accent/15 text-accent text-[11px] font-semibold inline-flex items-center justify-center tabular-nums"
</div> >
{activeCount}
</span>
)}
</div> </div>
<div className="flex items-center gap-0.5"> <div className="flex items-center gap-0.5 shrink-0">
{!editing && ( {!editing && (
<button <button
onClick={clearAll} onClick={clearAll}
disabled={!active} disabled={!active}
className="text-xs text-muted enabled:hover:text-accent disabled:opacity-40 transition px-1" className="text-xs text-muted enabled:hover:text-accent disabled:opacity-40 transition px-1 whitespace-nowrap"
> >
{t("sidebar.clearAll")} {t("sidebar.clearAll")}
</button> </button>

View file

@ -1,6 +1,6 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Clock, Database, History, Loader2, Pause, Play } from "lucide-react"; import { CheckCircle2, Clock, Database, History, Loader2, Pause, Play } from "lucide-react";
import { api, type MyStatus } from "../lib/api"; import { api, type MyStatus } from "../lib/api";
import { formatViews } from "../lib/format"; import { formatViews } from "../lib/format";
import Tooltip from "./Tooltip"; import Tooltip from "./Tooltip";
@ -75,7 +75,11 @@ export default function SyncStatus({
{t("header.sync.recentQueued", { count: syncing })} {t("header.sync.recentQueued", { count: syncing })}
</span> </span>
) : ( ) : (
<span>{t("header.sync.allSynced")}</span> // A small check anchors the "all synced" state so it doesn't read as orphaned text.
<span className="flex items-center gap-1 text-emerald-500">
<CheckCircle2 className="w-3.5 h-3.5" />
<span className="text-muted">{t("header.sync.allSynced")}</span>
</span>
); );
const pauseBtn = isAdmin && (data.paused || syncing > 0 || notFull > 0) && ( const pauseBtn = isAdmin && (data.paused || syncing > 0 || notFull > 0) && (