authorgravatar for maria@kuuro.netmaria <maria@kuuro.net> 2026-09-10 15:24:25-03:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-10 15:24:25-03:00
loge784975bbec7c54ed75fc6da3d4ffd4038fae041
treed8f788e936be6aa2f666768d56bc3e34ebc57b26
parent3836890e4484406813997259efc69065b25ce698
signature Signed by PGP key B5690EEEBB952194

fix(ui): simplify multiple linked pull request badges (#11104)


5 files changed, 24 insertions(+), 12 deletions(-)

apps/mobile/src/features/threads/thread-list-v2-items.tsx+10-4
...@@ -871,16 +871,22 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: {...@@ -871,16 +871,22 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: {
871 )}871 )}
872 {pr ? (872 {pr ? (
873 <View className="flex-row items-center gap-1" accessibilityLabel={pr.accessibilityLabel}>873 <View className="flex-row items-center gap-1" accessibilityLabel={pr.accessibilityLabel}>
874 {pr.kind === "stack" ? (874 {pr.kind === "stack" || pr.others > 0 ? (
875 <SymbolView875 <SymbolView
876 name="square.3.layers.3d"876 name={pr.kind === "stack" ? "square.3.layers.3d" : "arrow.triangle.pull"}
877 size={12}877 size={12}
878 tintColorClassName={878 tintColorClassName={
879 selected879 selected
880 ? materialYouStyleLayoutActive880 ? materialYouStyleLayoutActive
881 ? "accent-thread-selected-foreground"881 ? "accent-thread-selected-foreground"
882 : "accent-user-bubble-foreground"882 : "accent-user-bubble-foreground"
883 : "accent-foreground-muted"883 : pr.kind === "stack" || pr.isDraft || pr.state === null
884 ? "accent-foreground-muted"
885 : pr.state === "open"
886 ? "accent-adaptive-emerald-600-400"
887 : pr.state === "merged"
888 ? "accent-adaptive-violet-600-400"
889 : "accent-foreground-muted"
884 }890 }
885 />891 />
886 ) : null}892 ) : null}
...@@ -896,7 +902,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: {...@@ -896,7 +902,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: {
896 )}902 )}
897 style={{ fontFamily: MONO_FONT }}903 style={{ fontFamily: MONO_FONT }}
898 >904 >
899 {pr.kind === "stack" ? pr.label : `#${pr.label}`}905 {pr.kind === "stack" || pr.others > 0 ? pr.label : `#${pr.label}`}
900 </Text>906 </Text>
901 </View>907 </View>
902 ) : null}908 ) : null}
apps/mobile/src/state/thread-pr-presentation.ts+7-2
...@@ -17,11 +17,12 @@ export interface ThreadPrPresentation {...@@ -17,11 +17,12 @@ export interface ThreadPrPresentation {
17 readonly number: number;17 readonly number: number;
18 readonly state: ThreadPr["state"] | null;18 readonly state: ThreadPr["state"] | null;
19 readonly kind: "pull-request" | "stack";19 readonly kind: "pull-request" | "stack";
20 readonly others: number;
20 readonly isDraft: boolean;21 readonly isDraft: boolean;
21 /** Provider-side last activity, bounding when a terminal state landed. */22 /** Provider-side last activity, bounding when a terminal state landed. */
22 readonly updatedAt: string | null;23 readonly updatedAt: string | null;
23 readonly url: string;24 readonly url: string;
24 /** Compact pull request number label, e.g. "3774". */25 /** Compact pull request number or linked count, e.g. "3774" or "+2". */
25 readonly label: string;26 readonly label: string;
26 /** Full, provider-aware label for assistive technologies. */27 /** Full, provider-aware label for assistive technologies. */
27 readonly accessibilityLabel: string;28 readonly accessibilityLabel: string;
...@@ -42,6 +43,7 @@ export function presentThreadPr(...@@ -42,6 +43,7 @@ export function presentThreadPr(
42 const isDraft = pr.state === "open" && pr.isDraft === true;43 const isDraft = pr.state === "open" && pr.isDraft === true;
43 return {44 return {
44 kind: "pull-request",45 kind: "pull-request",
46 others: 0,
45 number: pr.number,47 number: pr.number,
46 state: pr.state,48 state: pr.state,
47 isDraft,49 isDraft,
...@@ -66,9 +68,12 @@ export function presentThreadLinkedPullRequests(...@@ -66,9 +68,12 @@ export function presentThreadLinkedPullRequests(
66 const label =68 const label =
67 badge.kind === "stack"69 badge.kind === "stack"
68 ? String(badge.layers)70 ? String(badge.layers)
69 : `${link.number}${badge.others > 0 ? ` +${badge.others}` : ""}`;71 : badge.others > 0
72 ? `+${badge.others}`
73 : String(link.number);
70 return {74 return {
71 kind: badge.kind,75 kind: badge.kind,
76 others: badge.kind === "pull-request" ? badge.others : 0,
72 number: link.number,77 number: link.number,
73 state,78 state,
74 isDraft,79 isDraft,
apps/mobile/src/state/use-thread-pr.test.ts+1-1
...@@ -87,7 +87,7 @@ describe("presentThreadLinkedPullRequests", () => {...@@ -87,7 +87,7 @@ describe("presentThreadLinkedPullRequests", () => {
87 it("counts unrelated links without labelling them a stack", () => {87 it("counts unrelated links without labelling them a stack", () => {
88 expect(presentThreadLinkedPullRequests([linkedPr(1), linkedPr(2)])).toMatchObject({88 expect(presentThreadLinkedPullRequests([linkedPr(1), linkedPr(2)])).toMatchObject({
89 kind: "pull-request",89 kind: "pull-request",
90 label: "1 +1",90 label: "+1",
91 });91 });
92 });92 });
9393
apps/web/src/components/Sidebar.tsx+1-1
...@@ -1485,7 +1485,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: {...@@ -1485,7 +1485,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: {
1485 </span>1485 </span>
1486 );1486 );
14871487
1488 // Stacks show their layer count; unrelated links show the current PR and a remainder count.1488 // Stacks show their layer count; unrelated links show only the remainder count.
1489 // Plain clicks open T3; individual PR links also support opening the host in a new tab.1489 // Plain clicks open T3; individual PR links also support opening the host in a new tab.
1490 const prBadgeShape = supportsMultiplePullRequests1490 const prBadgeShape = supportsMultiplePullRequests
1491 ? resolveThreadPullRequestBadge(thread.pullRequests)1491 ? resolveThreadPullRequestBadge(thread.pullRequests)
apps/web/src/components/ThreadStatusIndicators.tsx+5-4
...@@ -174,10 +174,11 @@ export function ThreadPullRequestBadgeControl({...@@ -174,10 +174,11 @@ export function ThreadPullRequestBadgeControl({
174 const content = (174 const content = (
175 <>175 <>
176 <ThreadPullRequestBadgeIcon icon={badge?.kind ?? "pull-request"} />176 <ThreadPullRequestBadgeIcon icon={badge?.kind ?? "pull-request"} />
177 {isStack ? badge.layers : number}177 {isStack
178 {badge?.kind === "pull-request" && badge.others > 0 ? (178 ? badge.layers
179 <span className="opacity-70">+{badge.others}</span>179 : badge?.kind === "pull-request" && badge.others > 0
180 ) : null}180 ? `+${badge.others}`
181 : number}
181 </>182 </>
182 );183 );
183 return (184 return (