From ca4ea8b9fbe64554fc707b020e866c721b70d35d Mon Sep 17 00:00:00 2001 From: Lee Jackson <130007945+Imagineer99@users.noreply.github.com> Date: Thu, 2 Apr 2026 03:57:10 +0100 Subject: [PATCH] studio: align composer/code, unify fonts, and remove tool collapse jitter (#4763) - Add min-w-0 guards to thread/message/markdown containers to prevent content overflow past the composer width - Unify chat typography from Hellix/Space Grotesk to the sans stack, keeping monospace for code blocks and inline code - Restructure desktop navbar right-side controls with shrink-0 wrappers for consistent spacing across HoverCard roots - Soften tool-call label styling (font-medium + text-foreground/85 instead of bold) - Add responsive code block sizing via @container queries - Add horizontal scrolling for wide code blocks within the thread column - Scope list-item code block alignment CSS to .aui-thread-root - Preserve useScrollLock in tool-fallback and tool-group collapsibles - Fall back to bg-background on ViewportFooter when hideComposer is true - Widen inline code monospace selector to cover th, blockquote, and heading elements - Remove unused @fontsource-variable/space-grotesk import --- .../components/assistant-ui/markdown-text.tsx | 2 +- .../src/components/assistant-ui/thread.tsx | 40 +++-- .../components/assistant-ui/tool-fallback.tsx | 6 +- studio/frontend/src/components/navbar.tsx | 164 +++++++++--------- .../src/features/chat/shared-composer.tsx | 2 +- studio/frontend/src/index.css | 72 ++++++-- 6 files changed, 175 insertions(+), 111 deletions(-) diff --git a/studio/frontend/src/components/assistant-ui/markdown-text.tsx b/studio/frontend/src/components/assistant-ui/markdown-text.tsx index 5e84b9175e..17a6f8f054 100644 --- a/studio/frontend/src/components/assistant-ui/markdown-text.tsx +++ b/studio/frontend/src/components/assistant-ui/markdown-text.tsx @@ -403,7 +403,7 @@ const MarkdownTextImpl = () => { } return ( -
+
= ({ }} > {!hideWelcome && ( thread.isEmpty}> @@ -89,7 +89,13 @@ export const Thread: FC<{ hideComposer?: boolean; hideWelcome?: boolean }> = ({ }} /> - + + {!hideComposer && ( +
+ )} !thread.isEmpty}> {!hideComposer && } @@ -220,14 +226,20 @@ const GeneratingSpinner: FC = () => { const ComposerAnimated: FC = () => { return ( - - - +
+
+ + + +
); }; @@ -262,7 +274,7 @@ const Composer: FC = () => { { const AssistantMessage: FC = () => { return ( -
+
{
-
+
diff --git a/studio/frontend/src/components/assistant-ui/tool-fallback.tsx b/studio/frontend/src/components/assistant-ui/tool-fallback.tsx index c965749f74..82a5b17e04 100644 --- a/studio/frontend/src/components/assistant-ui/tool-fallback.tsx +++ b/studio/frontend/src/components/assistant-ui/tool-fallback.tsx @@ -156,12 +156,12 @@ function ToolFallbackTrigger({ - {label}: {toolName} + {label}: {toolName} {isRunning && ( - {label}: {toolName} + {label}: {toolName} )} diff --git a/studio/frontend/src/components/navbar.tsx b/studio/frontend/src/components/navbar.tsx index 63189a0d5d..121c559db8 100644 --- a/studio/frontend/src/components/navbar.tsx +++ b/studio/frontend/src/components/navbar.tsx @@ -372,90 +372,94 @@ export function Navbar() { })} - {/* Right: docs/tour desktop */} -
- - - - - - Learn more - - - - -

- Unsloth Documentation -

-

- Guides on fine-tuning LLMs 2x faster with 70% less memory. - Covers LoRA, QLoRA, data formatting, and deployment. -

- - Visit docs - - -
-
-
- - - - - + {/* Right: docs/tour desktop — one wrapper per control so flex gap is even (HoverCard roots can confuse flex spacing). */} +
+
+ +
+ + {tourId ? ( +
- - - - - - - +
+ ) : null} +
+ + + + + + + + +
+
+ +
{/* Right: mobile */} diff --git a/studio/frontend/src/features/chat/shared-composer.tsx b/studio/frontend/src/features/chat/shared-composer.tsx index 59b0880add..ac01f77381 100644 --- a/studio/frontend/src/features/chat/shared-composer.tsx +++ b/studio/frontend/src/features/chat/shared-composer.tsx @@ -473,7 +473,7 @@ export function SharedComposer({ onChange={(e) => setText(e.target.value)} onKeyDown={onKeyDown} placeholder="Send to both models..." - className="mb-1 max-h-32 min-h-14 w-full resize-none bg-transparent px-4 pt-2 pb-3 text-sm outline-none placeholder:text-muted-foreground" + className="mb-1 max-h-32 min-h-14 w-full resize-none bg-transparent pl-5 pr-4 pt-2 pb-3 text-sm outline-none placeholder:text-muted-foreground" rows={1} />
diff --git a/studio/frontend/src/index.css b/studio/frontend/src/index.css index 8dc159a002..45696b2274 100644 --- a/studio/frontend/src/index.css +++ b/studio/frontend/src/index.css @@ -6,21 +6,11 @@ @import "shadcn/tailwind.css"; @import "streamdown/styles.css"; @import "@fontsource-variable/figtree"; -@import "@fontsource-variable/space-grotesk"; @import "@fontsource-variable/inter"; @import "tw-shimmer"; @plugin "@toolwind/corner-shape"; @source "../node_modules/streamdown/dist/*.js"; -@font-face { - font-family: "Hellix"; - src: url("/fonts/Hellix-SemiBold.woff2") format("woff2"), - url("/fonts/Hellix-SemiBold.woff") format("woff"); - font-weight: 600; - font-style: normal; - font-display: swap; -} - @custom-variant dark (&:is(.dark *)); :root { @@ -67,7 +57,7 @@ --sidebar-ring: oklch(0.6929 0.1396 166.5513); --destructive-foreground: oklch(1 0 0); --font-sans: "Inter Variable", ui-sans-serif, sans-serif, system-ui; - --font-heading: "Hellix", "Space Grotesk Variable", ui-sans-serif, sans-serif; + --font-heading: var(--font-sans); --font-serif: Source Serif 4, serif; --font-mono: JetBrains Mono, monospace; --shadow-color: hsl(0 0% 0%); @@ -159,7 +149,7 @@ @theme inline { --font-sans: "Inter Variable", ui-sans-serif, sans-serif, system-ui; - --font-heading: "Hellix", "Space Grotesk Variable", ui-sans-serif, sans-serif; + --font-heading: var(--font-sans); --color-sidebar-ring: var(--sidebar-ring); --color-sidebar-border: var(--sidebar-border); --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); @@ -343,10 +333,68 @@ [data-streamdown="code-block"] { gap: 0; padding: 0.5rem; + /* Wide lines must scroll inside the thread column, not widen past the composer (flex min-width:auto). */ + max-width: 100%; + min-width: 0; + overflow-x: auto; } [data-streamdown="code-block-header"] { padding-left: 0.75rem; } + + /* Chat thread: code slightly smaller by default; step up when the thread column is wide. */ + .aui-thread-root [data-streamdown="code-block"] { + font-size: 0.8125rem; + line-height: 1.55; + } + + .aui-thread-root [data-streamdown="code-block-header"] { + font-size: 0.6875rem; + } + + @container (min-width: 36rem) { + .aui-thread-root [data-streamdown="code-block"] { + font-size: 0.875rem; + } + + .aui-thread-root [data-streamdown="code-block-header"] { + font-size: 0.75rem; + } + } + + /* Chat: use the app sans stack for UI + prose. */ + .aui-thread-root { + font-family: var(--font-sans); + } + + .aui-thread-root .font-medium, + .aui-thread-root .font-semibold, + .aui-thread-root .font-bold, + .aui-thread-root .font-heading { + font-family: var(--font-sans); + } + + .aui-thread-root :where(h1, h2, h3, h4, h5, h6) { + font-family: var(--font-sans); + } + + /* Keep monospace for code fences and inline code (not KaTeX). */ + .aui-thread-root [data-streamdown="code-block"] pre, + .aui-thread-root [data-streamdown="code-block"] code { + font-family: var(--font-mono), ui-monospace, monospace; + } + + .aui-thread-root :where(p, li, td, th, blockquote, h1, h2, h3, h4, h5, h6) code { + font-family: var(--font-mono), ui-monospace, monospace; + } + + /* Align fenced code blocks with the main chat column even when nested in lists. */ + .aui-thread-root [data-streamdown="list-item"] > [data-streamdown="code-block"], + .aui-thread-root [data-streamdown="list-item"] [data-streamdown="code-block"] { + margin-left: -1.25rem; + width: calc(100% + 1.25rem); + max-width: calc(100% + 1.25rem); + } } /* Minimal scrollbar — thumb only, no track */