Unify Star/Watch/Fork/Clone header pills into one idiom (Star/Watch canonical): counts left of label, one aligned row #447

Closed
opened 2026-09-13 13:39:41 +00:00 by crueber · 3 comments
Owner

What's requested

Unify the repository header action pills — Star, Watch, Fork, Clone — into ONE idiom, with the Star/Watch button style as the canonical pattern. All counts render on the LEFT of the label, and all four controls sit aligned on one row in the header actions cluster.

Current behavior (evidence)

web/src/pages/Repo.jsx, header actions cluster (.repo-header right side, ~line 610-627):

  • Star (StarToggle, ~line 333): btn px-2 py-1 text-sm button rendering ★ {stars} — glyph+count, no text label.
  • Watch (WatchToggle, ~line 179): btn px-2 py-1 text-sm button rendering {watchers} with a glyph — glyph+count, no text label.
  • Fork (~line 624): <A class="pill"> anchor rendering Fork {forks} — LABEL-then-count (count on the RIGHT), and a different container class (pill vs btn).
  • Clone (CloneMenu, ~line 99): <summary class="pill"> — pill container, label only.

Result: three container styles (btn x2, pill x2) and two count placements (count-only vs label-then-count). The row reads as two families of control rather than one action strip.

Canonical idiom (Star/Watch style)

  • All four controls use the same container: the Star/Watch btn px-2 py-1 text-sm shape (toggles keep their primary active state; Fork stays an <A> link styled to the same metrics; Clone's <summary> adopts the same shape as its trigger).
  • Content order: count (if any) first, then the label — e.g. 3 Star, 2 Watch, 4 Fork, Clone (no count). The glyph convention Star/Watch use may be kept, but the count must sit left of the text label in every case.
  • One row: the ml-auto flex items-center gap-2 cluster keeps all four on a single aligned row; no wrapping/orphans at narrow widths (follow the repo's mobile-collapse precedent from #438).

Relationship to #446 (superseded)

#446 asked to render the fork count inside a .tab-badge count circle on the Fork button. That direction adds a second count idiom where the header needs one: this ticket absorbs and supersedes it. Closing #446 in favor of this one.

Architecture notes

  • Counts come from data already in hand: stars/watchers from the social/watch endpoints the toggles already fetch; forks from the shared summary (s().forks) — no new requests, no ETag concern (display-only).
  • Fork's hidden-at-zero behavior for its count is reasonable, but with counts leading the label the group should read consistently — at 0, either show 0 Fork like Star/Watch show 0 or keep it hidden; implementer's call, noted in the PR.
  • Pure client-side presentation change in Repo.jsx (+ possibly a shared small component if Star/Watch/Fork/Clone triggers want one source of the shape); no API, store, or routing changes.

Acceptance criteria

  • Star, Watch, Fork, and Clone all render the same container shape/metrics (Star/Watch btn style as canonical) in the header actions cluster.
  • Every count renders LEFT of its label ({n} Star, {n} Watch, {n} Fork); Clone renders label-only, same shape.
  • All four controls align on one row; no wrapping, reflow, or orphaned controls at narrow/mobile widths.
  • Star/Watch toggle behavior, Fork link navigation, and Clone popover function unchanged; optimistic-flip reconcile paths untouched.
  • #446 is closed with a cross-reference to this ticket.
## What's requested Unify the repository header action pills — Star, Watch, Fork, Clone — into ONE idiom, with the Star/Watch button style as the canonical pattern. All counts render on the LEFT of the label, and all four controls sit aligned on one row in the header actions cluster. ## Current behavior (evidence) `web/src/pages/Repo.jsx`, header actions cluster (`.repo-header` right side, ~line 610-627): - **Star** (`StarToggle`, ~line 333): `btn px-2 py-1 text-sm` button rendering `★ {stars}` — glyph+count, no text label. - **Watch** (`WatchToggle`, ~line 179): `btn px-2 py-1 text-sm` button rendering `{watchers}` with a glyph — glyph+count, no text label. - **Fork** (~line 624): `<A class="pill">` anchor rendering `Fork {forks}` — LABEL-then-count (count on the RIGHT), and a different container class (`pill` vs `btn`). - **Clone** (`CloneMenu`, ~line 99): `<summary class="pill">` — `pill` container, label only. Result: three container styles (`btn` x2, `pill` x2) and two count placements (count-only vs label-then-count). The row reads as two families of control rather than one action strip. ## Canonical idiom (Star/Watch style) - All four controls use the same container: the Star/Watch `btn px-2 py-1 text-sm` shape (toggles keep their `primary` active state; Fork stays an `<A>` link styled to the same metrics; Clone's `<summary>` adopts the same shape as its trigger). - Content order: count (if any) first, then the label — e.g. `3 Star`, `2 Watch`, `4 Fork`, `Clone` (no count). The glyph convention Star/Watch use may be kept, but the count must sit left of the text label in every case. - One row: the `ml-auto flex items-center gap-2` cluster keeps all four on a single aligned row; no wrapping/orphans at narrow widths (follow the repo's mobile-collapse precedent from #438). ## Relationship to #446 (superseded) #446 asked to render the fork count inside a `.tab-badge` count circle on the Fork button. That direction adds a second count idiom where the header needs one: this ticket absorbs and supersedes it. Closing #446 in favor of this one. ## Architecture notes - Counts come from data already in hand: stars/watchers from the social/watch endpoints the toggles already fetch; forks from the shared summary (`s().forks`) — no new requests, no ETag concern (display-only). - Fork's hidden-at-zero behavior for its count is reasonable, but with counts leading the label the group should read consistently — at 0, either show `0 Fork` like Star/Watch show `0` or keep it hidden; implementer's call, noted in the PR. - Pure client-side presentation change in `Repo.jsx` (+ possibly a shared small component if Star/Watch/Fork/Clone triggers want one source of the shape); no API, store, or routing changes. ## Acceptance criteria - [ ] Star, Watch, Fork, and Clone all render the same container shape/metrics (Star/Watch `btn` style as canonical) in the header actions cluster. - [ ] Every count renders LEFT of its label (`{n} Star`, `{n} Watch`, `{n} Fork`); Clone renders label-only, same shape. - [ ] All four controls align on one row; no wrapping, reflow, or orphaned controls at narrow/mobile widths. - [ ] Star/Watch toggle behavior, Fork link navigation, and Clone popover function unchanged; optimistic-flip reconcile paths untouched. - [ ] #446 is closed with a cross-reference to this ticket.
crueber added this to the v1 milestone 2026-09-13 13:40:13 +00:00
Author
Owner

Fixed by #454 (PR: unify header pills on the Star/Watch btn idiom, counts left of label). Headless tests + vite build green; no backend change.

Fixed by #454 (PR: unify header pills on the Star/Watch btn idiom, counts left of label). Headless tests + vite build green; no backend change.
Author
Owner

Review #454 (fix/issue-447) — verified head-to-head in scratch (/tmp/wt-447 branch vs /tmp/wt-447-main pristine origin/main, node_modules symlinked from main in both; no browser per instructions — node tests + reasoning, explicitly noted):

ACCEPTANCE (all 5 met):
(1) One shape: Star/Watch buttons (Repo.jsx:207,362), Fork A-link (:636), Clone summary (:99) all carry btn px-2 py-1 text-sm; toggles keep primary, Fork stays a link, Clone stays popover trigger. (2) Count-left-of-label: {n} Star, {n} Watch, {n} Fork; Clone label-only, no interpolation (glyphs kept). (3) Fork zero-count: always renders incl. 0 (no hidden-at-zero conditional), noted in code comment + 12_web_ui entry + test. (4) #446 absorbed: closed with two #447 cross-ref comments; tab-badge-circle rejection noted in code + doc + test. (5) One row: ml-auto flex items-center gap-2 cluster (:615) and repo-header flex-wrap (:542) byte-identical to main; narrow widths collapse as one unit per #438 precedent; 390px arithmetic pinned. (6) Behavior byte-identical: diff touches only classes/labels — flip/reconcile, Fork nav, Clone popover (lazy recipes, outside-click, Esc) untouched and pinned. (7) #285/#438 pins faithful: social-toggles rewritten to the labeled idiom (supersede noted in test header, a11y/pressed/active kept); fork-438 matched-pair retargeted pill to btn. (8) No backend change, no new deps (5 files: Repo.jsx + 3 tests + 12_web_ui.md); doc entry accurate after review fix below.

TESTS (head-to-head full node suite): branch 957 total / 955 pass / 2 fail vs main 950 / 948 / 2 — failing set file-by-file identical (only the 2 live-server smoke.test.js subtests needing a live Go server). +7 net new, zero PR-caused. The 837/822/15 claim in the PR body + doc entry does NOT reproduce in-scratch (no blob-md/data-guard/etc. failures here). vite build green (2.23s).

REVIEW FIX (pushed 771f762 to origin/fix/issue-447): corrected the 12_web_ui.md #447 entry to the verified 957/955/2 vs 950/948/2 numbers (Law 12; same correction pattern as #453 review). Re-tested after fix: 16/16 on the three touched files, full suite still 957/955/2. Note: PR #454 description body still carries the stale 837/822/15 numbers — consider updating it for the record.

Browser proof open (shared-daemon loopback guard; no private daemon per workspace rules) — noted explicitly, no browser driven.

MERGE RECOMMENDATION: ready to merge (after optional PR-body number touch-up; not merge-blocking).

Review #454 (fix/issue-447) — verified head-to-head in scratch (/tmp/wt-447 branch vs /tmp/wt-447-main pristine origin/main, node_modules symlinked from main in both; no browser per instructions — node tests + reasoning, explicitly noted): ACCEPTANCE (all 5 met): (1) One shape: Star/Watch buttons (Repo.jsx:207,362), Fork A-link (:636), Clone summary (:99) all carry btn px-2 py-1 text-sm; toggles keep primary, Fork stays a link, Clone stays popover trigger. (2) Count-left-of-label: {n} Star, {n} Watch, {n} Fork; Clone label-only, no interpolation (glyphs kept). (3) Fork zero-count: always renders incl. 0 (no hidden-at-zero conditional), noted in code comment + 12_web_ui entry + test. (4) #446 absorbed: closed with two #447 cross-ref comments; tab-badge-circle rejection noted in code + doc + test. (5) One row: ml-auto flex items-center gap-2 cluster (:615) and repo-header flex-wrap (:542) byte-identical to main; narrow widths collapse as one unit per #438 precedent; 390px arithmetic pinned. (6) Behavior byte-identical: diff touches only classes/labels — flip/reconcile, Fork nav, Clone popover (lazy recipes, outside-click, Esc) untouched and pinned. (7) #285/#438 pins faithful: social-toggles rewritten to the labeled idiom (supersede noted in test header, a11y/pressed/active kept); fork-438 matched-pair retargeted pill to btn. (8) No backend change, no new deps (5 files: Repo.jsx + 3 tests + 12_web_ui.md); doc entry accurate after review fix below. TESTS (head-to-head full node suite): branch 957 total / 955 pass / 2 fail vs main 950 / 948 / 2 — failing set file-by-file identical (only the 2 live-server smoke.test.js subtests needing a live Go server). +7 net new, zero PR-caused. The 837/822/15 claim in the PR body + doc entry does NOT reproduce in-scratch (no blob-md/data-guard/etc. failures here). vite build green (2.23s). REVIEW FIX (pushed 771f762 to origin/fix/issue-447): corrected the 12_web_ui.md #447 entry to the verified 957/955/2 vs 950/948/2 numbers (Law 12; same correction pattern as #453 review). Re-tested after fix: 16/16 on the three touched files, full suite still 957/955/2. Note: PR #454 description body still carries the stale 837/822/15 numbers — consider updating it for the record. Browser proof open (shared-daemon loopback guard; no private daemon per workspace rules) — noted explicitly, no browser driven. MERGE RECOMMENDATION: ready to merge (after optional PR-body number touch-up; not merge-blocking).
Author
Owner

Fixed by PR #454 (review clean + test-count doc fix by reviewer; all 8 checks pass, #446 absorbed), merged. Closing.

Fixed by PR #454 (review clean + test-count doc fix by reviewer; all 8 checks pass, #446 absorbed), merged. Closing.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
crueber/walhub#447
No description provided.