Co-authored-by: Cursor <[email protected]>
7.6 KiB
Admin UX Cleanup — Design Spec
Date: 2026-07-17
Status: Approved in chat (Phase 1); Phases 2–3 queued after Phase 1 ships
Scope: Admin panel (/admin/*) — EpicNext-cms
Context
The admin already has hub chrome (AdminHubChrome + AdminPageShell + AdminSectionTabs), a condensed sidebar, theme/language switchers, and ACL. Remaining pain is inconsistency: double headers, orphan routes, duplicated chrome controls, crowded Radio tabs, and identical icons for Access vs Moderation.
This document covers a three-phase program. Only Phase 1 is in scope for the next implementation plan.
Goals
- One clear page hierarchy under each hub (no stacked titles).
- Every useful admin route reachable from hub tabs (no orphan pages).
- Theme/language controls in one primary place (no desktop duplicate).
- Radio hub usable on smaller widths without losing URLs.
- Access vs Moderation visually distinct in the sidebar.
Non-goals (Phase 1)
- Full admin i18n (Phase 2).
- Full design-token / shadcn unification (Phase 3).
- New features, new pages, or permission model changes.
- Changing public-site chrome or avatar/imager behavior.
Phase 1 — UX cleanup
1.1 Single hub header
Current: AdminHubChrome renders hub title + subtitle + tabs; many child pages also render h1 / intro copy (often text-3xl font-bold), producing double titles.
Rule:
| Page type | Hub shell title | Page-level h1 |
|---|---|---|
| Hub list / overview (matches a hub tab) | Keep | Remove (or demote to section heading if needed for a11y only when content blocks require it) |
Nested create / edit / show (…/new, …/[id], …/create, …/show/[id]) |
Keep hub title | Keep entity-specific title (e.g. poll name, “Create Event”) |
Dashboard /admin (no hub) |
N/A | Keep its own header |
Implementation approach:
- Prefer removing redundant page chrome blocks (icon +
h1+ muted description that duplicates hub subtitle). - Keep action rows (Create buttons, filters, search) that sit next to the old
h1; restructure to a toolbar without a second page title. - Do not strip semantic headings inside content cards/tables.
Acceptance: Opening any hub tab shows exactly one primary title (from AdminPageShell). Detail pages still show the entity/create title below the hub chrome.
1.2 Wire orphan routes into hub tabs
Add tabs (English labels for Phase 1; i18n keys in Phase 2):
| Hub | New / adjusted tabs | Hrefs |
|---|---|---|
| Users | Multi-accounts | /admin/users/multi-accounts |
| Engagement | Event types, Templates | /admin/events/types, /admin/tickets/templates |
| Observability | Chat, Commands, Trades | /admin/logs/chat, /admin/logs/commands, /admin/logs/trades |
| Observability | Activity, Economy (under analytics) | /admin/analytics/activity, /admin/analytics/economy |
| Observability | Errors (under devops) | /admin/devops/errors |
Tab matching notes:
- Users “Directory” must keep
matchthat includes/admin/usersbut not steal active state from/admin/users/multi-accounts(exact / longest-prefix matching already inAdminSectionTabs— verify Directorymatchdoes not list multi-accounts; multi-accounts gets its own tab withhrefonly or explicitmatch). - Logs “Logs” tab (
/admin/logs) must not stay active on/admin/logs/chatetc. Prefer exact match for the main Logs index, or give sub-log tabs longer prefixes so they win (existing scorer prefers longer / exact — verify). - Analytics “Analytics” vs Activity/Economy: same longest-match rule.
- Engagement Event types:
/admin/events/typesmust win over Eventsmatch: ["/admin/events"]— longest prefix already favors/admin/events/typesif that tab is listed.
Acceptance: Every orphan page above is one click from its hub tab strip. No new routes required.
1.3 Theme / language control placement
Decision: Primary controls stay in the sidebar (desktop). Topbar keeps theme + language only on mobile (when the sidebar is not persistently visible), or remove from topbar entirely if AdminMobileWrapper already exposes sidebar controls on mobile.
Preferred behavior:
- Desktop (
lg+): switchers only in sidebar header row; remove fromTopbar. - Mobile: switchers remain reachable via the mobile sidebar drawer (already present). If the drawer is hard to discover, keep a compact pair in the topbar only below
lg.
Acceptance: On desktop, theme/language appear once. Mobile users can still change theme and locale without hunting.
1.4 Radio hub tab grouping
URLs unchanged. UI presents two rows (or a primary row + overflow “More” row):
Primary: Overview, History, Moderation, Monitoring, Settings
Tools: Banners, Embed, API keys, Points, Ranks, Auto DJ
Implementation options (pick one in plan):
- A (recommended): Extend
AdminSectionTabs/ hub definition with optionalgroup?: "primary" | "tools"and render two labeled rows for Radio only. - B: Nested “Tools” dropdown tab — less discoverable; avoid unless row A overflows badly.
Acceptance: Radio remains fully linked; primary ops are visible without horizontal scroll on a typical laptop width (~1280px).
1.5 Distinct Access vs Moderation icons
- Access & security sidebar: keep
Ban(orShield) — already distinct from Users. - Moderation sidebar: change from
Shieldto something likeGavelorShieldAlertso it does not match Access.
Hub definition icons for Access vs Moderation should also differ if both appear in chrome.
Acceptance: Sidebar icons for Access and Moderation are not the same glyph.
Phase 2 — Admin i18n (queued)
- Move hub
title/subtitle/ tablabeltolabelKey+pages.admin.hubs.*(and tab keys). - Translate high-traffic pages: Users, Events, Logs, Settings, Moderation.
- i18n theme switcher aria/title strings for
variant="admin". - Do not block Phase 1 on this; Phase 1 may leave English hub strings as today.
Phase 3 — Design system (queued)
- Standardize list pages on
--admin-*tokens (admin-card, shared empty state, table chrome). - Optional shared
AdminListToolbarfor actions formerly next to removedh1s. - Gradual migration; no big-bang rewrite of catalog/user detail.
Risks & mitigations
| Risk | Mitigation |
|---|---|
Removing h1 hurts accessibility |
Hub shell already exposes one h1; detail pages keep entity h1. Spot-check with one screen reader pass on Users + Events. |
| Tab active-state regressions | Add/adjust match arrays; manually verify Directory vs Multi-accounts, Logs vs Chat. |
| Radio two-row tabs feel heavy | Only Radio uses groups; other hubs stay single row. |
| Mobile loses theme/lang | Keep switchers in sidebar drawer; optional lg:hidden topbar pair. |
Out of scope leftovers
- Calendar under Shop hub (IA smell) — defer unless requested.
- Legacy user route folder split (
show/[id]vs[id]) — defer. - Avatar
/imagingproxy — separate track.
Success criteria (Phase 1)
- No double hub+page title on representative pages: Articles, Users directory, Events list, Logs index, Radio overview.
- Orphan routes listed above reachable from tabs.
- Desktop: single theme/language control location.
- Radio primary tabs visible without scrolling on 1280px width.
- Moderation and Access icons differ.
Approval
- Phase 1 approach approved in conversation (2026-07-17).
- Implementation proceeds via a Phase-1 plan under
docs/superpowers/plans/.