name: dashboard-ui-polish
description: Apply a checklist of polish upgrades to dashboard views (reduced-motion, responsive grids, hover states, empty states, sub-stats, live indicators)
---
# Dashboard UI Polish

## When to use
- User asks to "upgrade", "polish", "improve", or "make nicer" a dashboard / admin / vault / overview view
- A view renders stats cards, panels, action buttons, and activity feeds but feels flat or static
- Any task touching `ui/src/ui/views/*-dashboard.ts` (or similar) where the brief is open-ended UX improvement

## How to apply
1. **Read the full view file first** — note CSS const, render functions, and which fields actually exist on view state. Don't invent fields.
2. **Apply this checklist, only where data backs it:**
   - **Reduced-motion CSS:** add `@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation:none !important; transition:none !important; } }` to the view's CSS const.
   - **Responsive grids:** replace fixed `grid-template-columns: 1fr 1fr` / `1fr 1fr 1fr` with `repeat(auto-fit, minmax(min(380px,100%), 1fr))` so columns collapse on narrow viewports.
   - **Button hover states:** add `.v-action-btn:hover` / `.v-ctrl-btn:hover` rules with accent border, soft glow (`box-shadow`), and `translateY(-1px)`. Add a `-danger` variant for destructive buttons.
   - **Panel slide-in:** add a `.v-panel` class with `animation: slideIn 0.22s ease-out` and define the keyframes.
   - **Stat card hover bug:** if `@mouseenter` sets `borderColor` AND `boxShadow`, ensure `@mouseleave` resets BOTH — a common bug is resetting only one.
   - **Stat card sub-values:** under each top-level stat, add a small muted line with a derived value (e.g. "X% of members", "X this month") — ONLY when the source data is present; otherwise omit.
   - **LIVE indicator:** if a feed shows recent events, add a pulsing green dot next to the count when events exist.
   - **Empty states:** replace plain strings ("No activity yet") with a styled block: icon + heading + descriptive text + optional CTA button.
3. **Verify build:** run the project's typecheck/build script (check `package.json` `scripts`). Confirm zero NEW errors — pre-existing errors are out of scope.
4. **Report intentionally-skipped items:** explicitly list features you didn't add because the data isn't there (e.g. "no sparklines — no time-series field in view state").

## Rules
- Never invent view-state fields. If `course.completions` doesn't exist, don't render "X completed".
- Never add animations without the `prefers-reduced-motion` opt-out.
- Always check `package.json` scripts before guessing the build command — repos vary between `bun run build`, `npm run typecheck`, etc.
- Always verify the build after edits; report pre-existing vs new error counts separately.
- Never silently expand scope to other view files; if the task spans multiple views, list which you touched and which you deliberately didn't.
- When asked to "remove X" and X cannot be found after exhaustive search, report "not found" with the searched locations — do not fabricate a removal.