Animate player display inactive transitions and death state

Player display now tracks displayParticipants separately from raw encounter
participants so active->inactive can animate out before removal, and inactive->
active can animate in. This preserves 1-list order, keeps DM display behavior
unchanged, and avoids fading dying/stable participants.

PlayerParticipantCard handles transitions:
- active->inactive: scale/slide/fade out, then parent removes from display list
- inactive->active: scale/slide/fade in
- alive->dead: keep visible with dim/desaturate/red-rim death cue + skull pulse
- dying/stable: full visible, no fade/removal

DisplayView inactive characterization updated to wait for exit animation before
asserting removal. TODO item removed.
This commit is contained in:
david raistrick
2026-07-06 22:38:33 -04:00
parent 055895875a
commit 3b75ec9b3d
3 changed files with 97 additions and 25 deletions
@@ -94,7 +94,7 @@ describe('DisplayView characterization', () => {
expect(screen.getAllByText(/Dead/i).length).toBeGreaterThan(0);
});
test('DisplayView hides inactive participants for all types', async () => {
test('DisplayView hides inactive participants for all types after fade-out', async () => {
seedActiveDisplay([
{ ...participant('conscious'), id: 'active-pc', name: 'Active PC', isActive: true },
{ ...participant('conscious'), id: 'inactive-pc', name: 'Inactive PC', isActive: false },
@@ -103,7 +103,8 @@ describe('DisplayView characterization', () => {
render(<App />);
await waitFor(() => expect(screen.getByText('Active PC')).toBeInTheDocument());
expect(screen.queryByText('Inactive PC')).not.toBeInTheDocument();
// inactive held during exit animation, removed after transition
await waitFor(() => expect(screen.queryByText('Inactive PC')).not.toBeInTheDocument(), { timeout: 1500 });
expect(screen.queryByText('Inactive Monster')).not.toBeInTheDocument();
});
});