refactor(ui): fold Settings + Stats tabs into shared Tabs (R13 S2c step 6)

Tabs gains an `orientation` prop (+ optional per-tab `icon`/`testId`) so the
two hand-rolled NAV tab-sets that duplicated its active treatment now use it:
- SettingsPanel vertical rail (appearance/notifications/account) -> vertical
  Tabs with icons; settings-tab-* testIds preserved
- Stats overview/system tabs -> Tabs (rounded-full+border -> the rounded-lg
  tab canonical, per the agreed tab shape)

The underline ChannelPage tabs and the icon NavSidebar rail are intentionally
left as distinct idioms. Self-E2E'd: settings rail switches + persists with
icons, stats tabs toggle. gate green (tsc/eslint-0/vitest 136/knip/prettier).
Branch not merged.
This commit is contained in:
2026-08-15 01:04:59 +02:00
parent b57aec113e
commit dd2d53bb96
3 changed files with 46 additions and 41 deletions
+9 -12
View File
@@ -10,6 +10,7 @@ import { LS, useAccountPersistedState } from "../lib/storage";
import Tooltip from "./Tooltip";
import { LoadingState, StateMessage } from "./QueryState";
import FilterChipGroup from "./FilterChipGroup";
import Tabs from "./Tabs";
import { Section, SettingRow } from "./ui/form";
import { useMe } from "../lib/useMe";
@@ -31,18 +32,14 @@ export default function Stats() {
<div className="p-4 max-w-4xl mx-auto">
{/* Only admins have a second (System) tab; everyone else just sees the Overview. */}
{isAdmin && (
<div className="flex items-center gap-1 mb-4">
{(["overview", "system"] as StatsTab[]).map((id) => (
<button
key={id}
onClick={() => setTab(id)}
aria-pressed={tab === id}
className="pill px-3 py-1.5 rounded-full text-sm border"
>
{t(`stats.tabs.${id}`)}
</button>
))}
</div>
<Tabs
active={tab}
onChange={setTab}
tabs={(["overview", "system"] as StatsTab[]).map((id) => ({
id,
label: t(`stats.tabs.${id}`),
}))}
/>
)}
{tab === "system" && isAdmin ? <SystemStats /> : <Overview me={me} />}