From ea6a1d0f81fa155b70babd85055e85514c3347d7 Mon Sep 17 00:00:00 2001 From: Patrick Erichsen Date: Thu, 27 Aug 2026 13:18:48 -0700 Subject: [PATCH] fix(ui): make composer text sizing consistent (#131154) * fix(ui): align composer typography to semantic small size * fix(ui): use medium composer text sizing --- .../chat/chat-responsive.browser.test.ts | 38 +++++++++++++++---- ui/src/styles/chat/layout.css | 12 ++---- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/ui/src/pages/chat/chat-responsive.browser.test.ts b/ui/src/pages/chat/chat-responsive.browser.test.ts index 9c44cbd562bb..b45a5d685c90 100644 --- a/ui/src/pages/chat/chat-responsive.browser.test.ts +++ b/ui/src/pages/chat/chat-responsive.browser.test.ts @@ -3372,10 +3372,37 @@ describeBrowserLayout.concurrent("chat responsive browser layout", () => { expect(rectsOverlap(model, send)).toBe(false); const contextModelGap = model.x - (context.x + context.width); expect(contextModelGap).toBeGreaterThanOrEqual(-1); - const composerFontSize = await page - .locator(".agent-chat__composer-combobox > textarea") - .evaluate((textareaNode) => Number.parseFloat(getComputedStyle(textareaNode).fontSize)); - expect(composerFontSize).toBe(16); + const composerFontSizes = await page.evaluate(() => { + const textareaNode = document.querySelector( + ".agent-chat__composer-combobox > textarea", + ); + const selectors = [ + ".chat-controls__permission-trigger .chat-controls__inline-select-label", + ".chat-controls__model-trigger .chat-controls__inline-select-label", + ".chat-controls__effort-trigger .chat-controls__inline-select-label", + ]; + if (!textareaNode) { + throw new Error("Missing composer textarea"); + } + const fontSize = (node: Element, pseudo?: string) => + Number.parseFloat(getComputedStyle(node, pseudo).fontSize); + return { + labels: selectors.map((selector) => { + const label = document.querySelector(selector); + if (!label) { + throw new Error(`Missing composer label: ${selector}`); + } + return fontSize(label); + }), + placeholder: fontSize(textareaNode, "::placeholder"), + textarea: fontSize(textareaNode), + }; + }); + expect(composerFontSizes).toEqual({ + labels: [14, 14, 14], + placeholder: 14, + textarea: 14, + }); if (width <= 480) { const modelSettings = expectControlRect( controls.modelSettings, @@ -3412,9 +3439,6 @@ describeBrowserLayout.concurrent("chat responsive browser layout", () => { } expect(footer.height).toBeLessThanOrEqual(53); } else { - // The editor reads at input size, while the controls around it stay - // chrome-sized — that difference is what marks the text as the - // subject of the surface. expect(send.width).toBeCloseTo(32, 2); expect(send.height).toBeCloseTo(32, 2); } diff --git a/ui/src/styles/chat/layout.css b/ui/src/styles/chat/layout.css index 3f9adccc8e19..0c21d878b5f3 100644 --- a/ui/src/styles/chat/layout.css +++ b/ui/src/styles/chat/layout.css @@ -3123,7 +3123,7 @@ button.chat-pr__diff { --chat-composer-chip-height: 30px; --chat-composer-chip-gap: 6px; --chat-composer-chip-padding-inline: 8px; - --chat-composer-chip-text: 13px; + --chat-composer-chip-text: var(--control-ui-text-md); --chat-composer-chip-icon: 16px; /* Menu-row family: every option row inside a composer popover (model, effort, permission, plus menu, attach, microphone) shares one box, icon size, and @@ -3143,12 +3143,9 @@ button.chat-pr__diff { the surface's own floor is taller than the editor plus these insets. */ --chat-composer-editor-inset-inline: 14px; --chat-composer-editor-inset-block: 6px; - /* The editor is a reading and writing surface, not a compact form field, so it - owns a 16px base instead of the shared control token, whose 14px base only - reaches 16px through an iOS zoom floor — text that size by accident does not - follow the operator's text scale until the scale passes 1.15, and it drops - the moment that floor moves. The max() keeps 16px as a hard floor. */ - --chat-composer-editor-size: max(16px, calc(16px * var(--control-ui-text-scale))); + /* Draft text and its surrounding labels share one semantic UI size. The + coarse-pointer floor in base.css still prevents iOS focus zoom. */ + --chat-composer-editor-size: var(--control-ui-text-md); /* One editor line. The single-line box centres a line of exactly this height, and the multiline editor never gets shorter than one of them. Derived, so a scaled-up editor keeps its leading instead of crowding its own descenders. */ @@ -7267,7 +7264,6 @@ button.chat-pr__diff { --chat-composer-chip-height: var(--chat-mobile-row-target-size); --chat-composer-chip-gap: var(--chat-mobile-row-chip-gap); --chat-composer-chip-padding-inline: var(--chat-mobile-row-chip-padding-inline); - --chat-composer-chip-text: 12px; --chat-composer-footer-icon-size: var(--chat-mobile-row-icon-size); --chat-composer-menu-icon: var(--chat-mobile-row-icon-size); --chat-composer-send-size: var(--chat-mobile-row-plus-target-size);