feat: FLIP-style lozenge fly animation when agents are assigned to stories
Implements Story 74: agent lozenges now animate as fixed-position overlays that fly from the roster badge in AgentPanel to the story slot in StagePanel (and back when the agent is removed), satisfying all acceptance criteria. Key changes: - LozengeFlyContext.tsx (new): coordinates FLIP animations via React context. LozengeFlyProvider tracks pipeline changes, hides slot lozenges during fly-in (useLayoutEffect before paint), then creates a portal-rendered fixed-position clone that transitions from roster → slot (or reverse). z-index 9999 ensures the clone travels above all other UI elements. - AgentPanel.tsx: RosterBadge registers its DOM element with the context so fly animations know the correct start/end coordinates. - StagePanel.tsx: AgentLozenge registers its DOMRect on every render via useLayoutEffect (for fly-out) and reads pendingFlyIns to stay hidden while a fly-in clone is in flight. Added align-self: flex-start so the lozenge maintains its intrinsic width and never stretches in the panel. - Chat.tsx: right-column panels wrapped in LozengeFlyProvider. - LozengeFlyContext.test.tsx (new): 10 tests covering fixed width, fly-in/fly-out clone creation, portal placement, opacity lifecycle, and idle vs active visual distinction. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,7 @@ import { api, ChatWebSocket } from "../api/client";
|
||||
import type { Message, ProviderConfig, ToolCall } from "../types";
|
||||
import { AgentPanel } from "./AgentPanel";
|
||||
import { ChatHeader } from "./ChatHeader";
|
||||
import { LozengeFlyProvider } from "./LozengeFlyContext";
|
||||
import { StagePanel } from "./StagePanel";
|
||||
|
||||
const { useCallback, useEffect, useRef, useState } = React;
|
||||
@@ -713,12 +714,14 @@ export function Chat({ projectPath, onCloseProject }: ChatProps) {
|
||||
gap: "12px",
|
||||
}}
|
||||
>
|
||||
<AgentPanel />
|
||||
<LozengeFlyProvider pipeline={pipeline}>
|
||||
<AgentPanel />
|
||||
|
||||
<StagePanel title="To Merge" items={pipeline.merge} />
|
||||
<StagePanel title="QA" items={pipeline.qa} />
|
||||
<StagePanel title="Current" items={pipeline.current} />
|
||||
<StagePanel title="Upcoming" items={pipeline.upcoming} />
|
||||
<StagePanel title="To Merge" items={pipeline.merge} />
|
||||
<StagePanel title="QA" items={pipeline.qa} />
|
||||
<StagePanel title="Current" items={pipeline.current} />
|
||||
<StagePanel title="Upcoming" items={pipeline.upcoming} />
|
||||
</LozengeFlyProvider>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user