This repository has been archived on 2026-05-31. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
GallerySubscriber/docs/superpowers/specs/2026-03-19-ui-improvement-pass-design.md
2026-03-19 17:45:22 -04:00

8.1 KiB

UI Improvement Pass — Design Spec

Date: 2026-03-19 Scope: All 6 pages — visual polish + UX usability, equal weight Direction: Darker, cooler blue-grey tone ("monitoring dashboard" feel), lifted nav branding


Goals

  1. Replace the generic default-Vuetify color palette with a distinctive monitoring-dashboard identity
  2. Give the nav drawer meaningful visual structure and branding
  3. Add a WebSocket connection indicator in the app bar
  4. Improve Dashboard information hierarchy and action bar layout
  5. Fix dark-mode-breaking hardcoded colour classes across all pages
  6. Consistent empty states and loading treatment throughout
  7. Per-page UX improvements (Downloads filter, Credentials visual state, Subscriptions dark mode)

Section 1: Color System (frontend/src/plugins/vuetify.js)

Replace both theme palettes entirely.

Dark theme (primary use case)

dark: {
  dark: true,
  colors: {
    background: '#0F172A',   // slate-900 — deep navy
    surface:    '#1E293B',   // slate-800 — card surfaces
    primary:    '#60A5FA',   // blue-400  — cooler accent
    secondary:  '#94A3B8',   // slate-400
    error:      '#F87171',   // red-400
    warning:    '#FBBF24',   // amber-400
    success:    '#34D399',   // emerald-400
    info:       '#38BDF8',   // sky-400
  },
}

Light theme

light: {
  dark: false,
  colors: {
    background: '#F1F5F9',   // slate-100 — cool grey workspace
    surface:    '#FFFFFF',
    primary:    '#2563EB',   // blue-600 — deeper, more serious
    secondary:  '#475569',   // slate-600
    error:      '#EF4444',
    warning:    '#F59E0B',
    success:    '#10B981',
    info:       '#0EA5E9',
  },
}

Global component defaults (add to existing defaults)

VCard:  { elevation: 0, border: true },
VBtn:   { variant: 'flat' },
VChip:  { rounded: 'md' },

Removing shadow elevation in favour of a subtle border gives cards a cleaner, more modern feel at both themes. The border adapts to theme colours automatically.


Section 2: Nav Drawer & App Bar (frontend/src/App.vue)

Nav drawer brand header

Replace the plain v-list-item brand block with a styled header:

  • Container: pa-4 padding, bg-surface background to visually separate from nav list
  • Icon: mdi-download-network at size 32, color="primary" (icon intentionally changed from current mdi-image-multiple)
  • Title: "GallerySubscriber" in font-weight-bold text-subtitle-1 (title intentionally changed from "Gallery Subscriber" — one word, no space)
  • Subtitle: "Download Manager" in text-caption text-medium-emphasis
  • Followed by a v-divider

Nav list items

Change from density="compact" to density="comfortable". Add rounded="lg" and active-color="primary" to each v-list-item. The built-in Vuetify active state renders a tinted pill highlight on the current route.

App bar

  • Change elevation="1" to elevation="0" with border="b" — flat bar with bottom border
  • Add a WebSocket status indicator to the right of the title, before the theme toggle:
    • A small icon button showing two states (the store exposes isConnected: Ref<boolean> only — no "connecting" state is tracked):
      • Connected: mdi-circle at size 10, color="success" + v-tooltip "Real-time updates active"
      • Disconnected: mdi-circle at size 10, color="error" + v-tooltip "Disconnected — real-time updates paused"
    • Reads from useWebSocketStore().isConnected
    • Wrapped in a v-btn variant="text" icon so it is unobtrusive and the tooltip activates on hover

Section 3: Dashboard (frontend/src/views/Dashboard.vue)

Stat cards (number-forward layout)

Replace the v-avatar + side-by-side number layout with a vertical number-forward design:

  • Large text-h3 font-weight-bold number at top
  • text-caption text-medium-emphasis label below
  • A 4px left border accent stripe using inline style border-left: 4px solid <colour> matching the card's semantic colour (primary, success, error, warning)
  • Remove the v-avatar entirely — the border provides the colour signal

Action bar (split into two rows)

Row 1 (actions): The three action buttons unchanged — Check All Sources, Retry All Failed, Reset Stuck.

Row 2 (status): Two groups separated by a v-divider vertical:

  • Left: credential status chips (the existing platform chips, unchanged)
  • Right: storage stats (existing display, unchanged)

Each row is its own v-card-text. This removes the single-line cramming.

Active downloads list

Running items get a subtle animated left border:

.download-running {
  border-left: 3px solid rgb(var(--v-theme-primary));
  animation: pulse-border 2s ease-in-out infinite;
}
@keyframes pulse-border {
  0%, 100% { opacity: 1; }
  50%       { opacity: 0.4; }
}

Consistent empty states

All three empty panels (active downloads, recent activity, sources needing attention) use the same pattern:

<div class="text-center py-8">
  <v-icon size="48" color="secondary" :style="{ opacity: 0.5 }">mdi-[relevant-icon]</v-icon>
  <div class="text-body-1 mt-2">[Primary message]</div>
  <div class="text-caption text-medium-emphasis mt-1">[Helper text]</div>
</div>
  • Active downloads empty: icon mdi-check-circle-outline, "No active downloads", "All sources are idle"
  • Recent activity empty: icon mdi-history, "No recent activity", "Failures and new downloads appear here"
  • Sources needing attention empty: icon mdi-check-all, "All sources healthy", "No failures in the last 7 days"

Section 4: Per-Page Fixes

Subscriptions (frontend/src/views/Subscriptions.vue)

  • Replace class="bg-grey-lighten-4" on the expanded inner table with class="bg-surface". This is the only dark-mode-breaking class in the file.
  • Add class="border-t" to the inner table container for visual separation.

Downloads (frontend/src/views/Downloads.vue)

  • Add an exclude_superseded filter toggle below the existing four filter columns (the current row is already full-width with four md="3" columns). Add a new v-row directly below the existing filter row containing a single v-col cols="12" with a v-switch labelled "Hide superseded failures", density="compact", hide-details, defaulting to true. When true, adds exclude_superseded: true to the loadDownloads() params.
  • The existing four filter columns are unchanged.

Credentials (frontend/src/views/Credentials.vue)

Two visual states for platform cards:

Configured: Card gets border-color set to the success colour via inline style or a CSS class. Existing content unchanged.

Not configured: Card gets a dashed border via :style="{ border: '2px dashed var(--v-border-color)' }" and :border="false" to override the global VCard border: true default. (--v-border-color is a hex value, not an RGB triplet, so it must be used directly without rgb() wrapping.) The v-alert info block is replaced with a concise empty-state message, and the "Add Credentials" button is promoted to color="primary" variant="flat" (currently variant="text"), making the call to action visually prominent.

Settings & Logs

No structural changes — both pages inherit the new palette and card border style from the vuetify.js update automatically.


Files Changed

File Change
frontend/src/plugins/vuetify.js Full palette replacement, component defaults update
frontend/src/App.vue Nav branding, nav item density/rounding, app bar border+ws indicator
frontend/src/views/Dashboard.vue Stat card layout, action bar split, running item pulse, empty states
frontend/src/views/Subscriptions.vue Replace bg-grey-lighten-4 with bg-surface
frontend/src/views/Downloads.vue Add exclude_superseded filter toggle
frontend/src/views/Credentials.vue Configured/unconfigured card visual states

Settings.vue and Logs.vue are not modified — they benefit from the theme update without code changes.


Non-Goals

  • No new pages or routes
  • No layout restructuring (grid columns, page structure unchanged)
  • No new API endpoints
  • No component extraction / shared component library
  • Settings.vue and Logs.vue: no structural changes