From 297d2ef5de2c09716c8b091bbb4075da9d7f1012 Mon Sep 17 00:00:00 2001 From: Jiayuan Zhang Date: Sun, 17 May 2026 01:22:43 +0800 Subject: [PATCH] fix(views): collapse PR cards at N>=4, not N>4 The card-vs-collapse threshold used `>` so 4 PRs slipped past it and all rendered as full cards, contrary to RFC v3 (N >= 4 collapses to 3 cards + compact tail). Switch to `>=` and update the threshold- boundary test to expect "Show 1 more". Co-authored-by: multica-agent --- .../issues/components/pull-request-list.test.tsx | 9 ++++++--- .../views/issues/components/pull-request-list.tsx | 13 +++++++------ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/views/issues/components/pull-request-list.test.tsx b/packages/views/issues/components/pull-request-list.test.tsx index 66b4a02755..65edf19d9f 100644 --- a/packages/views/issues/components/pull-request-list.test.tsx +++ b/packages/views/issues/components/pull-request-list.test.tsx @@ -170,7 +170,7 @@ describe("PullRequestList card layout", () => { expect(screen.getByText("Show 2 more")).toBeInTheDocument(); }); - it("renders all four PRs as cards when count == threshold", async () => { + it("collapses to 3 cards + compact tail when count == threshold", async () => { mockPRs = [ makePR({ id: "a", number: 1, title: "PR-A" }), makePR({ id: "b", number: 2, title: "PR-B" }), @@ -179,7 +179,10 @@ describe("PullRequestList card layout", () => { ]; renderList(); await waitForRender(); - expect(screen.getByText("PR-D")).toBeInTheDocument(); - expect(screen.queryByText(/Show.*more/)).not.toBeInTheDocument(); + expect(screen.getByText("PR-A")).toBeInTheDocument(); + expect(screen.getByText("PR-B")).toBeInTheDocument(); + expect(screen.getByText("PR-C")).toBeInTheDocument(); + expect(screen.queryByText("PR-D")).not.toBeInTheDocument(); + expect(screen.getByText("Show 1 more")).toBeInTheDocument(); }); }); diff --git a/packages/views/issues/components/pull-request-list.tsx b/packages/views/issues/components/pull-request-list.tsx index 7a1139e02f..14455e5eda 100644 --- a/packages/views/issues/components/pull-request-list.tsx +++ b/packages/views/issues/components/pull-request-list.tsx @@ -30,9 +30,10 @@ import { cn } from "@multica/ui/lib/utils"; import { useT } from "../../i18n"; // Card layout takes ~4× the vertical space of the legacy row. Past 3 cards -// the sidebar feels packed, so we expand the first N inline and collapse the -// rest behind a "Show more" toggle that renders them as the legacy compact -// rows. 4 is the threshold per Xeon's RFC v3 increment. +// the sidebar feels packed, so once we hit this threshold we collapse: show +// (LIMIT - 1) cards inline and push the rest behind a "Show more" toggle as +// legacy compact rows. 4 is the threshold per Xeon's RFC v3 increment, so +// N >= 4 collapses to 3 cards + compact tail. const CARD_LIMIT_BEFORE_COLLAPSE = 4; const STATE_ICON: Record< @@ -72,11 +73,11 @@ export function PullRequestList({ issueId }: { issueId: string }) { } // Render rule: - // - <= CARD_LIMIT_BEFORE_COLLAPSE: every PR as a card. - // - > CARD_LIMIT_BEFORE_COLLAPSE: first (LIMIT - 1) as cards, the + // - < CARD_LIMIT_BEFORE_COLLAPSE: every PR as a card. + // - >= CARD_LIMIT_BEFORE_COLLAPSE: first (LIMIT - 1) as cards, the // remainder as compact rows behind a toggle. Keeping LIMIT-1 visible // before the toggle leaves room for the toggle itself without overflow. - const useCollapse = prs.length > CARD_LIMIT_BEFORE_COLLAPSE; + const useCollapse = prs.length >= CARD_LIMIT_BEFORE_COLLAPSE; const expandedHead = useCollapse ? prs.slice(0, CARD_LIMIT_BEFORE_COLLAPSE - 1) : prs; const collapsedTail = useCollapse ? prs.slice(CARD_LIMIT_BEFORE_COLLAPSE - 1) : [];