Files
design-system/docs/superpowers/specs/2026-03-18-admin-redesign.md

208 lines
8.1 KiB
Markdown
Raw Normal View History

# Admin Section Redesign Spec
**Date:** 2026-03-18
**Scope:** UX/UI consistency overhaul of AuditLog, OidcConfig, UserManagement admin pages
## Overview
Three expert reviews identified critical bugs, consistency gaps, and usability issues in the admin section. This spec covers all changes organized by priority tier.
---
## Tier 1: Critical Bugs
### 1.1 Replace nonexistent `--bg-base` token
`--bg-base` is referenced 3 times but does not exist in `tokens.css`. Dark mode is broken.
**Files:**
- `Admin.module.css` line 6: `.adminNav`
- `UserManagement.module.css` lines 13, 19: `.listPane`, `.detailPane`
**Fix:** Replace all `var(--bg-base)` with `var(--bg-surface)`.
### 1.2 Change AuditEvent `id` to string
`DataTable` requires `T extends { id: string }`. Current `AuditEvent.id` is `number`.
**Files:**
- `auditMocks.ts`: change `id: number` to `id: string`, update all IDs to `'audit-1'`, `'audit-2'`, etc.
- `AuditLog.tsx`: update `expandedId` state from `number | null` to `string | null`
---
## Tier 2: High-Impact Consistency
### 2.1 Replace admin nav with Tabs composite
The hand-rolled admin nav in `Admin.tsx` lacks ARIA roles and has subtle color differences from the Tabs composite.
**Fix:** Replace the custom `<nav>` block with:
```tsx
<Tabs
tabs={[
{ label: 'User Management', value: '/admin/rbac' },
{ label: 'Audit Log', value: '/admin/audit' },
{ label: 'OIDC', value: '/admin/oidc' },
]}
active={location.pathname}
onChange={(path) => navigate(path)}
/>
```
Delete `.adminNav`, `.adminTab`, `.adminTabActive` from `Admin.module.css`.
### 2.2 Remove duplicate page titles
Breadcrumb + active tab + h2 heading all show the same label. Remove the h2.
**Files:**
- `AuditLog.tsx`: remove the `.header` div with `<h2>Audit Log</h2>`. Move the event count badge into a toolbar row.
- `OidcConfig.tsx`: remove the `.header` div with `<h2>`. Keep Save/Test buttons in a compact toolbar row below the tabs.
Delete `.header`, `.title` CSS from both `AuditLog.module.css` and `OidcConfig.module.css`.
### 2.3 Migrate AuditLog to DataTable
Replace the hand-built `<table>` with the DataTable composite.
**Column definitions:**
- Timestamp: render with `MonoText`, width `'170px'`
- User: render with bold text
- Category: render with `Badge color="auto"`
- Action: plain text
- Target: render with ellipsis style
- Result: render with `Badge color={row.result === 'SUCCESS' ? 'success' : 'error'}`
**Features to enable:**
- `sortable` on Timestamp, User, Category, Result columns
- `rowAccent={(row) => row.result === 'FAILURE' ? 'error' : undefined}` — red left-border on failures
- `expandedContent={(row) => <detail block with IP, user agent, CodeBlock>}`
- `pageSize={10}`
- `flush` prop (table sits inside a card wrapper)
**Card wrapper:** Wrap DataTable in a section with `background: var(--bg-surface)`, `border: 1px solid var(--border-subtle)`, `border-radius: var(--radius-lg)`, `box-shadow: var(--shadow-card)`. Add a header row with title + event count badge, matching Dashboard's `.tableSection` pattern.
**Delete from AuditLog.module.css:** `.tableWrap`, `.table`, `.th`, `.row`, `.td`, `.userCell`, `.target`, `.empty`, `.detailRow`, `.detailCell`, `.detailGrid`, `.detailField`, `.detailLabel`, `.detailValue`, `.detailJson`. Also remove the separate `Pagination` import — DataTable handles pagination internally.
### 2.4 Fix content padding
`Admin.module.css` `.adminContent`: change `padding: 20px` to `padding: 20px 24px 40px`.
### 2.5 Center OIDC form
`OidcConfig.module.css` `.page`: add `margin: 0 auto` to center the 640px max-width form.
### 2.6 Replace inline style
`UserManagement.tsx` line 20: replace `style={{ marginTop: 16 }}` with a CSS class `.tabContent { margin-top: 16px; }` in `UserManagement.module.css`.
---
## Tier 3: Usability Improvements
### 3.1 Add toast notifications to RBAC mutations
Import `useToast` into `UsersTab.tsx`, `GroupsTab.tsx`, `RolesTab.tsx`. Fire toasts on:
- Create user/group/role: `variant: 'success'`
- Delete user/group/role: `variant: 'warning'`
- Role assigned/removed: `variant: 'success'`
- Group added/removed: `variant: 'success'`
### 3.2 Rework user creation form
Replace the flat inline form with a provider-aware two-step form.
**Form structure:**
1. **Provider selection** — RadioGroup with "Local" and "OIDC" options. Default: "Local".
2. **Fields (always shown):** Username (required), Display name (optional), Email (optional)
3. **Fields (Local only):** Password (required)
4. **OIDC info callout:** When OIDC selected, show an InfoCallout: "OIDC users authenticate via the configured identity provider. Pre-register to assign roles/groups before their first login."
**Components used:** RadioGroup + RadioItem (existing primitive), Input, InfoCallout (existing primitive), Button.
**Create handler:** Set `provider` based on RadioGroup selection. Only validate password when provider is 'local'.
The form should use the existing inline pattern (appears at the top of the list pane), but use a proper card-like treatment (the existing `.createForm` background is fine).
### 3.3 Add password management to user detail pane
Add a "Security" section (using `SectionHeader`) in the user detail pane, below the metadata grid.
**For local users:**
- Show "Password: ••••••••" with a "Reset password" Button
- Clicking "Reset password" reveals an inline form: Input (type=password, placeholder "New password") + Cancel/Set buttons
- Setting fires a success toast: "Password updated"
**For OIDC users:**
- Show "Authentication: OIDC ({provider})"
- Show InfoCallout: "Password managed by the identity provider."
- No password reset option
### 3.4 Add ConfirmDialog to cascading removals
When removing a group from a user (which may strip inherited roles), show a confirmation dialog if the group grants roles.
When removing a role from a group (which affects all members), show a confirmation dialog.
Direct role removal from a user does not need confirmation (low risk).
### 3.5 Make entity list items keyboard accessible
Add to each `.entityItem` div:
- `role="option"`
- `tabIndex={0}`
- `aria-selected={selectedId === item.id}`
- `onKeyDown`: Enter/Space to select, ArrowUp/ArrowDown to navigate
Add `role="listbox"` and `aria-label` to each `.entityList` container.
### 3.6 Add expand/collapse affordance to AuditLog
After DataTable migration (2.3), add a first column with a chevron indicator (`>` / `v`) that rotates when the row is expanded. Width: `'40px'`. This makes the expandable row pattern discoverable.
### 3.7 Add duplicate name validation
Before creating, check for existing names:
- Users: `users.some(u => u.username === newUsername.trim())`
- Groups: `groups.some(g => g.name.toLowerCase() === newName.trim().toLowerCase())`
- Roles: `roles.some(r => r.name === newName.trim().toUpperCase())`
Show inline error using state + red text below the name field. Disable Create button.
### 3.8 Partial FilterBar migration for AuditLog
After DataTable migration, use FilterBar for search + category filters:
- Search input maps to FilterBar's built-in search
- Categories (INFRA, AUTH, USER_MGMT, CONFIG) become FilterPill toggles
- Keep DateRangePicker and user filter Input alongside FilterBar in a row
### 3.9 Add empty-search states to entity lists
When search returns no results in Users/Groups/Roles lists, show centered muted text: "No users match your search" (etc.) inside the `.entityList` area.
---
## Tier 4: Polish
### 4.1 Replace lock emoji with Badge
`RolesTab.tsx`: replace `🔒` with `<Badge label="system" color="auto" variant="outlined" />`.
### 4.2 Fix split-pane border radius
`UserManagement.module.css`: change `border-radius: var(--radius-md)` to `var(--radius-lg)` on `.splitPane`, `.listPane`, `.detailPane`.
### 4.3 Add shadow to split-pane
`UserManagement.module.css`: add `box-shadow: var(--shadow-card)` to `.splitPane`.
---
## Out of Scope
- Replacing split-pane with DataTable+DetailPanel (not appropriate for dense editing)
- EventFeed as alternative audit view (future enhancement)
- Tabs inside user detail pane (not needed until more sections are added)
- FilterBar extension to support DateRangePicker slots (separate design system ticket)