---
phase: 11-visual-design-responsive-layout-cleanup
plan: 5
subsystem: frontend/visual-consistency
tags: [visual, typography, focus-visible, hover, active, skeleton, VISUAL-01, VISUAL-03, VISUAL-04]
dependency_graph:
  requires: [11-04]
  provides: [typography-normalized, focus-visible-rings, active-states, skeleton-class-widths]
  affects:
    - frontend/src/components/admin/AdminSidebar.vue
    - frontend/src/components/auth/BackupCodesDisplay.vue
    - frontend/src/components/cloud/CloudCredentialModal.vue
    - frontend/src/components/documents/DocumentCard.vue
    - frontend/src/components/layout/AppSidebar.vue
    - frontend/src/components/settings/SettingsAccountTab.vue
    - frontend/src/components/settings/SettingsAiTab.vue
    - frontend/src/components/settings/SettingsCloudTab.vue
    - frontend/src/components/settings/SettingsPreferencesTab.vue
    - frontend/src/components/storage/StorageBrowser.vue
    - frontend/src/components/topics/TopicManager.vue
    - frontend/src/views/DocumentView.vue
    - frontend/src/views/SettingsView.vue
    - frontend/src/views/SharedView.vue
    - frontend/src/views/TopicsView.vue
    - frontend/src/views/admin/AdminAiView.vue
    - frontend/src/views/admin/AdminAuditView.vue
    - frontend/src/views/admin/AdminOverviewView.vue
    - frontend/src/views/admin/AdminUsersView.vue
tech_stack:
  added: []
  patterns:
    - "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-1 — keyboard focus convention for all interactive elements"
    - "active:bg-{color}-{shade} — press feedback on all primary and secondary buttons"
    - "w-12/w-16/w-20 Tailwind classes instead of inline :style={{ width }} for skeleton placeholders"
    - "Typography scale: text-2xl font-semibold (page title), text-lg font-semibold (section title), text-sm font-semibold (panel heading)"
key_files:
  created:
    - frontend/src/components/layout/__tests__/AppSidebar.visual.test.js
    - frontend/src/views/__tests__/typography.visual.test.js
  modified:
    - frontend/src/components/admin/AdminSidebar.vue
    - frontend/src/components/auth/BackupCodesDisplay.vue
    - frontend/src/components/cloud/CloudCredentialModal.vue
    - frontend/src/components/documents/DocumentCard.vue
    - frontend/src/components/layout/AppSidebar.vue
    - frontend/src/components/settings/SettingsAccountTab.vue
    - frontend/src/components/settings/SettingsAiTab.vue
    - frontend/src/components/settings/SettingsCloudTab.vue
    - frontend/src/components/settings/SettingsPreferencesTab.vue
    - frontend/src/components/storage/StorageBrowser.vue
    - frontend/src/components/topics/TopicManager.vue
    - frontend/src/views/DocumentView.vue
    - frontend/src/views/SettingsView.vue
    - frontend/src/views/SharedView.vue
    - frontend/src/views/TopicsView.vue
    - frontend/src/views/admin/AdminAiView.vue
    - frontend/src/views/admin/AdminAuditView.vue
    - frontend/src/views/admin/AdminOverviewView.vue
    - frontend/src/views/admin/AdminUsersView.vue
decisions:
  - "Typography scale locked: text-2xl font-semibold for page titles, text-lg font-semibold for section card headings, text-sm font-semibold for panel/table headings"
  - "focus-visible: convention chosen over focus: on interactive buttons to avoid ring on mouse click — form inputs keep existing focus: pattern (appropriate for forms)"
  - "Stat number displays (AdminOverview cards, TopicsView doc count) keep font-bold — these are metric numerals, not headings"
  - "AuthLayout DocuVault brand name keeps text-xl font-semibold — branding element, not a page title"
  - "Sidebar nav-link scoped CSS updated in both AppSidebar and AdminSidebar to include active:bg-gray-200 and focus-visible ring as @apply directives"
metrics:
  duration_minutes: 10
  tasks_completed: 7
  files_created: 2
  files_modified: 19
  completed_date: "2026-06-16"
---

# Phase 11 Plan 5: Visual Consistency Pass Summary

Normalized typography to one consistent scale across all views and components, replaced generic `focus:ring-*` patterns with keyboard-only `focus-visible:` convention on all interactive buttons, added `active:bg-*` press feedback states, and converted decorative skeleton inline styles to static Tailwind width classes.

## What Was Built

### Task 1 — Preserve data-driven inline styles

Audited and confirmed the following inline styles are data-driven and preserved:
- `{ backgroundColor: topic.color }` — topic color swatches in TopicBadge, AppSidebar, TopicsView
- `{ width: pct + '%' }` — QuotaBar progress fill (runtime percentage)
- `pickerStyle` (top/left/bottom/width computed from getBoundingClientRect) — Teleport dropdown coordinates in StorageBrowser and DocumentCard
- Tree indentation via depth-computed padding in FolderTreeItem via TreeItem

### Task 2 — Remove decorative inline styles

Three sections in `AppSidebar.vue` used `:style="{ width: (50 + n * 15) + 'px' }"` for skeleton placeholder widths. Replaced all 9 instances (3 sections × 3 skeleton rows) with static Tailwind classes `w-12`, `w-16`, `w-20` (equivalent visual widths without runtime computation).

### Task 3 — Normalize typography

**Page titles (`text-2xl font-semibold`):**
- `TopicsView.vue`: `font-bold` → `font-semibold`
- `DocumentView.vue`: `font-bold` → `font-semibold`
- `SharedView.vue`: `font-bold` → `font-semibold`
- `AdminOverviewView.vue`: `text-xl` → `text-2xl font-semibold`

**Section titles (`text-lg font-semibold`):**
- `SettingsPreferencesTab.vue`: `text-xl` → `text-lg`
- `SettingsAiTab.vue`: `text-xl` → `text-lg`
- `SettingsCloudTab.vue`: `text-xl` → `text-lg`
- `BackupCodesDisplay.vue`: `text-xl` → `text-lg`
- `CloudCredentialModal.vue`: `text-xl` → `text-lg`

**Panel headings (`text-sm font-semibold`):**
- `SettingsAccountTab.vue`: 4 h3 headings — added `text-sm` (was `font-semibold` without explicit size)
- `DocumentView.vue`: 2 h3 headings (Topics, Extracted Text) — added `text-sm`

### Task 4 — Replace focus:ring patterns with focus-visible convention

Applied `focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-1` to:
- All sidebar nav links (via scoped CSS `.nav-link` `@apply` in AppSidebar + AdminSidebar)
- Expand/collapse toggle buttons in AppSidebar
- Sign-out button in AppSidebar and AdminSidebar
- StorageBrowser: New Folder button, rename/delete/share/move/delete icon action buttons
- DocumentView: Back button, Preview/Delete/Re-classify/Suggest/cloud-modal buttons
- TopicsView: All Topics back button, topic card router-links
- SettingsView: tab strip buttons, dismiss buttons
- TopicManager: Add/Save/Cancel/Edit/Delete buttons
- DocumentCard: Move and Share icon action buttons
- AdminAuditView: Apply/Clear/Export/Previous/Next/Download buttons
- AdminUsersView: Create User button (header and form submit)
- AdminAiView: all accordion and action buttons
- SettingsCloudTab: all Connect/Edit/Remove/Disconnect buttons
- SettingsAccountTab: Disable 2FA and Sign out all buttons
- BackupCodesDisplay: Copy all + Enable 2FA buttons
- CloudCredentialModal: Close button

Destructive actions use `focus-visible:ring-red-500` instead of indigo.

### Task 5 — Coherent hover and active states

Added `active:bg-{color}-{shade}` to all interactive elements that lacked press feedback:
- Primary buttons: `active:bg-indigo-800`
- Secondary/border buttons: `active:bg-gray-100`
- Icon action buttons: `active:bg-gray-300` (neutral), `active:bg-red-100` (destructive)
- Nav links: `active:bg-gray-200` via scoped CSS
- Folder picker dropdown items: `active:bg-gray-100` / `active:bg-indigo-100`
- Green "Set Active" button in AdminAiView: `active:bg-green-800`

### Task 6 — Palette preservation

No new colors introduced. Existing DocuVault identity preserved:
- amber/folders, sky/cloud, indigo/admin/primary, red/destructive, green/success
- Focus rings use indigo-500 for primary elements, red-500 for destructive elements, green-500 for success buttons

### Task 7 — Tests

**`AppSidebar.visual.test.js`** (4 tests):
- VISUAL-01: cloud skeleton items use `w-*` class not inline style width
- VISUAL-01: topics skeleton items use class-based widths not inline style
- VISUAL-04: expand/collapse folder toggle button has `focus-visible:ring-2` and `focus-visible:ring-indigo-500`
- VISUAL-04: sign-out button has `focus-visible:ring-2`

**`typography.visual.test.js`** (3 tests):
- VISUAL-03: SharedView h2 has `font-semibold` not `font-bold` and `text-2xl`
- VISUAL-03: TopicsView h2 has `font-semibold` not `font-bold` and `text-2xl`
- VISUAL-03: SettingsAccountTab h3 headings don't use `text-xl` or `font-bold`

## Verification

- `./node_modules/.bin/vitest run`: **36 test files, 270 tests, all pass**
- `./node_modules/.bin/vite build`: **succeeds** — all chunks build cleanly

## Deviations from Plan

None — plan executed exactly as written.

## Known Stubs

None — all data displayed is wired to real store/API data. No placeholder text or hardcoded values introduced.

## Threat Flags

None — all changes are frontend presentation classes and test files. No network endpoints, auth paths, file access patterns, or schema changes.

## Self-Check: PASSED

- `frontend/src/components/layout/AppSidebar.vue`: modified — skeleton classes, focus-visible, active states, expanded CSS
- `frontend/src/components/admin/AdminSidebar.vue`: modified — focus-visible, active states, expanded CSS
- `frontend/src/views/TopicsView.vue`: modified — font-semibold, focus-visible on back button and cards
- `frontend/src/views/DocumentView.vue`: modified — font-semibold, text-sm panel headings, focus-visible, active states
- `frontend/src/views/SharedView.vue`: modified — font-semibold
- `frontend/src/views/SettingsView.vue`: modified — focus-visible on tab buttons and dismiss buttons
- `frontend/src/views/admin/AdminOverviewView.vue`: modified — text-2xl page title
- `frontend/src/views/admin/AdminAuditView.vue`: modified — focus-visible and active states on all buttons
- `frontend/src/views/admin/AdminUsersView.vue`: modified — focus-visible and active states
- `frontend/src/views/admin/AdminAiView.vue`: modified — focus-visible and active states
- `frontend/src/components/settings/SettingsAccountTab.vue`: modified — text-sm panel headings, focus-visible, active states
- `frontend/src/components/settings/SettingsAiTab.vue`: modified — text-lg section title
- `frontend/src/components/settings/SettingsCloudTab.vue`: modified — text-lg section title, focus-visible, active states
- `frontend/src/components/settings/SettingsPreferencesTab.vue`: modified — text-lg section title
- `frontend/src/components/auth/BackupCodesDisplay.vue`: modified — text-lg heading, focus-visible, active
- `frontend/src/components/cloud/CloudCredentialModal.vue`: modified — text-lg modal title, close button focus-visible
- `frontend/src/components/documents/DocumentCard.vue`: modified — focus-visible and active on action buttons
- `frontend/src/components/storage/StorageBrowser.vue`: modified — focus-visible and active on all row action buttons
- `frontend/src/components/topics/TopicManager.vue`: modified — focus-visible and active on all buttons
- `frontend/src/components/layout/__tests__/AppSidebar.visual.test.js`: created — 4 tests
- `frontend/src/views/__tests__/typography.visual.test.js`: created — 3 tests
- Commit `2af5b7c` exists in git log: confirmed
- 36 test files, 270 tests all pass: confirmed
- Build succeeds: confirmed
