@@ -2,9 +2,10 @@ import { Icon } from "@opencode/ui/icon"
22import { IconButton } from "@opencode/ui/icon-button"
33import { Menu } from "@opencode/ui/menu"
44import { SessionProgressIndicatorV2 } from "@opencode/session-ui/v2/session-progress-indicator-v2"
5- import { createEffect , createMemo , createSignal , For , onCleanup , Show } from "solid-js"
5+ import { createEffect , createSignal , For , onCleanup , Show } from "solid-js"
66import { useLanguage } from "@/runtime/i18n/language"
77import { useSettings } from "@/settings/model"
8+ import { useComposerLaneAlignment } from "./composer-lane"
89import "./activity-chips.css"
910
1011export type SessionActivityItem = {
@@ -42,8 +43,7 @@ export function formatElapsed(ms: number, t: (key: DurationKey, params: Record<s
4243 } )
4344}
4445
45- // Live work above the composer, one capsule like the iOS app's background-work summary. It floats out of flow in a
46- // lane the timeline reserves at its tail, so coming and going never resizes the composer region or moves the timeline.
46+ // Live work above the composer, one capsule like the iOS app's background-work summary, in the composer lane.
4747export function SessionActivityChips ( props : {
4848 subagents : readonly SessionActivityItem [ ]
4949 shells : readonly SessionActivityItem [ ]
@@ -56,16 +56,9 @@ export function SessionActivityChips(props: {
5656 const active = ( ) =>
5757 settings . general . backgroundActivity ( ) !== "off" && ( props . subagents . length > 0 || props . shells . length > 0 )
5858
59- const alignment = createMemo ( ( ) => {
60- const value = settings . general . backgroundActivity ( )
59+ const alignment = useComposerLaneAlignment ( )
6160
62- if ( value === "center" ) return "center"
63-
64- // Left/right are physical positions; Kobalte and flex alignment use logical start/end.
65- return ( value === "left" ) !== ( language . direction ( ) === "rtl" ) ? "start" : "end"
66- } )
67-
68- const placement = ( ) => ( { center : "top" , start : "top-start" , end : "top-end" } as const ) [ alignment ( ) ]
61+ const placement = ( ) => ( ( { center : "top" , start : "top-start" , end : "top-end" } ) as const ) [ alignment ( ) ]
6962
7063 // A subagent can only be interrupted once its child session exists.
7164 const stoppable = ( item : SessionActivityItem ) => item . type === "shell" || ! ! item . sessionID
@@ -143,15 +136,7 @@ export function SessionActivityChips(props: {
143136
144137 return (
145138 < Show when = { active ( ) } >
146- < div
147- data-component = "session-activity-chips"
148- class = "pointer-events-none absolute inset-x-0 bottom-full flex items-center pb-2.5"
149- classList = { {
150- "justify-start" : alignment ( ) === "start" ,
151- "justify-center" : alignment ( ) === "center" ,
152- "justify-end" : alignment ( ) === "end" ,
153- } }
154- >
139+ < div data-component = "session-activity-chips" class = "flex min-w-0 shrink items-center" >
155140 < Menu gutter = { 8 } placement = { placement ( ) } onOpenChange = { setOpen } >
156141 < Menu . Trigger
157142 as = "button"
0 commit comments