From 473731479b1168c4591a293cc578badcbee2d6cc Mon Sep 17 00:00:00 2001
From: T3 Code PR Stack <41898282+github-actions[bot]@users.noreply.github.com>
Date: Fri, 31 Jul 2026 11:05:06 +0200
Subject: [PATCH 1/2] feat(identity): merge participation into count badge
---
.../features/identity/ParticipantStack.tsx | 28 +++++++++----------
.../identity/participantStackSurface.test.ts | 5 +++-
.../components/identity/ParticipantStack.tsx | 21 ++++++--------
apps/web/src/forkSurfaceExistence.test.ts | 5 +++-
4 files changed, 31 insertions(+), 28 deletions(-)
diff --git a/apps/mobile/src/features/identity/ParticipantStack.tsx b/apps/mobile/src/features/identity/ParticipantStack.tsx
index eda60df41f6..6dd6ca208b3 100644
--- a/apps/mobile/src/features/identity/ParticipantStack.tsx
+++ b/apps/mobile/src/features/identity/ParticipantStack.tsx
@@ -56,25 +56,25 @@ export function ParticipantStack(props: {
/>
{extras.length > 0 ? (
-
+
+{extras.length}
) : null}
- {youParticipated ? (
-
- ✓
-
- ) : null}
);
}
diff --git a/apps/mobile/src/features/identity/participantStackSurface.test.ts b/apps/mobile/src/features/identity/participantStackSurface.test.ts
index ef64d87a877..a5b69d389f2 100644
--- a/apps/mobile/src/features/identity/participantStackSurface.test.ts
+++ b/apps/mobile/src/features/identity/participantStackSurface.test.ts
@@ -13,7 +13,10 @@ describe("mobile participation indicator surface", () => {
const listV2 = readSource("../threads/thread-list-v2-items.tsx");
const board = readSource("../board/BoardScreen.tsx");
- expect(stack).toContain('testID="you-participated-indicator"');
+ expect(stack).toContain('testID={youParticipated ? "you-participated-indicator"');
+ expect(stack).toContain("+{extras.length}");
+ expect(stack).toContain('"border border-primary bg-primary/15"');
+ expect(stack).not.toContain(">✓");
expect(stack).toContain("isClaimedNonStarterParticipant");
expect(stack).toContain("You participated");
expect(listV1).toContain("environmentId={thread.environmentId}");
diff --git a/apps/web/src/components/identity/ParticipantStack.tsx b/apps/web/src/components/identity/ParticipantStack.tsx
index 760fa81b147..edfcb097c64 100644
--- a/apps/web/src/components/identity/ParticipantStack.tsx
+++ b/apps/web/src/components/identity/ParticipantStack.tsx
@@ -4,7 +4,6 @@ import {
isClaimedNonStarterParticipant,
} from "@t3tools/client-runtime/state/identity";
import type { ThreadParticipantSummary } from "@t3tools/contracts";
-import { CheckIcon } from "lucide-react";
import { identityClaimPersonIdByEnvironmentAtom } from "../../state/identity";
import { IdentityAvatar } from "./IdentityAvatar";
import { participantDisplayLabel } from "./ParticipantStack.logic";
@@ -56,21 +55,19 @@ export function ParticipantStack(props: {
/>
{extras.length > 0 ? (
+{extras.length}
) : null}
- {youParticipated ? (
-
-
-
- ) : null}
);
diff --git a/apps/web/src/forkSurfaceExistence.test.ts b/apps/web/src/forkSurfaceExistence.test.ts
index 22dbe806de8..0cc80ea0deb 100644
--- a/apps/web/src/forkSurfaceExistence.test.ts
+++ b/apps/web/src/forkSurfaceExistence.test.ts
@@ -137,7 +137,10 @@ describe("fork surface existence (anti stack-drop)", () => {
expect(stack).toContain("
Date: Fri, 31 Jul 2026 11:24:42 +0200
Subject: [PATCH 2/2] feat(identity): highlight claimed user avatar
---
.../src/features/identity/IdentityAvatar.tsx | 15 ++++++++++++---
.../src/features/identity/ParticipantStack.tsx | 1 +
.../identity/participantStackSurface.test.ts | 3 +++
.../src/components/identity/IdentityAvatar.tsx | 6 +++++-
.../src/components/identity/ParticipantStack.tsx | 2 ++
apps/web/src/forkSurfaceExistence.test.ts | 3 +++
6 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/apps/mobile/src/features/identity/IdentityAvatar.tsx b/apps/mobile/src/features/identity/IdentityAvatar.tsx
index 3e3ab28d65d..d640c03a80f 100644
--- a/apps/mobile/src/features/identity/IdentityAvatar.tsx
+++ b/apps/mobile/src/features/identity/IdentityAvatar.tsx
@@ -13,6 +13,7 @@ export function IdentityAvatar(props: {
readonly name?: string | null | undefined;
readonly size?: "micro" | "sm" | "md";
readonly className?: string;
+ readonly highlighted?: boolean;
}) {
const model = identityAvatar({
personId: props.personId,
@@ -26,10 +27,18 @@ export function IdentityAvatar(props: {
return (
-
+
{model.initials}
diff --git a/apps/mobile/src/features/identity/ParticipantStack.tsx b/apps/mobile/src/features/identity/ParticipantStack.tsx
index 6dd6ca208b3..b53956727cb 100644
--- a/apps/mobile/src/features/identity/ParticipantStack.tsx
+++ b/apps/mobile/src/features/identity/ParticipantStack.tsx
@@ -53,6 +53,7 @@ export function ParticipantStack(props: {
username={lead.username}
name={lead.name}
size="micro"
+ highlighted={lead.personId === claimPersonId}
/>
{extras.length > 0 ? (
{
expect(stack).toContain("+{extras.length}");
expect(stack).toContain('"border border-primary bg-primary/15"');
expect(stack).not.toContain(">✓");
+ expect(stack).toContain("highlighted={lead.personId === claimPersonId}");
+ const avatar = readSource("./IdentityAvatar.tsx");
+ expect(avatar).toContain('props.highlighted && "bg-primary"');
expect(stack).toContain("isClaimedNonStarterParticipant");
expect(stack).toContain("You participated");
expect(listV1).toContain("environmentId={thread.environmentId}");
diff --git a/apps/web/src/components/identity/IdentityAvatar.tsx b/apps/web/src/components/identity/IdentityAvatar.tsx
index d41462c5b9b..cee49d7b440 100644
--- a/apps/web/src/components/identity/IdentityAvatar.tsx
+++ b/apps/web/src/components/identity/IdentityAvatar.tsx
@@ -7,6 +7,7 @@ export function IdentityAvatar(props: {
readonly name?: string | null | undefined;
readonly size?: "micro" | "sm" | "md";
readonly className?: string;
+ readonly highlighted?: boolean;
/** `null` suppresses the native title when a parent owns richer tooltip content. */
readonly title?: string | null;
}) {
@@ -33,7 +34,10 @@ export function IdentityAvatar(props: {
sizeClass,
props.className,
)}
- style={{ backgroundColor: model.backgroundColor, color: model.color }}
+ style={{
+ backgroundColor: props.highlighted ? "var(--primary)" : model.backgroundColor,
+ color: props.highlighted ? "var(--primary-foreground)" : model.color,
+ }}
>
{model.initials}
diff --git a/apps/web/src/components/identity/ParticipantStack.tsx b/apps/web/src/components/identity/ParticipantStack.tsx
index edfcb097c64..979e6a2d4c1 100644
--- a/apps/web/src/components/identity/ParticipantStack.tsx
+++ b/apps/web/src/components/identity/ParticipantStack.tsx
@@ -52,6 +52,7 @@ export function ParticipantStack(props: {
name={lead.name}
size="micro"
title={null}
+ highlighted={lead.personId === claimPersonId}
/>
{extras.length > 0 ? (
{participantDisplayLabel(person)}
diff --git a/apps/web/src/forkSurfaceExistence.test.ts b/apps/web/src/forkSurfaceExistence.test.ts
index 0cc80ea0deb..7eb0383d37c 100644
--- a/apps/web/src/forkSurfaceExistence.test.ts
+++ b/apps/web/src/forkSurfaceExistence.test.ts
@@ -141,6 +141,9 @@ describe("fork surface existence (anti stack-drop)", () => {
expect(stack).toContain("+{extras.length}");
expect(stack).toContain('"bg-primary/15 text-primary ring-1 ring-primary/35"');
expect(stack).not.toContain("