7.0 KiB
phase, plan, subsystem, tags, dependency_graph, tech_stack, key_files, decisions, metrics, status
| phase | plan | subsystem | tags | dependency_graph | tech_stack | key_files | decisions | metrics | status | |||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 17-ui-optimization-polish | 06 | pwa-admin |
|
|
|
|
|
|
complete |
Phase 17 Plan 06: Admin Polish — Toasts, Two-Tab Nav, Reset-Sheet Centering Summary
One-liner: Admin UX polish with success toasts (D-08), two-tab ARIA strip wrapping existing sections (D-10), desktop-centered reset-password sheet (D-09 admin slice), and admin.spec.ts tab ARIA + keyboard assertions (Wave 0 requirement).
Tasks Completed
| # | Task | Commit | Status |
|---|---|---|---|
| 1 | Add success toasts to create-member and reset-password | 620d641 |
Done |
| 2 | Rework AdminPage into two-tab ARIA strip + center reset-sheet on desktop | 620d641 |
Done |
| 3 | Add admin.spec.ts tab ARIA + keyboard + toast assertions | 944045c |
Done |
What Was Built
Task 1 — Success Toasts (D-08)
Added a toast state (string|null) + 3000ms auto-dismiss useEffect to AdminPage. The phone boolean (window.matchMedia('(max-width: 767px)').matches) drives the bottom offset.
Hooks:
createMemberMutation.onSuccess→setToast('Member added.')ResetPasswordSheet.resetMutation.onSuccess→ callsonSuccess?.()callback prop →setToast('Password reset.')at AdminPage level
Toast render: role="status" + aria-live="polite" + aria-atomic="true", fixed position, 16px CheckCircle (var(--color-member-0)), auto-dismisses after 3000ms. Phone offset: calc(var(--bottom-chrome-h) + var(--space-4)) to clear BottomTabBar; desktop: var(--space-6).
Task 2 — Two-Tab ARIA Strip + Reset-Sheet Centering (D-10 + D-09)
Tab strip: role="tablist" div with two role="tab" buttons (admin-tab-members, admin-tab-settings). Roving tabindex (active: 0, inactive: -1). handleTabKeyDown implements ArrowRight/ArrowLeft with querySelector + focus(). Active tab: fontWeight 600 + borderBottom: 2px solid var(--color-member-0).
Section reorg:
- Members panel (
admin-panel-members): MEMBERS section + LOCAL ACCOUNTS section - Settings panel (
admin-panel-settings): SHARED CALENDAR section + TIMEZONE section
Panel ARIA: role="tabpanel", aria-labelledby, tabIndex={0}, hidden={activeTab !== id}.
Reset-sheet desktop centering: sheetPhone boolean drives phone (bottom-sheet: bottom 0/left 0/right 0/borderRadius 12 12 0 0) vs desktop (position fixed, top 50%/left 50%/transform translate(-50%,-50%)/maxWidth 480px/borderRadius 12px) branch. role="dialog" + aria-modal="true" + aria-label unchanged.
Task 3 — admin.spec.ts ARIA + Keyboard Assertions
Extended apps/pwa/e2e/admin.spec.ts with two new test.describe blocks:
Admin two-tab ARIA strip (D-10) (5 tests):
- tablist + both named tabs visible
- Members & Accounts tab is selected by default (aria-selected=true)
- ArrowRight switches to Settings tab (aria-selected=true)
- ArrowLeft returns to Members & Accounts tab
- Both panels have correct
aria-labelledby; phone overflow check
Admin success toast structure (D-08) (1 test):
role="status"not present on initial load (toast is null)
Playwright run result: 12/12 tests pass on pixel profile.
Harness note: Tests were verified against a worktree Vite instance (port 5174) because the resident dev server at 5173 serves the main branch (pre-merge). The CI harness at merge time will use the merged code. Verified via PLAYWRIGHT_BASE_URL=http://localhost:5174.
Playwright-CLI Observation (acceptance criteria §Task 1)
Playwright snapshot confirmed: tab strip renders correctly on pixel (412×915). Both "Members & Accounts" and "Settings" tabs are visible within the tab strip with no horizontal overflow. ArrowRight correctly moves aria-selected to the Settings tab. Toast role="status" is absent on initial page load as expected.
Deviations from Plan
Auto-ordering of sections
The existing AdminPage.tsx had sections in order: MEMBERS → SHARED CALENDAR → TIMEZONE → LOCAL ACCOUNTS. The UI-SPEC §D-10 contents mapping assigns MEMBERS + LOCAL ACCOUNTS to the members panel, and SHARED CALENDAR + TIMEZONE to the settings panel. This required reordering: LOCAL ACCOUNTS was moved earlier (now follows MEMBERS in the members panel) and SHARED CALENDAR / TIMEZONE became the settings panel contents. This is a presentation change only — no mutation logic was touched.
Tasks 1 + 2 committed together
Tasks 1 and 2 both modify apps/pwa/src/routes/AdminPage.tsx. Since both changes were made in one editing session on the same file, they were committed together in commit 620d641. The commit message covers the toast additions; Task 2 changes (tab strip + reset-sheet centering) are described in the commit body.
Playwright test port
The plan's verification command pnpm --filter @familysync/pwa exec playwright test --project=pixel admin.spec.ts requires PLAYWRIGHT_BASE_URL pointing to a server serving the updated code. The resident dev server at port 5173 serves the main branch. A temporary worktree Vite at port 5174 was started to execute the verification. 12/12 tests passed. CI will run against merged code where this is a non-issue.
Known Stubs
None. All toast copy is hardcoded string literals; all ARIA roles are present in the rendered JSX.
Threat Flags
None. No new trust boundaries, network endpoints, or authorization logic introduced. Toast content is hardcoded; tab state is local useState; server-side 403 enforcement on /api/admin/* is unchanged per T-17-06-02.
Self-Check: PASSED
| Item | Result |
|---|---|
| 17-06-SUMMARY.md | FOUND |
| apps/pwa/src/routes/AdminPage.tsx | FOUND |
| apps/pwa/e2e/admin.spec.ts | FOUND |
Commit 620d641 (toasts + two-tab nav) |
FOUND |
Commit 944045c (admin.spec.ts) |
FOUND |