chore(loop): iOS HIG compliance plan — 24 tasks across 7 phases

Font sizes (text-[10px]→text-xs, text-[8-9px]→text-[11px]),
touch targets (44×44px minimum for all buttons), input zoom
prevention (16px minimum), gap compliance (8px between targets),
glass button system updates, and comprehensive verification.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-04 12:43:44 +00:00
co-authored by Claude Opus 4.6
parent bda670d8d9
commit dde3859a2e
2 changed files with 124 additions and 81 deletions
+71 -52
View File
@@ -1,83 +1,102 @@
You are hardening the AIUI content extraction pipeline, integrating Archy services, and completing incomplete features. Read these files first:
You are making the AIUI app compliant with iOS Human Interface Guidelines (HIG) for font sizes, touch targets, and button hitboxes — WITHOUT changing the visual design. Read these files first:
1. `loop/plan.md` — Your task checklist (mark items `- [x]` as you complete them)
2. `CLAUDE.md` — Project conventions, design system rules, and coding standards
## Key Context
## Key Principle
### Content Extraction Pipeline
- `packages/app/src/composables/contentExtraction.ts` — Extracts books, films, TV, songs, podcasts, places, images, code blocks, apps from AI response text
- `packages/app/src/composables/contentFiltering.ts` — Query/response classifiers (isBookQuery, isTVQuery, etc.) and tab routing (filterTabsByContext)
- `packages/app/src/composables/useContentPanel.ts` — Wires extraction functions to Vue reactive state and tab system
- `packages/app/src/components/content/ContentPanel.vue` — Main content panel rendering grids and detail views
- `packages/app/src/components/content/ContentGridView.vue` — Grid view (already has ImageGrid/PlaceGrid wired)
- `packages/app/src/__tests__/extractionQuality.test.ts` — Extraction quality test suite (currently 64 tests)
**Same design, better accessibility.** The app should look identical but be properly tappable and readable on mobile. All changes are about sizing minimums, not visual redesign.
Content flows: AI response text → extraction functions → useContentPanel refs → filterTabsByContext → ContentPanel/ContentGridView rendering
## iOS HIG Requirements
### Archy Integration (CRITICAL — this is the main new work)
- `packages/app/src/services/archyBridge.ts` — PostMessage client for AIUI ↔ Archipelago IPC (already implemented)
- `packages/app/src/composables/useArchy.ts` — Reactive Vue wrapper (just created, needs extension)
- `packages/app/src/composables/useAI.ts` — Already injects Archy context via `buildArchyContext()` in `buildSystemPrompt()`
1. **Font Sizes:**
- Body text: 17px (but we use 14px base — OK, it's a dense app)
- Footnote: 13px minimum
- Caption: 11px ABSOLUTE minimum (nothing smaller than 11px ever)
- Form inputs: 16px minimum (prevents iOS auto-zoom on focus)
Archy is a self-hosted Linux node OS with 23+ apps. AIUI runs as an iframe inside Archy at `/aiui/`. Communication is via postMessage with 5 context categories: apps, system, network, wallet, files. The bridge is initialized when `?embedded=true` is in the URL.
2. **Touch Targets:**
- All interactive elements: 44×44px minimum tappable area
- The VISUAL icon can be smaller (e.g., 20px SVG), but the tappable wrapper must be 44×44px
- Pattern: `<button class="min-w-[44px] min-h-[44px] flex items-center justify-center"><svg class="w-5 h-5" ...></button>`
**Archy Services Available** (that AIUI should know about):
- Bitcoin Core (blockchain data, UTXO, fee estimates)
- LND / Core Lightning / Lightning Stack (channels, payments, invoices)
- BTCPay Server (payment processing)
- Mempool (blockchain explorer)
- Nextcloud (files, notes, contacts, calendar via WebDAV)
- Immich (photos, ML-tagging)
- Nostr relays (nostr-rs-relay, strfry)
- Home Assistant (smart home)
- Grafana (monitoring)
- SearXNG (privacy search)
- Ollama (local LLM)
- Penpot (design)
- OnlyOffice (documents)
- Fedimint (federated custody)
- Meshtastic (mesh networking)
- DID Wallet (Web5 identity)
3. **Gaps Between Targets:**
- Minimum 8px (gap-2) between any two tappable elements
- `gap-0.5` (2px) and `gap-1` (4px) between buttons is a violation
**Data Handshake**: AIUI requests context via `archyBridge.requestContext(category)`. Archy's contextBroker responds with sanitized data (no secrets, no IPs, no keys). Currently `wallet` and `files` categories are stubs in Archy — build the AIUI consumer side anyway so it's ready when Archy implements them. Use realistic mock shapes.
## Current Violations Found (from audit)
**API Path Note**: All API paths use `import.meta.env.BASE_URL` prefix so they work at both `/` (dev) and `/aiui/` (production). This was just implemented — don't change it.
- **301× `text-[10px]`** — timestamps, labels, metadata throughout app
- **76× `text-[11px]`** — settings, branch switcher, design system
- **100× `text-[9px]` / `text-[8px]`** — badges, version numbers, plugin metadata
- **40+ buttons below 44×44px** — `w-7 h-7` (28px), `w-8 h-8` (32px), `w-6 h-6` (24px), `w-5 h-5` (20px)
- **20+ locations with gap < 8px** between clickable elements
- **9+ inputs below 16px** — ChatInput textarea, settings inputs, search
## Key Files
- `packages/app/src/styles/main.css` — Glass button system, utility classes
- `packages/app/src/components/chat/ChatMessage.vue` — Message actions, timestamps
- `packages/app/src/components/chat/ChatInput.vue` — Main input, send button
- `packages/app/src/components/chat/ChatHeader.vue` — Toolbar buttons
- `packages/app/src/components/chat/ChatSearch.vue` — Search nav buttons
- `packages/app/src/components/chat/SettingsModal.vue` — Settings UI
- `packages/app/src/components/content/ContentPanel.vue` — Tab bar
- `packages/app/src/components/content/*Grid.vue` — All content grids
- `packages/app/src/components/content/*Detail.vue` — All detail views
- `packages/app/src/components/settings/` — Settings components
- `packages/app/src/components/ui/` — Shared UI components
## Design System Rules (must follow for every file you touch)
- **Glass morphism only** — use `.glass`, `.glass-card`, `.glass-button`, `.glass-button-sm` from `src/styles/main.css`
- **No light-mode conditionals** — never use `isDark ?` pattern. The app is dark-only. Remove any existing light-mode code you encounter.
- **No light-mode conditionals** — never use `isDark ?` pattern. The app is dark-only.
- **No `bg-gray-*` or `bg-white`** — use `bg-white/5`, `bg-white/10`, `bg-black/35` etc.
- **Text opacity scale** — `text-white/25``/40``/60``/70``/80``/90``/96``text-white`
- **Accent colour** — `text-accent` (`#F7931A`), `bg-accent/15`, `border-accent/30` for Bitcoin-orange highlights
- **Touch targets** — min 44×44px, 8px gaps between targets
- **Font size** — min `16px` on all inputs (prevents iOS zoom)
- **Accent colour** — `text-accent` (`#F7931A`), `bg-accent/15`, `border-accent/30`
- **Animations** — `animate-scale-in`, `animate-fade-up`, `animate-fade-in` from design system only
## How to Fix Touch Targets (Pattern)
**Before (violation):**
```html
<button class="w-7 h-7 rounded-full" @click="doThing">
<svg class="w-4 h-4" ...></svg>
</button>
```
**After (compliant):**
```html
<button class="min-w-[44px] min-h-[44px] flex items-center justify-center rounded-full" @click="doThing">
<svg class="w-4 h-4" ...></svg>
</button>
```
Or use the utility class (after T19):
```html
<button class="touch-target rounded-full" @click="doThing">
<svg class="w-4 h-4" ...></svg>
</button>
```
## For each task in loop/plan.md:
1. Find the first unchecked `- [ ]` item
2. Read the task description carefully
3. Read the relevant source files before making changes
4. Implement the feature/fix following conventions and design system rules
5. Run `pnpm typecheck && pnpm lint` — fix all errors before committing
4. Make the change — keep visual design identical, only adjust sizing
5. Run `pnpm typecheck && pnpm lint` — fix all errors
6. Run `pnpm test` — fix any failing tests
7. If the task involves tests, run `cd packages/app && npx vitest run` specifically
8. Commit: `type(scope): description` (conventional commits)
9. Mark it done `- [x]` in `loop/plan.md`
10. Move to the next unchecked task immediately
7. Commit: `type(scope): description` (conventional commits)
8. Mark it done `- [x]` in `loop/plan.md`
9. Move to the next unchecked task immediately
## Rules
- Never skip a testing gate — if tests fail, fix them before moving on
- If a task is proving difficult, keep trying different approaches. Make at least 30 genuine attempts before giving up and moving on.
- If a task is proving difficult, keep trying different approaches. Make at least 30 genuine attempts.
- Always run typecheck + lint after every code change
- Keep initial bundle < 250 KB gzipped — lazy-load anything heavy
- Bitcoin only — never altcoins, never fiat payment flows
- Privacy first — no external analytics calls, no telemetry
- The visual design must NOT change — same colors, same layout, same glass morphism
- Only sizes of tappable areas, font minimums, and gaps change
- Do not stop until all tasks are checked or you are rate limited
- When adding tests, aim for realistic AI response patterns, not trivial examples
- When wiring components into ContentPanel.vue, follow the exact same pattern used for existing content types (BookGrid/BookDetail, TVSeriesGrid/TVSeriesDetail, etc.)
- When building Archy integration, the AIUI side should be resilient — always handle the case where Archy doesn't respond or data is empty
- Commit and push after each completed phase (TEST: tasks)
- Commit and push after each TEST: task