Profile page: remove leftover repository summary and move owner tabs into the right sidebar #437

Closed
opened 2026-09-13 13:02:19 +00:00 by crueber · 3 comments
Owner

Profile page: drop the leftover repo-count teaser and move the owner tabs into the sidebar

What's requested

Two changes to the owner profile page (web/src/pages/Repos.jsx, the OwnerPage profile view, route /:owner):

  1. Remove the leftover repository summary section at the bottom of the profile view. The profile view still renders the repository-count teaser ("N repositories · View all →") that predates the #422 tab split — web/src/pages/Repos.jsx lines 531-549 (the <Show when={view() === "profile"}> block rendering the count + link from the shared repos:{owner} doc). With the Repositories tab now owning the listing, this summary is redundant leftover chrome on the identity page. Delete the teaser block from the profile view (the repositories tab's own count paragraph at lines 660-662 stays untouched).

  2. Move the Profile / Repositories / Organizations tabs into the right sidebar as a vertical tab list above the avatar. Today <OwnerTabs> renders as a horizontal strip at the top of the page flow (line 422, component defined at line 102; landed in #435). Move it into the profile-layout right sidebar (web/src/pages/Repos.jsx line 565, the profile-sidebar aside from #421) as the FIRST element, above the avatar, styled as a vertical tab list that behaves as true tabs:

    • Stacked vertically, full sidebar width.
    • Active tab visually connected — e.g. shared border + background with the tabs block (no visible seam between the active tab and its container), the way real tab widgets look, not just a colored underline floating in space. Match the sidebar design language (zinc borders border-zinc-200 dark:border-zinc-700, the existing text/hover treatment).
    • Keep: the active-tab derivation from the pathname (line 108-113), aria-current="page", the tab-badge repository count on the Repositories tab, and the isOrg gating (Organizations tab hidden on org profiles, #370).

Architecture notes

  • This supersedes the #435 placement (strip-first, top of page flow). The tab component (OwnerTabs, line 102) and the sidebar (profile-sidebar aside, line 565, #421) are the two seams; no API change, no new fetches — the count already rides the shared repos:{owner} payload (#422).
  • Placement detail for the implementer: the sidebar currently renders behind a <Show when={!isOrg() && (userSrc() || isSelf() || getProfile()?.can_edit)}> gate. The tabs must render for ALL viewers on both user and org profiles — if they live inside that aside, either widen the gate or render the tab list as a sibling above the gated aside inside the same sidebar column. Planner's call; the visible requirement is tabs-above-avatar in the right column on every owner profile.
  • The org sidebar variant (line 615) needs the same tab treatment (Profile | Repositories only).
  • The repositories and organizations tab views (view="repos" / view="orgs" branches) currently render the strip plus their content with no sidebar. After the move, decide and note how those views surface the tab list (e.g. render the same sidebar shell on all three views so navigation stays one click away) — planner's call, but the tabs must remain reachable from every owner route.
  • Existing tests to update: web/test/unit/owner-tabs-top-435.test.js (asserts strip-first placement — will need rework to the sidebar shape), plus owner-repos-tab-422.test.js, owner-orgs-tab-430.test.js, profile-sidebar-421.test.js as affected.

Acceptance criteria

  • The "N repositories · View all →" teaser no longer renders anywhere on the profile view; the repositories tab still shows its count.
  • No top tab strip remains above the profile identity content on any owner route.
  • Profile / Repositories (and Organizations on user profiles) render as a vertical tab list at the top of the right sidebar, above the avatar, on both user and org profiles.
  • The active tab is visually connected to its container (true-tab look) and matches the sidebar's zinc design language in light and dark modes.
  • aria-current="page", the repository-count badge, and the #370 org gating survive the move.
  • Navigation between the three owner routes works from the sidebar tabs on all owner routes.
  • No horizontal overflow at 390px (per #273-#278 conventions); existing unit tests updated and green.
# Profile page: drop the leftover repo-count teaser and move the owner tabs into the sidebar ## What's requested Two changes to the owner profile page (`web/src/pages/Repos.jsx`, the `OwnerPage` profile view, route `/:owner`): 1. **Remove the leftover repository summary section at the bottom of the profile view.** The profile view still renders the repository-count teaser ("N repositories · View all →") that predates the #422 tab split — `web/src/pages/Repos.jsx` lines 531-549 (the `<Show when={view() === "profile"}>` block rendering the count + link from the shared `repos:{owner}` doc). With the Repositories tab now owning the listing, this summary is redundant leftover chrome on the identity page. Delete the teaser block from the profile view (the repositories tab's own count paragraph at lines 660-662 stays untouched). 2. **Move the Profile / Repositories / Organizations tabs into the right sidebar as a vertical tab list above the avatar.** Today `<OwnerTabs>` renders as a horizontal strip at the top of the page flow (line 422, component defined at line 102; landed in #435). Move it into the profile-layout right sidebar (`web/src/pages/Repos.jsx` line 565, the `profile-sidebar` aside from #421) as the FIRST element, above the avatar, styled as a **vertical tab list that behaves as true tabs**: - Stacked vertically, full sidebar width. - **Active tab visually connected** — e.g. shared border + background with the tabs block (no visible seam between the active tab and its container), the way real tab widgets look, not just a colored underline floating in space. Match the sidebar design language (zinc borders `border-zinc-200 dark:border-zinc-700`, the existing text/hover treatment). - Keep: the active-tab derivation from the pathname (line 108-113), `aria-current="page"`, the `tab-badge` repository count on the Repositories tab, and the isOrg gating (Organizations tab hidden on org profiles, #370). ## Architecture notes - This supersedes the #435 placement (strip-first, top of page flow). The tab component (`OwnerTabs`, line 102) and the sidebar (`profile-sidebar` aside, line 565, #421) are the two seams; no API change, no new fetches — the count already rides the shared `repos:{owner}` payload (#422). - Placement detail for the implementer: the sidebar currently renders behind a `<Show when={!isOrg() && (userSrc() || isSelf() || getProfile()?.can_edit)}>` gate. The tabs must render for ALL viewers on both user and org profiles — if they live inside that aside, either widen the gate or render the tab list as a sibling above the gated aside inside the same sidebar column. Planner's call; the visible requirement is tabs-above-avatar in the right column on every owner profile. - The org sidebar variant (line 615) needs the same tab treatment (Profile | Repositories only). - The repositories and organizations tab views (`view="repos"` / `view="orgs"` branches) currently render the strip plus their content with no sidebar. After the move, decide and note how those views surface the tab list (e.g. render the same sidebar shell on all three views so navigation stays one click away) — planner's call, but the tabs must remain reachable from every owner route. - Existing tests to update: `web/test/unit/owner-tabs-top-435.test.js` (asserts strip-first placement — will need rework to the sidebar shape), plus `owner-repos-tab-422.test.js`, `owner-orgs-tab-430.test.js`, `profile-sidebar-421.test.js` as affected. ## Acceptance criteria - [ ] The "N repositories · View all →" teaser no longer renders anywhere on the profile view; the repositories tab still shows its count. - [ ] No top tab strip remains above the profile identity content on any owner route. - [ ] Profile / Repositories (and Organizations on user profiles) render as a vertical tab list at the top of the right sidebar, above the avatar, on both user and org profiles. - [ ] The active tab is visually connected to its container (true-tab look) and matches the sidebar's zinc design language in light and dark modes. - [ ] `aria-current="page"`, the repository-count badge, and the #370 org gating survive the move. - [ ] Navigation between the three owner routes works from the sidebar tabs on all owner routes. - [ ] No horizontal overflow at 390px (per #273-#278 conventions); existing unit tests updated and green.
crueber added this to the v1 milestone 2026-09-13 13:03:03 +00:00
Author
Owner

Fix ready for review: #439 (#439) — branch fix/issue-437. Sidebar vertical tabs (ungated sibling above the gated asides) + teaser deleted, all three views share one layout grid. node --test 810 total / 796 pass (14 pre-existing failures, identical set on pristine main); vite + esbuild green. Not merging per instructions.

Fix ready for review: #439 (https://git.packden.us/crueber/walhub/pulls/439) — branch fix/issue-437. Sidebar vertical tabs (ungated sibling above the gated asides) + teaser deleted, all three views share one layout grid. node --test 810 total / 796 pass (14 pre-existing failures, identical set on pristine main); vite + esbuild green. Not merging per instructions.
Author
Owner

Review of PR #439 (fix/issue-437), verified in scratch worktrees on branch tip + pristine origin/main (node v26, web/node_modules symlinked from main; no browser — node tests + source reasoning only, as instructed; no docker, no live instance touched).

ACCEPTANCE CRITERIA (all 7 pass):

  1. Teaser gone, tab count intact: zero 'View all →' matches anywhere in web/src/pages/Repos.jsx (the 531-549 block deleted); repos-tab count paragraph + orderByActivity payload untouched (pinned by owner-tabs-sidebar-437.test.js 'repositories tab keeps its own count paragraph').
  2. Vertical tab list, tabs-first: single <OwnerTabs … /> use at Repos.jsx:628, first child of .profile-sidebar-col above both avatar asides (asserted against Profile-actions, Organization-actions, profile-avatar, Edit-profile, Manage-organization markers). True-tab look: bordered box (border-zinc-200 dark:border-zinc-700, bg-white dark:bg-zinc-950) + active tab fills row (!bg-zinc-100 dark:!bg-zinc-800, medium type) — emerald underline fully gone, zinc both themes.
  3. Gate choice correct: ungated sibling — zero between .repos-page and .profile-layout, OwnerTabs ungated, both #421 aside gates byte-identical. Anonymous sees tabs with no empty asides (widening instead would render empty asides — issue's warned-against option, correctly avoided).
  4. Shared shell: .profile-layout renders on all three views, main column carries all three view() branches (profile/reps/orgs gates at Repos.jsx:432/530/585), sidebar shell identical on every view incl. org variant (Profile | Repositories via isOrg).
  5. aria-current x3 + tab-badge (Repositories-only, shared-payload count) + !props.isOrg org gating all preserved verbatim.
  6. Deleted owner-tabs-top-435.test.js (9 tests) fully replaced, not dropped: strip-first→no-top-strip, profile-only-branch→shared-shell-on-every-view, teaser-intact→teaser-deleted (inverted), derivation/routes/gates/390px rewritten to the list shape; new file has 10 tests. Rescoped pins (422/430/421/profile-header/profile-header-403) use strict presence/absence on exact class strings — no weakening spotted; 422 dropping the Repo.jsx anatomy import is correct (list no longer reuses the repo tab bar).
  7. No top strip remains: no overflow-x-auto/whitespace-nowrap/border-b/rounded-t tokens anywhere in Repos.jsx; strip scrollbar CSS retired (.owner-tabs a is now block w-full).
    390px: grid-cols-1 base + min-w-0/flex-col/no-fixed-widths (reasoned, not browser-rendered — noted). No backend/SDK/API change (diff is web/ + docs only); no dep changes (package.json/lock/go.mod untouched). Docs: 12_web_ui.md FIXED(#437) entry accurate on design; see fix below for its test counts.

FULL-SUITE HEAD-TO-HEAD (claim rigorously reproduced):

  • PR branch: 913 total / 911 pass / 2 fail; pristine main: 912 / 910 / 2. Failing sets identical file-by-file (smoke.test.js live-server subtests only: 'built SPA shell is served' + 'hashed assets … immutable caching'). Zero PR-caused failures. Targeted re-run of the 6 touched/affected test files: 50/50 green.
  • DISCREPANCY (fixed): the PR description + docs entry claimed '810/796/14 (12 env files + 2 smoke)' — does not reproduce from the branch tip; only the 2 smoke subtests fail on both branches. Pushed docs-only correction to origin/fix/issue-437 (12_web_ui.md: 913/911/2 vs 912/910/2, +1 net new test) and re-ran green. The durable claim — all failures pre-existing, identical sets — holds.
  • vite build + esbuild green in the PR scratch (first vite failure was my own cwd mistake, reran from web/ → built in 2.30s).

MERGE RECOMMENDATION: ready to merge (after CI confirms). No structural issues; the one factual inaccuracy is already fixed on the branch.

Review of PR #439 (fix/issue-437), verified in scratch worktrees on branch tip + pristine origin/main (node v26, web/node_modules symlinked from main; no browser — node tests + source reasoning only, as instructed; no docker, no live instance touched). ACCEPTANCE CRITERIA (all 7 pass): 1. Teaser gone, tab count intact: zero 'View all →' matches anywhere in web/src/pages/Repos.jsx (the 531-549 block deleted); repos-tab count paragraph + orderByActivity payload untouched (pinned by owner-tabs-sidebar-437.test.js 'repositories tab keeps its own count paragraph'). 2. Vertical tab list, tabs-first: single <OwnerTabs … /> use at Repos.jsx:628, first child of .profile-sidebar-col above both avatar asides (asserted against Profile-actions, Organization-actions, profile-avatar, Edit-profile, Manage-organization markers). True-tab look: bordered box (border-zinc-200 dark:border-zinc-700, bg-white dark:bg-zinc-950) + active tab fills row (!bg-zinc-100 dark:!bg-zinc-800, medium type) — emerald underline fully gone, zinc both themes. 3. Gate choice correct: ungated sibling — zero <Show> between .repos-page and .profile-layout, OwnerTabs ungated, both #421 aside gates byte-identical. Anonymous sees tabs with no empty asides (widening instead would render empty asides — issue's warned-against option, correctly avoided). 4. Shared shell: .profile-layout renders on all three views, main column carries all three view() branches (profile/reps/orgs gates at Repos.jsx:432/530/585), sidebar shell identical on every view incl. org variant (Profile | Repositories via isOrg). 5. aria-current x3 + tab-badge (Repositories-only, shared-payload count) + !props.isOrg org gating all preserved verbatim. 6. Deleted owner-tabs-top-435.test.js (9 tests) fully replaced, not dropped: strip-first→no-top-strip, profile-only-branch→shared-shell-on-every-view, teaser-intact→teaser-deleted (inverted), derivation/routes/gates/390px rewritten to the list shape; new file has 10 tests. Rescoped pins (422/430/421/profile-header/profile-header-403) use strict presence/absence on exact class strings — no weakening spotted; 422 dropping the Repo.jsx anatomy import is correct (list no longer reuses the repo tab bar). 7. No top strip remains: no overflow-x-auto/whitespace-nowrap/border-b/rounded-t tokens anywhere in Repos.jsx; strip scrollbar CSS retired (.owner-tabs a is now block w-full). 390px: grid-cols-1 base + min-w-0/flex-col/no-fixed-widths (reasoned, not browser-rendered — noted). No backend/SDK/API change (diff is web/ + docs only); no dep changes (package.json/lock/go.mod untouched). Docs: 12_web_ui.md FIXED(#437) entry accurate on design; see fix below for its test counts. FULL-SUITE HEAD-TO-HEAD (claim rigorously reproduced): - PR branch: 913 total / 911 pass / 2 fail; pristine main: 912 / 910 / 2. Failing sets identical file-by-file (smoke.test.js live-server subtests only: 'built SPA shell is served' + 'hashed assets … immutable caching'). Zero PR-caused failures. Targeted re-run of the 6 touched/affected test files: 50/50 green. - DISCREPANCY (fixed): the PR description + docs entry claimed '810/796/14 (12 env files + 2 smoke)' — does not reproduce from the branch tip; only the 2 smoke subtests fail on both branches. Pushed docs-only correction to origin/fix/issue-437 (12_web_ui.md: 913/911/2 vs 912/910/2, +1 net new test) and re-ran green. The durable claim — all failures pre-existing, identical sets — holds. - vite build + esbuild green in the PR scratch (first vite failure was my own cwd mistake, reran from web/ → built in 2.30s). MERGE RECOMMENDATION: ready to merge (after CI confirms). No structural issues; the one factual inaccuracy is already fixed on the branch.
Author
Owner

Fixed by PR #439 (review clean + test-count doc fix by reviewer; all 7 criteria pass, coverage replaced not dropped, zero PR-caused failures), merged. Closing.

Fixed by PR #439 (review clean + test-count doc fix by reviewer; all 7 criteria pass, coverage replaced not dropped, zero PR-caused failures), 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#437
No description provided.