From e8ebe685763f6ce0d8932a13ac548d6bbc084b72 Mon Sep 17 00:00:00 2001 From: 777genius Date: Thu, 23 Apr 2026 02:22:20 +0300 Subject: [PATCH] fix(team): keep member launch labels consistent --- .../components/team/members/MemberCard.tsx | 13 ++++--- .../team/members/MemberDetailHeader.tsx | 2 +- .../team/members/MemberHoverCard.tsx | 2 +- .../team/members/MemberCard.test.ts | 37 ++++++++++++++++++- .../team/members/MemberDetailHeader.test.ts | 1 + .../team/members/MemberHoverCard.test.ts | 2 + 6 files changed, 49 insertions(+), 8 deletions(-) diff --git a/src/renderer/components/team/members/MemberCard.tsx b/src/renderer/components/team/members/MemberCard.tsx index 7b0e01c4..55db083a 100644 --- a/src/renderer/components/team/members/MemberCard.tsx +++ b/src/renderer/components/team/members/MemberCard.tsx @@ -126,6 +126,10 @@ export const MemberCard = ({ const spawnCardClass = launchPresentation.cardClass; const launchVisualState = launchPresentation.launchVisualState; const launchStatusLabel = launchPresentation.launchStatusLabel; + const displayPresenceLabel = + launchVisualState === 'runtime_pending' || launchVisualState === 'permission_pending' + ? (launchStatusLabel ?? presenceLabel) + : presenceLabel; const colors = getTeamColorSet(memberColor); const { isLight } = useTheme(); const pending = taskCounts?.pending ?? 0; @@ -155,8 +159,7 @@ export const MemberCard = ({ (presenceLabel === 'starting' || presenceLabel === 'connecting' || launchVisualState === 'runtime_pending'); - const launchBadgeLabel = - presenceLabel === 'starting' ? presenceLabel : (launchStatusLabel ?? presenceLabel); + const launchBadgeLabel = presenceLabel === 'starting' ? presenceLabel : displayPresenceLabel; const showRuntimeAdvisoryBadge = !isRemoved && Boolean(runtimeAdvisoryLabel) && @@ -201,7 +204,7 @@ export const MemberCard = ({
@@ -295,7 +298,7 @@ export const MemberCard = ({ variant="secondary" className="shrink-0 bg-red-500/15 px-1.5 py-0.5 text-[10px] font-normal leading-none text-red-400" > - {presenceLabel} + {displayPresenceLabel} @@ -325,7 +328,7 @@ export const MemberCard = ({ className={`shrink-0 px-1.5 py-0.5 text-[10px] font-normal leading-none ${isRemoved ? 'bg-zinc-600 text-zinc-300' : 'text-[var(--color-text-muted)]'}`} title={isRemoved ? 'This member has been removed' : activityTitle} > - {isRemoved ? 'removed' : presenceLabel} + {isRemoved ? 'removed' : displayPresenceLabel} ) : null} {showStartingSkeleton ? ( diff --git a/src/renderer/components/team/members/MemberDetailHeader.tsx b/src/renderer/components/team/members/MemberDetailHeader.tsx index f6b910b4..e159488a 100644 --- a/src/renderer/components/team/members/MemberDetailHeader.tsx +++ b/src/renderer/components/team/members/MemberDetailHeader.tsx @@ -105,7 +105,7 @@ export const MemberDetailHeader = ({ />
diff --git a/src/renderer/components/team/members/MemberHoverCard.tsx b/src/renderer/components/team/members/MemberHoverCard.tsx index 0ed187ad..2ab37e50 100644 --- a/src/renderer/components/team/members/MemberHoverCard.tsx +++ b/src/renderer/components/team/members/MemberHoverCard.tsx @@ -157,7 +157,7 @@ export const MemberHoverCard = ({ />
diff --git a/test/renderer/components/team/members/MemberCard.test.ts b/test/renderer/components/team/members/MemberCard.test.ts index fd23edf4..3ce27e9b 100644 --- a/test/renderer/components/team/members/MemberCard.test.ts +++ b/test/renderer/components/team/members/MemberCard.test.ts @@ -201,6 +201,41 @@ describe('MemberCard starting-state visuals', () => { }); }); + it('keeps runtime-pending accessibility copy honest even when launch badge is hidden by an active task', async () => { + vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true); + const host = document.createElement('div'); + document.body.appendChild(host); + const root = createRoot(host); + + await act(async () => { + root.render( + React.createElement(MemberCard, { + member: { + ...member, + currentTaskId: currentTask.id, + }, + memberColor: 'blue', + currentTask, + isTeamAlive: true, + isTeamProvisioning: false, + spawnStatus: 'online', + spawnLaunchState: 'runtime_pending_bootstrap', + spawnRuntimeAlive: true, + spawnLivenessSource: 'process', + }) + ); + await Promise.resolve(); + }); + + expect(host.textContent).not.toContain('online'); + expect(host.querySelector('[aria-label="connecting"]')).not.toBeNull(); + + await act(async () => { + root.unmount(); + await Promise.resolve(); + }); + }); + it('keeps the starting treatment and runtime summary visible while a runtime is still joining', async () => { vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true); const host = document.createElement('div'); @@ -258,7 +293,7 @@ describe('MemberCard starting-state visuals', () => { }); expect(host.textContent).toContain('awaiting permission'); - expect(host.querySelector('[aria-label="connecting"]')).not.toBeNull(); + expect(host.querySelector('[aria-label="awaiting permission"]')).not.toBeNull(); expect(host.querySelector('.member-waiting-shimmer')).not.toBeNull(); await act(async () => { diff --git a/test/renderer/components/team/members/MemberDetailHeader.test.ts b/test/renderer/components/team/members/MemberDetailHeader.test.ts index 2cdfdd8d..17c21bd5 100644 --- a/test/renderer/components/team/members/MemberDetailHeader.test.ts +++ b/test/renderer/components/team/members/MemberDetailHeader.test.ts @@ -123,6 +123,7 @@ describe('MemberDetailHeader spawn-aware presence', () => { expect(host.textContent).toContain('connecting'); expect(host.textContent).not.toContain('online'); + expect(host.querySelector('[aria-label="connecting"]')).not.toBeNull(); await act(async () => { root.unmount(); diff --git a/test/renderer/components/team/members/MemberHoverCard.test.ts b/test/renderer/components/team/members/MemberHoverCard.test.ts index f9fe301d..fe06f72b 100644 --- a/test/renderer/components/team/members/MemberHoverCard.test.ts +++ b/test/renderer/components/team/members/MemberHoverCard.test.ts @@ -190,6 +190,7 @@ describe('MemberHoverCard spawn-aware presence', () => { expect(host.textContent).toContain('connecting'); expect(host.textContent).not.toContain('online'); + expect(host.querySelector('[aria-label="connecting"]')).not.toBeNull(); await act(async () => { root.unmount(); @@ -225,6 +226,7 @@ describe('MemberHoverCard spawn-aware presence', () => { expect(host.textContent).toContain('connecting'); expect(host.textContent).not.toContain('online'); + expect(host.querySelector('[aria-label="connecting"]')).not.toBeNull(); await act(async () => { root.unmount();