feat: media page T1

This commit is contained in:
fsylvain committed 2026-10-01 01:36:35 +02:00
1 parent 67d456baf6
commit 008b0dfbb9
46 files changed
+5742 -204

No files matched your search

+13 -22
View File
@@ -6,7 +6,7 @@ SPA only. The media API already exists (slice A), so there is no HTTP-level Go t
and no `test/` file. The Go suite is run only to confirm nothing regressed (`task test`).
Slice B2 (upload, multi-select, bulk bar, Duplicates content, merge, drag and drop, rate limit) is
out of scope: its states are listed under "Pending, slice B2" and are never reported as passing.
specified in features/media_upload_selection_duplicates.feature and its .qa.md.
Toast ids: "media-url-copied-{id}", "media-renamed-{id}", "media-deleted-{id}", "media-not-found-{id}".
@@ -29,26 +29,26 @@ Logic and copy:
"WEBP", image/svg+xml "SVG"); accessible name for used_in 2, 1 and 0 ("used in 2 articles",
"used in 1 article", "unused").
2. **Query string mapping** - Examples-driven from the .feature: each URL produces the exact
request query and control state; unknown values and ?filter=duplicates fall back to defaults;
request query and control state; unknown values fall back to defaults;
changing a control rewrites the URL and drops default values.
3. **Default** - 12 cards in fixture order, tabs "All 12" "Unused 2" "Duplicates 2", the
Duplicates badge only when duplicates > 0, "12 images" in the Select all row, breadcrumb
"Media", no checkbox in the DOM.
Duplicates badge only when duplicates > 0, "Select all" and "12 images" in the Select all row,
breadcrumb "Media".
4. **Badges and accessible names** - the 5 Examples rows (badges and aria-label / accessible name).
5. **Grid, few images** - 3 items; tabs "All 3" "Unused 1" "Duplicates" without a badge.
6. **List view** - desktop: table with the 7 column headers and 12 rows, the Used in cell
underlined count or Unused badge; mobile: card list with "3.9 MB · 4032 × 3024 · JPEG" and
"Marta Alves · 12 Sep 2026"; clicking the Used in count opens the panel.
7. **Disabled Duplicates tab** - aria-disabled, click and focus change nothing, no request.
7. **Duplicates tab** - covered by the B2 spec.
8. **Loading** - unresolved GET: nothing before 150 ms; after 150 ms the skeleton (10 cards,
6 below md) and aria-busy; resolve; cards replace it; same on retry and on search, tab and
sort change, in list view too.
9. **Empty library** - zero items and counts 0 with no q: toolbar and tabs absent, copy exact,
"Upload an image" rendered disabled, the footnote "PNG, JPEG, WEBP, SVG · max 10 MB each".
"Upload an image" enabled, the footnote "PNG, JPEG, WEBP, SVG · max 10 MB each".
10. **No results** - unused + "wall": title `No images match "wall"`, text "Nothing matches in
Unused. Check the spelling, or clear the filters."; "Clear filters" resets q and filter and
restores the cards.
11. **Keyboard** - each card is a button; Enter opens the panel; Space opens nothing; arrow keys
11. **Keyboard** - each card is a button; Enter opens the panel; Space toggles selection and opens nothing; arrow keys
move focus (left, right, up, down by one row, stopping at the edges); Escape closes the panel
and focus returns to the card.
12. **Detail panel, in use** - usage called once for id 1, title, actions, metadata rows, article
@@ -57,7 +57,7 @@ Logic and copy:
text.
14. **Detail panel, duplicate** - hash query used; alert title "Identical to 2 other images" and
"floorboards-copy.jpg and IMG_2208.jpg have the same content." (the image itself is excluded);
the "Review duplicates" action is disabled.
the "Review duplicates" action is enabled and selects the Duplicates tab.
15. **Copy URL** - clipboard called with `{origin}{url}`; toast id "media-url-copied-1", icon
circle-check, title "URL copied", text "Paste it wherever you need the image address.".
16. **Rename dialog** - title, description, field "north-wall" with ".jpg" suffix, help text,
@@ -87,8 +87,7 @@ Logic and copy:
29. **Sidebar and drawer** - Media between Articles and Users with the images icon, active on
/media, in the desktop sidebar and the mobile drawer; the route has meta.auth "verified" and
meta.title "Media" (routerGuard spec extended).
30. **Header** - title, subtitle, and the Upload button disabled and inert in this slice (also
the mobile pinned 48 px variant).
30. **Header** - title, subtitle, and the Upload button (also the mobile pinned 48 px variant).
## Visual (`task visual:check -- media`, desktop and mobile, light and dark)
@@ -105,10 +104,7 @@ icon, the RenewCMS mark on the SVG, a checkerboard behind PNG and SVG), not phot
mocked image URLs must render the same way, or the 10 % gate fails for a reason unrelated to
the code.
Harness note: `web/visual/states.ts` gains a `skip: 'pending'` option, added by coder. It prints
`PENDING` and counts as neither pass nor fail. `task visual:check -- media` still exits non-zero
when a B1 state has no setup, when a `/v1` call is unmocked, when sizes mismatch or when a capture
exceeds its budget. Every B2 state carries `skip: 'pending'` and is never reported as passing.
Harness note: the B2 states now have setups and no longer carry `skip: 'pending'`.
Setups for this slice (name in screens/media.md, then what must be drawn):
@@ -118,9 +114,8 @@ Setups for this slice (name in screens/media.md, then what must be drawn):
- [ ] Loading: skeleton cards (10 desktop, 6 mobile), toolbar visible.
- [ ] Empty library, first run: no toolbar, "No images yet" panel and the footnote.
- [ ] No results: unused + "wall".
- [ ] Hover, focus and keyboard: hover on id 2, focus ring on id 3 (the checkbox reveal is not
drawn in this slice).
- [ ] Detail panel: in use (id 1), unused (id 8), duplicate (id 12; the action rendered disabled).
- [ ] Hover, focus and keyboard: hover on id 2, focus ring on id 3 (the checkbox reveal is covered by B2).
- [ ] Detail panel: in use (id 1), unused (id 8), duplicate (id 12).
- [ ] Copy URL: id 1 panel plus the toast.
- [ ] Rename: dialog, saving, validation, failed, done (id 1, "north-wall-01").
- [ ] Delete: unused (id 8), in use (id 1), in progress (id 1), failed (id 8), done (grid without
@@ -129,11 +124,7 @@ Setups for this slice (name in screens/media.md, then what must be drawn):
- [ ] List failed to load: alert with "Try again".
- [ ] Offline: banner and disabled Upload.
Pending, slice B2 (`skip: 'pending'`, never reported as passing):
- Selection and bulk bar; Bulk delete: confirm, in progress, partly failed, done
- Upload: drag over the page, several files mixed, summary, rejected files (413, 400), too many requests (429)
- Duplicates: groups, empty; Merge: confirm, in progress, failed, conflict (409), done
The B2 states are listed in features/media_upload_selection_duplicates.qa.md.
Manual checks screenshots cannot cover: