Admin Console Premium UX
At a glance
Admin console lifted from internal tooling to Linear/Vercel/Stripe-grade UX: 14 sections consolidated into 6 navigation groups, shared design system, four top-level admin views, ⌘K command palette, breadcrumbs, keyboard shortcuts, role-filtered menus, dual-mode mobile/desktop shell, tenant-branded theming and a guided five-step onboarding tour.
How it works
The information architecture collapses 14 disconnected sections into 6 deliberate groups — Overview, Organisation, Activity, Finance, Commercial, Platform — in admin/src/navigation/sections.ts. "Coming soon" entries are gone; everything in the menu is something the operator can actually do. The design system lives in packages/shared/src/design/native (bottle-green and ivory tokens) and bridges into the admin via admin/src/theme/tokens.ts under a ThemeContext supporting light and dark modes.
A shared component library — DataTable, FormField + FormSection, Breadcrumbs, CommandPalette, KeyboardShortcutsOverlay, OnboardingBanner — replaces the previous one-off UI work. The dashboard at admin/app/(dashboard)/index.tsx greets the user, surfaces the onboarding banner when relevant, exposes three quick actions and four KPI cards, and renders an activity feed pulled from the audit log (last 20 entries from GET /audit-log?limit=20 with relative timestamps and domain icons, with EmptyState/Banner fallbacks). Four flagship views (Federations, Licenses, Governance, Discipline) and a separate audit-log route set the pattern for the wider 200+-view sweep.
The ⌘K command palette is a global search over navigation and tenant switching with the same visibility rules as the sidebar. Breadcrumbs root every detail view back to its section. Keyboard shortcuts open the cheat-sheet (?), close overlays (Esc) and open the palette (⌘K / Ctrl+K), with input-typing suppression. Menu visibility filters by role through NavItem.requiredTenantRoles plus a visibleSectionsFor() resolver that takes tenant type, platform-admin flag and active role; the same RBAC lens applies to sidebar, palette and bottom-tab bar.
useDeviceClass() flips between desktop sidebar and mobile bottom-tab + drawer at runtime without route-changes or data-remounts; the mobile bar exposes 5 slots (Overview / My org / Activity / Finance / More). Tenant branding flows through ThemeProvider — useTenantBranding() fetches /tenants/{id}/branding on tenant switch, applyTenantBranding mixes the primary colour into WCAG-aware hover/text/focus variants and broadcasts --pl-tenant-primary as a CSS var. A lightweight UX telemetry buffer tracks route-views/actions in a 200-event ringbuffer with localStorage opt-out. A guided five-step onboarding tour (tenant-config → first license → first member → first competition → first invoice) with dismiss/later semantics, mirrored by a dashboard checklist widget that disappears on completion.
Key capabilities
- IA consolidation from 14 sections to 6 groups (Overview, Organisation, Activity, Finance, Commercial, Platform)
- Shared design system with bottle-green/ivory tokens and ThemeContext (light/dark)
- Component library: DataTable, FormField + FormSection, Breadcrumbs, CommandPalette, KeyboardShortcutsOverlay
- ⌘K / Ctrl+K command palette over navigation and tenant switching with RBAC visibility
- Keyboard shortcuts (?, Esc, ⌘K) with input-typing suppression and global cheat-sheet
- Role-based menu filtering through NavItem.requiredTenantRoles and visibleSectionsFor()
- Dual-mode shell flipping between desktop sidebar and mobile bottom-tab + drawer via useDeviceClass()
- Tenant branding injected through ThemeProvider with WCAG-aware colour variants and CSS var broadcast
- Activity feed bound to audit-log stream with EmptyState/Banner fallbacks
- Five-step guided onboarding tour with dashboard checklist widget and per-tenant progress
In practice
A non-technical club secretary opens the admin app for the first time on her laptop. The dashboard greets her by name with a five-step onboarding banner; she works through tenant-config in step one and the checklist widget on the home screen ticks the first box. She hits ⌘K, types "new license", and the palette deep-links her to the license-issue view — exactly the same path the sidebar would have taken her.
She switches to her phone on the bus the next morning; the bottom-tab shell reorganises around five slots and the same command palette is one tap away. By Friday she has all five steps green, the onboarding tour dismisses itself, the checklist widget disappears and the dashboard surfaces an activity feed of every action she has taken — pulled live from the audit log under her tenant.
Features in this subsystem
20| ID | Status | Features |
|---|---|---|
| F16.20.01 | Shipped | Informationsarkitektur — 14 sektioner konsoliderade till 6 grupper (Översikt, Organisation, Aktivitet, Ekonomi, Kommersiellt, Plattform) i admin/src/navigation/sections.ts. "Coming soon" borttaget. ✅ PL-T099 |
| F16.20.02 | Shipped | Designsystem — tokens i packages/shared/src/design/native (bottle-green/ivory), admin-bridge admin/src/theme/tokens.ts, ThemeContext med light/dark. ✅ PL-T099 |
| F16.20.03 | Shipped | Komponentbibliotek — DataTable, FormField + FormSection, Breadcrumbs, CommandPalette, KeyboardShortcutsOverlay, OnboardingBanner som delade primitiver. ✅ PL-T099 |
| F16.20.04 | Shipped | Dashboard-startsida — hälsning, onboarding-banner, 3 snabbåtgärder, 4 KPI-kort, aktivitetsflöde-placeholder. admin/app/(dashboard)/index.tsx. ✅ PL-T099 |
| F16.20.05 | Shipped | Fyra top-level admin-vyer — Federations, Licenses, Governance, Discipline. Audit-logg bruten ut till egen route. Se specs/admin/views/. ✅ PL-T099 |
| F16.20.06 | Shipped | Kommandopalett (⌘K / Ctrl+K) — global sök över nav-items och tenant-switch. Samma synlighetsregler som sidomenyn. ✅ PL-T099 |
| F16.20.07 | Shipped | Brödsmulor — Breadcrumbs-primitiv mountad i governance, federations, audit, discipline. Sista item inert, tidigare router-länkade. ✅ PL-T099 |
| F16.20.08 | Shipped | Keyboard shortcuts — ? öppnar cheat-sheet (KeyboardShortcutsOverlay), Esc stänger, Meta+K / Ctrl+K öppnar paletten. Input-typing-suppress. ✅ PL-T099 |
| F16.20.09 | Shipped | Rollbaserad menyfiltrering — NavItem.requiredTenantRoles: TenantRole[], visibleSectionsFor(tt, isPlatformAdmin, activeRole). RBAC-lins på nav, applicerad på sidomeny + palett. ✅ PL-T099 |
| F16.20.10 | Shipped | UX-telemetri — lättviktig buffer i admin/src/lib/telemetry.ts med trackRouteView / trackRouteAction, 200-event ringbuffer, opt-out via localStorage. ✅ PL-T099 |
| F16.20.11 | Shipped | UserDashboardPreferences-endpoint-spec — /me/dashboard-preferences GET/PUT/reset, tenant-scoped, upsert-on-read. Backend-implementation deferrad. ✅ PL-T099 (spec) |
| F16.20.12 | Shipped | Widget drag-and-drop med persistens mot /me/dashboard-preferences. Backend-endpoint + frontend-binding via DraggableDashboardGrid (keyboard-first WCAG 2.1.1 AA, HTML5 drag-events på web). 500 ms debounced PUT, optimistisk UI med rollback vid 5xx, "Lägg till widget"-meny + "Nollställ layout"-knapp. Tillämpad på både admin- och sys-konsolens dashboards. ✅ PL-T290 |
| F16.20.13 | Shipped | Aktivitetsflöde kopplat till audit-stream — senaste 20 entries från GET /audit-log?limit=20 med relativ tid, domän-ikon och EmptyState/Banner-fallbacks. admin/app/(dashboard)/index.tsx. ✅ PL-T156 |
| F16.20.14 | Shipped | UX-validerings-pipeline för admin-konsolen — testprotokoll i docs/product/admin/usability-test-protocol.md (5 deltagare × 5 kärnuppgifter, SUS-mätning, severity-klassad friktion), avpersonifierad rapport-mall i usability-test-2026-h1.md; Lighthouse-runner tools/lighthouse/run-admin-routes.sh (12 routes × mobile+desktop) + compare-baselines.mjs med absolut floor 90 och regression-tröskel 5 poäng (routes.json); CI-workflow admin-lighthouse.yml (PR + nightly mot prod, PR-kommentar med summary-tabell); admin-baseline visual regression (tools/visual-regression/tests/admin-baseline.spec.ts, 12 routes × {375,1440} × {light,dark} = 48 PNG i Chromium) med dedikerat workflow admin-visual-regression.yml + [accept admin baseline]-marker; budget-doc i docs/engineering/testing/lighthouse-budget.md. Modererat användartest mot 5 icke-tekniska klubbadmins är OWNER-todo (kräver rekrytering + Zoom-sessioner). ✅ PL-T291 |
| F16.20.15 | Shipped | Dual-mode admin-shell — useDeviceClass() växlar mellan desktop-sidebar och mobile bottom-tab + drawer utan route-byte eller data-remount. 5 bottom-tab-slottar (Översikt / Min org / Aktivitet / Ekonomi / Mer). admin/app/(dashboard)/_layout.tsx, admin/src/components/ui/BottomTabNav.tsx. ✅ PL-T156 |
| F16.20.16 | Shipped | Design-system-primitives i admin — Text (Fraunces display + Inter UI via Google Fonts på web), SkeletonBlock, Banner, EmptyState i admin/src/components/ui/. Dashboard-vyn är referensimplementation; breddare sweep över 200+ vyer pågår i owner-todo. ✅ PL-T156 |
| F16.20.17 | Shipped | Tenant-branding injicerad i ThemeProvider — useTenantBranding() hämtar /tenants/{id}/branding vid tenant-byte, ThemeProvider.applyTenantBranding blandar primary-färg med WCAG-aware hover/text/focus-varianter. CSS-var --pl-tenant-primary broadcastas för externa widgets. Dark mode respekterar tenant-primary. admin/src/context/ThemeContext.tsx, admin/src/hooks/useTenantBranding.ts. ✅ PL-T156 |
| F16.20.18 | Shipped | Guided 5-stegs onboarding-tour för tenant-admins — tenant-config → första licens → första medlem → första tävling → första faktura. Dismiss/later + per-tenant-progress i cross-platform storage. Migrerar till UserDashboardPreferences.onboarding_progress när endpointen landar. admin/src/components/OnboardingTour.tsx. ✅ PL-T156 |
| F16.20.19 | Shipped | Onboarding-checklist-widget på dashboard-startsidan — renderar wizard-progressionen (6 steg från /onboarding/status), försvinner när wizard + tour är klara, primary-branded CTA som deep-länkar till wizarden. ✅ PL-T156 |
| F16.20.20 | Shipped | Command palette tillgänglig på mobil — search-ikon i topbaren öppnar samma <CommandPalette> som desktop (⌘K). Modal-layouten skalar till viewport utan separat mobil-komponent. ✅ PL-T156 |