1- import { For , createEffect , createMemo , on , onCleanup , Show , Index , type JSX } from "solid-js"
1+ import { For , createEffect , createMemo , on , onCleanup , Show , Index , type JSX , createSignal } from "solid-js"
22import { createStore , produce } from "solid-js/store"
33import { useNavigate , useParams } from "@solidjs/router"
44import { Button } from "@opencode-ai/ui/button"
@@ -23,6 +23,7 @@ import { useSDK } from "@/context/sdk"
2323import { useSync } from "@/context/sync"
2424import { messageAgentColor } from "@/utils/agent"
2525import { parseCommentNote , readCommentMetadata } from "@/utils/comment-note"
26+ import { makeTimer } from "@solid-primitives/timer"
2627
2728type MessageComment = {
2829 path : string
@@ -239,38 +240,21 @@ export function MessageTimeline(props: {
239240 const working = createMemo ( ( ) => ! ! pending ( ) || sessionStatus ( ) . type !== "idle" )
240241 const tint = createMemo ( ( ) => messageAgentColor ( sessionMessages ( ) , sync . data . agent ) )
241242
242- const [ slot , setSlot ] = createStore ( {
243- open : false ,
244- show : false ,
245- fade : false ,
243+ const [ timeoutDone , setTimeoutDone ] = createSignal ( true )
244+
245+ const workingStatus = createMemo < "hidden" | "showing" | "hiding" > ( ( prev ) => {
246+ if ( working ( ) ) return "showing"
247+ if ( prev === "showing" || ! timeoutDone ( ) ) return "hiding"
248+ return "hidden"
246249 } )
247250
248- let f : number | undefined
249- const clear = ( ) => {
250- if ( f !== undefined ) window . clearTimeout ( f )
251- f = undefined
252- }
251+ createEffect ( ( ) => {
252+ if ( workingStatus ( ) !== "hiding" ) return
253+
254+ setTimeoutDone ( false )
255+ makeTimer ( ( ) => setTimeoutDone ( true ) , 260 , setTimeout )
256+ } )
253257
254- onCleanup ( clear )
255- createEffect (
256- on (
257- working ,
258- ( on , prev ) => {
259- clear ( )
260- if ( on ) {
261- setSlot ( { open : true , show : true , fade : false } )
262- return
263- }
264- if ( prev ) {
265- setSlot ( { open : false , show : true , fade : true } )
266- f = window . setTimeout ( ( ) => setSlot ( { show : false , fade : false } ) , 260 )
267- return
268- }
269- setSlot ( { open : false , show : false , fade : false } )
270- } ,
271- { defer : true } ,
272- ) ,
273- )
274258 const activeMessageID = createMemo ( ( ) => {
275259 const parentID = pending ( ) ?. parentID
276260 if ( parentID ) {
@@ -609,13 +593,19 @@ export function MessageTimeline(props: {
609593 aria-label = { language . t ( "common.goBack" ) }
610594 />
611595 </ Show >
612- < Show when = { titleValue ( ) || title . editing } >
613- < Show
614- when = { title . editing }
615- fallback = {
616- < h1
617- class = "text-14-medium text-text-strong truncate grow-1 min-w-0 pl-2"
618- onDblClick = { openTitleEditor }
596+ < div class = "flex items-center min-w-0 grow-1" >
597+ < div
598+ class = "shrink-0 flex items-center justify-center overflow-hidden transition-[width,margin] duration-300 ease-[cubic-bezier(0.22,1,0.36,1)]"
599+ style = { {
600+ width : working ( ) ? "16px" : "0px" ,
601+ "margin-right" : working ( ) ? "8px" : "0px" ,
602+ } }
603+ aria-hidden = "true"
604+ >
605+ < Show when = { workingStatus ( ) !== "hidden" } >
606+ < div
607+ class = "transition-opacity duration-200 ease-out"
608+ classList = { { "opacity-0" : workingStatus ( ) === "hiding" } }
619609 >
620610 < Spinner class = "size-4" style = { { color : tint ( ) ?? "var(--icon-interactive-base)" } } />
621611 </ div >
@@ -713,7 +703,6 @@ export function MessageTimeline(props: {
713703 </ div >
714704 </ div >
715705 </ Show >
716-
717706 < div
718707 role = "log"
719708 class = "flex flex-col gap-12 items-start justify-start pb-16 transition-[margin]"
0 commit comments