diff --git a/.gitignore b/.gitignore index 8c99934..7bfbb63 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ # testing /coverage +/.tmp-vitest/ # next.js /.next/ @@ -23,6 +24,7 @@ # misc .DS_Store *.pem +/.worktrees/ # debug npm-debug.log* diff --git a/src/app/globals.css b/src/app/globals.css index 13b0c6e..03d4fb2 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -312,6 +312,7 @@ body { @apply bg-background text-foreground; min-height: 100vh; + min-height: 100dvh; margin: 0; letter-spacing: var(--tracking-normal); font-family: var(--font-sans), sans-serif; @@ -982,6 +983,8 @@ textarea:focus::-webkit-scrollbar { border: 1px solid color-mix(in oklch, var(--border) 72%, transparent); border-radius: var(--radius-card); background: var(--chat-surface-bg); + -webkit-overflow-scrolling: touch; + touch-action: pan-y; } .dark .ui-chat-scroll { @@ -1001,12 +1004,14 @@ textarea:focus::-webkit-scrollbar { } .ui-chat-user-card { + max-width: 100%; border: 1px solid var(--chat-user-border); background: var(--chat-user-bg); box-shadow: 0 1px 3px color-mix(in oklch, var(--foreground) 8%, transparent); } .ui-chat-assistant-card { + max-width: 100%; border: 1px solid var(--chat-assistant-border); border-radius: var(--radius-small); background: var(--chat-assistant-bg); @@ -1313,6 +1318,13 @@ textarea:focus::-webkit-scrollbar { box-shadow: none !important; } +@media (max-width: 768px) { + .chat-composer-input, + [data-agent-panel] .ui-input.ui-control-important { + font-size: 16px !important; + } +} + @keyframes fadeUp { from { opacity: 0; diff --git a/src/app/page.tsx b/src/app/page.tsx index 3e7a5e9..81bd082 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1372,8 +1372,8 @@ const AgentStudioPage = () => { if (!agentsLoadedOnce && !coreConnected && (!didAttemptGatewayConnect || gatewayConnecting)) { return ( -
-
+
+
OpenClaw Studio @@ -1389,8 +1389,8 @@ const AgentStudioPage = () => { if (!coreConnected && !agentsLoadedOnce && didAttemptGatewayConnect) { return ( -
-
+
+
setShowConnectionPanel(true)} @@ -1438,8 +1438,8 @@ const AgentStudioPage = () => { if (coreConnected && !agentsLoadedOnce) { return ( -
-
+
+
OpenClaw Studio @@ -1452,7 +1452,7 @@ const AgentStudioPage = () => { } return ( -
+
{state.loading ? (
@@ -1460,7 +1460,7 @@ const AgentStudioPage = () => {
) : null} -
+
setShowConnectionPanel(true)} diff --git a/src/app/styles/markdown.css b/src/app/styles/markdown.css index 6281e9a..d3ad38a 100644 --- a/src/app/styles/markdown.css +++ b/src/app/styles/markdown.css @@ -107,6 +107,7 @@ font-family: var(--font-mono), ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; font-size: 0.82em; + white-space: break-spaces; overflow-wrap: anywhere; word-break: break-word; background: color-mix(in oklch, var(--surface-3) 92%, transparent); @@ -116,6 +117,8 @@ } .agent-markdown pre { + max-width: 100%; + min-width: 0; background: color-mix(in oklch, var(--surface-2) 94%, transparent); border-radius: 0.4rem; padding: 0.75rem 0.85rem; @@ -124,6 +127,13 @@ line-height: 1.64; } +.agent-markdown pre, +.agent-markdown pre code { + white-space: pre-wrap; + overflow-wrap: anywhere; + word-break: break-word; +} + .agent-markdown pre code { background: transparent; padding: 0; @@ -145,7 +155,12 @@ } .agent-markdown table { - width: 100%; + display: block; + width: max-content; + min-width: 100%; + max-width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; border-collapse: collapse; font-size: 0.85em; } diff --git a/src/features/agents/components/AgentChatPanel.tsx b/src/features/agents/components/AgentChatPanel.tsx index d281590..a95978a 100644 --- a/src/features/agents/components/AgentChatPanel.tsx +++ b/src/features/agents/components/AgentChatPanel.tsx @@ -14,7 +14,7 @@ import { import type { AgentState as AgentRecord } from "@/features/agents/state/store"; import ReactMarkdown from "react-markdown"; import remarkGfm from "remark-gfm"; -import { Check, ChevronRight, Clock, Cog, Pencil, Shuffle, Trash2, X } from "lucide-react"; +import { Check, ChevronRight, Clock, Cog, Maximize2, Pencil, Shuffle, Trash2, X } from "lucide-react"; import type { GatewayModelChoice } from "@/lib/gateway/models"; import { rewriteMediaLinesToMarkdown } from "@/lib/text/media-markdown"; import { normalizeAssistantDisplayText } from "@/lib/text/assistantText"; @@ -665,7 +665,6 @@ const AgentChatTranscript = memo(function AgentChatTranscript({ }>; }) { const chatRef = useRef(null); - const chatBottomRef = useRef(null); const scrollFrameRef = useRef(null); const pinnedRef = useRef(true); const [isPinned, setIsPinned] = useState(true); @@ -673,12 +672,9 @@ const AgentChatTranscript = memo(function AgentChatTranscript({ const [nowMs, setNowMs] = useState(null); const scrollChatToBottom = useCallback(() => { - if (!chatRef.current) return; - if (chatBottomRef.current) { - chatBottomRef.current.scrollIntoView({ block: "end" }); - return; - } - chatRef.current.scrollTop = chatRef.current.scrollHeight; + const el = chatRef.current; + if (!el) return; + el.scrollTop = el.scrollHeight; }, []); const setPinned = useCallback((nextPinned: boolean) => { @@ -827,11 +823,11 @@ const AgentChatTranscript = memo(function AgentChatTranscript({ }, [runStartedAt, showLiveAssistantCard, status]); return ( -
+
updatePinnedFromScroll()} onWheel={(event) => { event.stopPropagation(); @@ -840,23 +836,23 @@ const AgentChatTranscript = memo(function AgentChatTranscript({ event.stopPropagation(); }} > -
+
{showLoadMoreBanner ? ( -
-
+
+
{hasHiddenFetchedHistory && typeof historyFetchedCount === "number" && typeof visibleTurnCount === "number" ? `Showing latest ${visibleTurnCount} of ${historyFetchedCount} loaded turns` : `Showing latest ${typeof visibleTurnCount === "number" ? visibleTurnCount : "?"} turns`}
{historyGatewayCapReached && !hasHiddenFetchedHistory ? ( -
+
Showing latest retrievable history
) : (