diff --git a/docs/ux-audit-2026-03.md b/docs/ux-audit-2026-03.md new file mode 100644 index 00000000..28ad759a --- /dev/null +++ b/docs/ux-audit-2026-03.md @@ -0,0 +1,159 @@ +# UX Audit Report - Archipelago Web UI + +**Date**: 2026-03-11 +**Scope**: All 12 pages (login, home, apps, marketplace, cloud, server, web5, settings, chat, federation, credentials, system update) +**Method**: Screenshot review + source code analysis + +## Summary + +| Priority | Count | Description | +|----------|-------|-------------| +| **P0** | 3 | Apps empty state never renders; Credentials API parse error; Persistent unhealthy banners | +| **P1** | 13 | Dead links, no-op buttons, hardcoded fake data, missing error feedback, silent failures | +| **P2** | 14 | Inconsistent patterns, visual polish, native dialogs, loading states | + +--- + +## P0 - Broken Functionality + +### Apps: Empty state hardcoded to never display +- **File**: `Apps.vue:19` — `v-if="false"` means the "No Apps Installed" empty state can never render +- **Fix**: Change to `v-if="sortedPackageEntries.length === 0 && !searchQuery"` + +### Credentials: API parse error on page load +- **File**: `Credentials.vue` — screenshot shows "Failed to load credentials: Parsing credentials" red error +- **Fix**: Debug `identity.list-credentials` RPC response format; handle all response shapes gracefully + +### Cross-page: Persistent "tor is unhealthy" banners stack in top-right +- Every dashboard page shows 3-4 stacked red notification banners that never clear +- **Fix**: Auto-dismiss when service recovers, or make dismissible; don't stack duplicates + +--- + +## P1 - Confusing UX + +### Login: "Forgot password?" link is dead (`href="#"`) +- **File**: `Login.vue:178` +- **Fix**: Remove link or show help message (password reset requires SSH/re-image) + +### Login: No minimum password length feedback during setup +- **File**: `Login.vue:80` — button disabled check doesn't include length >= 8 +- **Fix**: Add reactive validation message and include length check in `:disabled` + +### Home: Web5 card values are hardcoded (fake data) +- **File**: `Home.vue:244-259` — DID "Active", DWN "Synced", Profits "0.024" are static +- **Fix**: Fetch from RPC or show "--" / "Loading..." + +### Home: No loading state for Network/Web5 cards +- **File**: `Home.vue` — Network and Web5 cards show static content immediately +- **Fix**: Add skeleton placeholders consistent with Cloud card pattern + +### Home: Refresh buttons on Network/Web5 cards are no-ops +- **File**: `Home.vue:208,266` — `@click="() => {}"` +- **Fix**: Wire to reload data or remove the buttons + +### Apps: Start/stop errors only logged to console +- **File**: `Apps.vue:344,360` +- **Fix**: Add toast notification on failure + +### Server: "Manage Local Network" and "Manage Web3 Services" buttons are no-ops +- **File**: `Server.vue:223,284` — no `@click` handler +- **Fix**: Wire to route/modal or disable with "Coming Soon" tooltip + +### Server: "View" logs button clears count but shows nothing +- **File**: `Server.vue:766-768` — just resets counter +- **Fix**: Navigate to logs view or show "Coming soon" message + +### Server: WiFi connection failure silently swallowed +- **File**: `Server.vue:668` +- **Fix**: Show error message in WiFi modal + +### Server: DNS configuration error silently swallowed +- **File**: `Server.vue:622` +- **Fix**: Show error message in DNS modal + +### Chat: No close/back button on mobile +- **File**: `Chat.vue:4` — `hidden md:flex` hides close button +- **Fix**: Add mobile-specific back button + +### Federation: Error display at bottom of template, easily missed +- **File**: `Federation.vue:292-295` +- **Fix**: Move error display above "Federated Nodes" section + +### Federation: "Remove from Federation" has no confirmation +- **File**: `Federation.vue:243` — destructive action, no confirm dialog +- **Fix**: Add confirmation step before removing node + +--- + +## P2 - Minor Polish + +### Login: Duplicate `id="password"` across setup/login templates +- **File**: `Login.vue:52,150` +- **Fix**: Use distinct IDs (`setup-password`, `login-password`) + +### Home: System stats show 0 until first RPC response +- **File**: `Home.vue:297-323` +- **Fix**: Show skeleton/placeholder bars instead of zero values + +### Marketplace: Category tabs hidden on mobile +- **File**: `Marketplace.vue:112` — `hidden md:flex` +- **Fix**: Add horizontal scrollable tabs or dropdown for mobile + +### Marketplace: Bottom row of apps may be cut off +- **Fix**: Add `pb-24` bottom padding to scrollable container + +### Cloud: No loading state while file counts fetch +- **Fix**: Add loading skeleton to item count areas + +### Web5: Quick actions grid wraps asymmetrically at lg breakpoint +- **File**: `Web5.vue:11` — 5 items in 3-column grid +- **Fix**: Use `lg:grid-cols-5` or restructure for balanced layout + +### Settings: DID string has no copy button +- **File**: `Settings.vue:63` — Tor address has copy button, DID doesn't +- **Fix**: Add copy button matching Tor address pattern + +### Settings: Onion address may overflow on mobile +- **File**: `Settings.vue:87` +- **Fix**: Add `truncate` with title tooltip + +### Chat: Fallback message exposes env variable name +- **File**: `Chat.vue:52` — shows `VITE_AIUI_URL` +- **Fix**: Reword to user-friendly message + +### Federation: Page header hidden on mobile with no alternative +- **File**: `Federation.vue:3` +- **Fix**: Verify mobile layout shell shows title + +### Credentials: Toast position overlapped by mobile tab bar +- **File**: `Credentials.vue:190` — `fixed bottom-6` +- **Fix**: Change to `bottom-20` to clear mobile tab bar + +### Credentials: Issue button has no validation feedback for empty fields +- **File**: `Credentials.vue:44` +- **Fix**: Add `:disabled` when required fields empty; add required indicators + +### SystemUpdate: Sequential await calls slow page load +- **File**: `SystemUpdate.vue:374-378` +- **Fix**: Use `Promise.all()` for concurrent fetching + +### SystemUpdate: `confirm()` for apply/rollback breaks glass UI +- **File**: `SystemUpdate.vue:316,334` +- **Fix**: Replace with glass-styled confirmation modals + +### Apps: Uninstall failure uses `alert()` +- **File**: `Apps.vue:396` +- **Fix**: Replace with inline error toast + +--- + +## Cross-Page Issues + +### Toast pattern inconsistent +- Credentials: custom inline toast. Settings: inline `
`. Apps: `alert()`. Server: swallows errors. +- **Fix**: Implement shared `useToast()` composable used consistently everywhere + +### Page headers inconsistently hidden on mobile +- Apps, Cloud, Server, Federation: `hidden md:block`. Home, Web5, Settings, Credentials, SystemUpdate: always visible. +- **Fix**: Standardize pattern across all pages diff --git a/loop/plan.md b/loop/plan.md index 7513ccd3..a7315083 100644 --- a/loop/plan.md +++ b/loop/plan.md @@ -310,7 +310,7 @@ #### Sprint 25: User Experience Polish (Week 1-4) -- [ ] **UXP-01** — Run complete UX audit. Use `/ux-review` skill on every page. Document all issues: inconsistent spacing, misaligned elements, broken mobile layouts, confusing flows. **Acceptance**: UX audit document with prioritized issues. +- [x] **UXP-01** — Run complete UX audit. Reviewed all 12 pages via Playwright screenshots + source code analysis. Found 30 issues: 3 P0 (Apps empty state hardcoded off, Credentials parse error, persistent unhealthy banners), 13 P1 (dead links, no-op buttons, fake data, silent failures, missing error feedback), 14 P2 (inconsistent patterns, native dialogs, loading states). Full report in `docs/ux-audit-2026-03.md`. - [ ] **UXP-02** — Fix all UX audit findings. Address every issue identified. Focus on: mobile responsiveness, keyboard navigation, loading states, error messages, empty states. No visual/animation changes. **Acceptance**: All audit items resolved.