Files
reactbin/specs/005-ui-polish/quickstart.md
agatha 9246f75fdd Feat: Polish Angular UI with cohesive design system
Introduces a shared CSS custom property token layer and applies it
across all five views (library, upload, detail, login, app shell).
Each view now has intentional loading, empty, and error states.

- styles.css: 13 design tokens on :root; shimmer skeleton animation
- Library: 150ms-debounced skeleton loading, empty state with /upload
  link, error card with retry, card hover lift, broken-image fallback
- Upload: token-styled drop-zone, Uploading… spinner, 4s success
  banner, distinct validation vs. network error messages
- Detail: image skeleton, network error card (separate from 404
  not-found card), Owner actions panel, danger tag error styling,
  broken-image fallback
- Login: vertically centred surface card, danger field/server errors,
  Signing in… disabled button
- App shell: 48px fixed header, app name left, sign-out right, no
  reflow on auth state change
- All 24 ESLint errors resolved (including pre-existing auth spec
  issues); ng build and ng lint pass clean

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 20:03:56 +00:00

156 lines
5.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Quickstart: UI Polish Visual Acceptance Scenarios
Use this guide to manually verify each milestone after implementation.
Run `docker compose up` before starting. Open the browser at `http://localhost:4200`.
---
## M1 — Design Token Layer
**Goal**: Tokens exist; visual output is identical to before.
1. Open the library, upload, detail, and login pages.
2. Open browser DevTools → Elements → `<html>` or `<body>`.
3. Confirm `--bg`, `--surface`, `--accent`, `--danger` etc. are visible in
computed styles.
4. Confirm no visible change in any view compared to before M1.
---
## M2 — Library View
### Loading skeleton
1. Open DevTools → Network → set throttle to "Slow 3G".
2. Hard-refresh the library page.
3. **Expect**: A grid of grey shimmer cards appears immediately; no blank white
space; no layout jump when real images load in.
### Empty state
1. Ensure no images are uploaded (or use a fresh test database).
2. Open the library.
3. **Expect**: A centred empty-state panel with explanatory text and a prominent
"Upload your first image" link. Clicking the link navigates to `/upload`.
### Error state
1. Stop the API container (`docker compose stop api`).
2. Hard-refresh the library.
3. **Expect**: An error card with a plain-language message and a "Retry" button.
No blank grid, no raw status code.
4. Restart the API (`docker compose start api`) and click "Retry".
5. **Expect**: Images load successfully.
### Card polish
1. Hover over an image card.
2. **Expect**: Card lifts slightly (2 px translate) with a smooth transition.
### Broken image
1. Manually corrupt a storage key in the database (or unplug MinIO) and reload.
2. **Expect**: Card shows a grey placeholder graphic, not a broken-image browser icon.
### 375 px viewport
1. DevTools → Device toolbar → iPhone SE (375 × 667).
2. **Expect**: Cards stack, no horizontal scrollbar, all content readable.
---
## M3 — Upload View
### Drop-zone idle
1. Navigate to `/upload` (must be logged in).
2. **Expect**: A visually distinct drop-zone with dashed border and clear
instructions. Submit button is disabled/greyed.
### In-progress
1. Select a large image file.
2. Click upload.
3. **Expect**: Button label changes to "Uploading…" and is disabled. A spinner
or animated indicator is visible.
### Success
1. After a successful upload completes.
2. **Expect**: A green-tinted success banner with the filename, "Upload another"
link, and "View in library" link. Banner disappears after 4 seconds.
### Validation error
1. Attempt to upload a `.txt` file.
2. **Expect**: An inline error message names the problem ("Unsupported file type").
The form is still usable — no page reload required.
### Network error
1. Stop the API mid-upload (or use DevTools → block the upload request).
2. **Expect**: A generic inline error with guidance to retry. Form remains usable.
---
## M4 — Detail View
### Loading skeleton
1. Set network throttle to Slow 3G.
2. Navigate directly to an image URL (e.g., `http://localhost:4200/images/<id>`).
3. **Expect**: A grey rectangle skeleton for the image area and chip skeletons
below. No blank page.
### Not-found state
1. Navigate to `http://localhost:4200/images/00000000-0000-0000-0000-000000000000`.
2. **Expect**: A styled not-found card with "Image not found" heading and a
"Back to library" button. No blank page, no raw 404 text.
### Authenticated write controls
1. Log in and open a detail page.
2. **Expect**: Tag editing input and delete button are visible and clearly grouped.
### Unauthenticated view
1. Open the detail page in a private/incognito window (not logged in).
2. **Expect**: Image and read-only tag chips are visible. No tag input, no
delete button.
### Tag error
1. While logged in, attempt to add a tag with invalid characters (e.g., `TAG!`).
2. **Expect**: An inline error in danger colour with a left accent border.
Other tags and the image remain visible.
### Broken image
1. Open a detail page for an image whose storage object has been deleted.
2. **Expect**: A placeholder graphic replaces the image. Page layout is not broken.
---
## M5 — Login View
### Visual consistency
1. Open `/login` without being logged in.
2. **Expect**: Dark background matching the library; form centred in a surface
card; same font and spacing as other pages.
### Field validation
1. Click the Sign In button without entering any credentials.
2. **Expect**: Inline validation messages appear on the username and password
fields without a page reload.
### Invalid credentials error
1. Enter wrong credentials and submit.
2. **Expect**: A single error message below the form. Fields retain their values.
### In-progress state
1. Submit valid credentials (throttle network if needed to see the state).
2. **Expect**: Button label changes to "Signing in…" and is disabled while the
request is in flight.
---
## M6 — App Shell
### Authenticated header
1. Log in and navigate between library, upload, and an image detail page.
2. **Expect**: A consistent 48 px header is present on all pages. Sign-out
control is visible on the right. Header does not reflow content.
### Unauthenticated header
1. Open the library or detail page without logging in.
2. **Expect**: Header is present but sign-out control is absent.
### Sign out
1. Click the sign-out control in the header.
2. **Expect**: Redirected to `/login`. Header no longer shows sign-out control.
Navigating to `/upload` redirects back to `/login`.