From 5cf6a1343c6ca088bd2b586197faf7fe58961290 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Mon, 15 Dec 2025 09:34:00 -0600 Subject: wip(desktop): progress --- packages/ui/src/components/message-part.css | 76 +++++++++++++++++++++-- packages/ui/src/components/message-part.tsx | 96 ++++++++++++++++++++++++++--- packages/ui/src/components/session-turn.tsx | 10 ++- 3 files changed, 166 insertions(+), 16 deletions(-) (limited to 'packages/ui/src/components') diff --git a/packages/ui/src/components/message-part.css b/packages/ui/src/components/message-part.css index b66ef1d27..e2d70e342 100644 --- a/packages/ui/src/components/message-part.css +++ b/packages/ui/src/components/message-part.css @@ -14,11 +14,77 @@ line-height: var(--line-height-large); letter-spacing: var(--letter-spacing-normal); color: var(--text-base); - display: -webkit-box; - line-clamp: 3; - -webkit-line-clamp: 3; - -webkit-box-orient: vertical; - overflow: hidden; + display: flex; + flex-direction: column; + gap: 8px; + + [data-slot="user-message-attachments"] { + display: flex; + flex-wrap: wrap; + gap: 8px; + } + + [data-slot="user-message-attachment"] { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + border-radius: 6px; + overflow: hidden; + background: var(--surface-base); + border: 1px solid var(--border-base); + transition: border-color 0.15s ease; + + &:hover { + border-color: var(--border-strong-base); + } + + &[data-type="image"] { + width: 48px; + height: 48px; + } + + &[data-type="file"] { + width: 48px; + height: 48px; + } + } + + [data-slot="user-message-attachment-image"] { + width: 100%; + height: 100%; + object-fit: cover; + } + + [data-slot="user-message-attachment-icon"] { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + color: var(--icon-weak); + + [data-component="icon"] { + width: 20px; + height: 20px; + } + } + + [data-slot="user-message-text"] { + display: -webkit-box; + line-clamp: 3; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; + } + + .text-text-strong { + color: var(--text-strong); + } + + .font-medium { + font-weight: var(--font-weight-medium); + } } [data-component="text-part"] { diff --git a/packages/ui/src/components/message-part.tsx b/packages/ui/src/components/message-part.tsx index f00c43bd8..5ea3cd19c 100644 --- a/packages/ui/src/components/message-part.tsx +++ b/packages/ui/src/components/message-part.tsx @@ -2,6 +2,7 @@ import { Component, createMemo, For, Match, Show, Switch } from "solid-js" import { Dynamic } from "solid-js/web" import { AssistantMessage, + FilePart, Message as MessageType, Part as PartType, TextPart, @@ -74,13 +75,93 @@ export function AssistantMessageDisplay(props: { message: AssistantMessage; part } export function UserMessageDisplay(props: { message: UserMessage; parts: PartType[] }) { - const text = createMemo(() => - props.parts - ?.filter((p) => p.type === "text" && !(p as TextPart).synthetic) - ?.map((p) => (p as TextPart).text) - ?.join(""), + const textPart = createMemo( + () => props.parts?.find((p) => p.type === "text" && !(p as TextPart).synthetic) as TextPart | undefined, + ) + + const text = createMemo(() => textPart()?.text || "") + + const files = createMemo(() => (props.parts?.filter((p) => p.type === "file") as FilePart[]) ?? []) + + const attachments = createMemo(() => + files()?.filter((f) => { + const mime = f.mime + return mime.startsWith("image/") || mime === "application/pdf" + }), + ) + + const inlineFiles = createMemo(() => + files().filter((f) => { + const mime = f.mime + return !mime.startsWith("image/") && mime !== "application/pdf" && f.source?.text?.start !== undefined + }), + ) + + return ( +