From eb779a7cc5c1728471489a3304a6203716bd4d47 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Mon, 19 Jan 2026 10:54:56 -0600 Subject: [PATCH] chore: cleanup --- packages/ui/src/components/session-turn.css | 13 +++-- packages/ui/src/components/session-turn.tsx | 60 +++++++++++++++++++-- 2 files changed, 67 insertions(+), 6 deletions(-) diff --git a/packages/ui/src/components/session-turn.css b/packages/ui/src/components/session-turn.css index 556b357c3..5f8c0a16f 100644 --- a/packages/ui/src/components/session-turn.css +++ b/packages/ui/src/components/session-turn.css @@ -1,4 +1,6 @@ [data-component="session-turn"] { + --session-turn-sticky-height: 0px; + --sticky-header-height: calc(var(--session-title-height, 0px) + var(--session-turn-sticky-height, 0px) + 12px); /* flex: 1; */ height: 100%; min-height: 0; @@ -44,6 +46,12 @@ } } + [data-slot="session-turn-attachments"] { + width: 100%; + min-width: 0; + align-self: stretch; + } + [data-slot="session-turn-sticky"] { width: calc(100% + 9px); position: sticky; @@ -331,11 +339,10 @@ } [data-component="sticky-accordion-header"] { - top: var(--sticky-header-height, 40px); + top: var(--sticky-header-height, 0px); &[data-expanded]::before { - top: calc(-1 * var(--sticky-header-height, 40px)); + top: calc(-1 * var(--sticky-header-height, 0px)); } - /* position: static; */ } [data-slot="session-turn-accordion-trigger-content"] { diff --git a/packages/ui/src/components/session-turn.tsx b/packages/ui/src/components/session-turn.tsx index e5fe4ba1c..a918f0ae4 100644 --- a/packages/ui/src/components/session-turn.tsx +++ b/packages/ui/src/components/session-turn.tsx @@ -1,5 +1,6 @@ import { AssistantMessage, + FilePart, Message as MessageType, Part as PartType, type PermissionRequest, @@ -29,6 +30,7 @@ import { Spinner } from "./spinner" import { createStore } from "solid-js/store" import { DateTime, DurationUnit, Interval } from "luxon" import { createAutoScroll } from "../hooks" +import { createResizeObserver } from "@solid-primitives/resize-observer" function computeStatusFromPart(part: PartType | undefined): string | undefined { if (!part) return undefined @@ -75,6 +77,12 @@ function same(a: readonly T[], b: readonly T[]) { return a.every((x, i) => x === b[i]) } +function isAttachment(part: PartType | undefined) { + if (part?.type !== "file") return false + const mime = (part as FilePart).mime ?? "" + return mime.startsWith("image/") || mime === "application/pdf" +} + function AssistantMessageItem(props: { message: AssistantMessage responsePartId: string | undefined @@ -133,6 +141,7 @@ export function SessionTurn( const emptyMessages: MessageType[] = [] const emptyParts: PartType[] = [] + const emptyFiles: FilePart[] = [] const emptyAssistant: AssistantMessage[] = [] const emptyPermissions: PermissionRequest[] = [] const emptyPermissionParts: { part: ToolPart; message: AssistantMessage }[] = [] @@ -180,6 +189,19 @@ export function SessionTurn( return data.store.part[msg.id] ?? emptyParts }) + const attachmentParts = createMemo(() => { + const msgParts = parts() + if (msgParts.length === 0) return emptyFiles + return msgParts.filter((part) => isAttachment(part)) as FilePart[] + }) + + const stickyParts = createMemo(() => { + const msgParts = parts() + if (msgParts.length === 0) return emptyParts + if (attachmentParts().length === 0) return msgParts + return msgParts.filter((part) => !isAttachment(part)) + }) + const assistantMessages = createMemo( () => { const msg = message() @@ -331,6 +353,15 @@ export function SessionTurn( const hideResponsePart = createMemo(() => !working() && !!responsePartId()) const [responseCopied, setResponseCopied] = createSignal(false) + const [rootRef, setRootRef] = createSignal() + const [stickyRef, setStickyRef] = createSignal() + + const updateStickyHeight = (height: number) => { + const root = rootRef() + if (!root) return + const next = Math.ceil(height) + root.style.setProperty("--session-turn-sticky-height", `${next}px`) + } const handleCopyResponse = async () => { const content = response() if (!content) return @@ -361,6 +392,24 @@ export function SessionTurn( onUserInteracted: props.onUserInteracted, }) + createResizeObserver( + () => stickyRef(), + ({ height }) => { + updateStickyHeight(height) + }, + ) + + createEffect(() => { + const root = rootRef() + if (!root) return + const sticky = stickyRef() + if (!sticky) { + root.style.setProperty("--session-turn-sticky-height", "0px") + return + } + updateStickyHeight(sticky.getBoundingClientRect().height) + }) + const diffInit = 20 const diffBatch = 20 @@ -438,7 +487,7 @@ export function SessionTurn( }) return ( -
+
-
+ 0}> +
+ +
+
+
{/* User Message */}
- +
{/* Trigger (sticky) */}