From e03979491219001b864eeefb7b61e9be7d7d5024 Mon Sep 17 00:00:00 2001 From: Matthew Wesney Date: Wed, 29 Jul 2026 15:25:07 -0400 Subject: [PATCH] tighten composer layout and visual hierarchy --- docs/UI_MODERNIZATION_AUDIT.md | 9 +++-- .../src/components/MessageComposer.test.tsx | 7 ++++ frontend/src/components/MessageComposer.tsx | 11 +++--- frontend/src/styles/tokens.css | 37 ++++++++++--------- 4 files changed, 37 insertions(+), 27 deletions(-) diff --git a/docs/UI_MODERNIZATION_AUDIT.md b/docs/UI_MODERNIZATION_AUDIT.md index dca6b8d..c62a3c9 100644 --- a/docs/UI_MODERNIZATION_AUDIT.md +++ b/docs/UI_MODERNIZATION_AUDIT.md @@ -1,6 +1,6 @@ # Cortex UI modernization audit -**Status:** UI modernization follow-up complete; dedicated image-editor affordances and preset prompt cards removed; native package rebuilt and startup-verified +**Status:** UI modernization follow-up complete; dedicated image-editor affordances, preset prompt cards, and composer clutter removed; native package rebuilt and startup-verified **Scope:** Every user-facing frontend surface, not a cosmetic theme pass ## What was audited @@ -19,7 +19,7 @@ primary problems were structural: | --- | --- | --- | | Workspace shell | The top bar conveyed almost no context and the sidebar was a loose list of text. | A clear workspace header, local-runtime status, product identity, conversation count, and a deliberate sidebar footer establish hierarchy. | | Conversation canvas | A new chat opened into a large, empty dark region, then introduced generic preset prompts. | A quiet new-thread orientation gives the canvas context while leaving the user in control of the first message. | -| Composer | The input was visually stranded in a full-width bottom strip. | The composer is now a centered, elevated input island with integrated local-model context, state feedback, and responsive sizing. | +| Composer | The input was visually stranded in a full-width bottom strip, with redundant badges and competing colored controls. | The composer is a compact centered island with one model control, grouped metadata, neutral idle chrome, and an accent send action only when actionable. | | Conversation controls | Saved chats, rename, and delete controls had weak grouping and feedback. | The list uses active/hover/focus states, reveal-on-focus actions, and purposeful confirmation dialogs. | | Settings and submenus | Settings read as a large collection of unrelated boxes. | Text-led categories, descriptive labels, and a unified detail pane make settings read like a native control surface. | | Supporting flows | Setup, model pulls, memory, jobs, errors, and notifications used unrelated visual patterns; the chat also advertised an image editor that is not Cortex's product surface. | Shared surfaces, status colors, progress treatment, form controls, and meaningful feedback now connect those flows. Code-driven image work stays behind the execution layer instead of appearing as a first-class editor. | @@ -56,7 +56,8 @@ opaque background service. not advertise image transformation, image generation, or preset prompt suggestions. - `frontend/src/components/MessageComposer.tsx` integrates local-model context - into the composer island. + into the composer island with a compact, quiet utility row and state-based + send control. - `frontend/src/components/SettingsPanel.tsx` turns settings into a structured text-led category navigation with descriptions while retaining existing keyboard and screen-reader names. @@ -74,7 +75,7 @@ build, and browser-level flows for new chat, streaming, retry/regenerate/fork, settings, memory, model progress, and compact-window composer behavior. The native Windows package must also launch from a fresh build before release. -This slice passed the release checks: 44 component tests in a single worker, +This slice passed the release checks: 45 component tests in a single worker, 6 browser-level flows, typecheck, lint, production build, a fresh Windows package build, and a packaged launch with `GET /api/v1/health/ready` returning HTTP 200. The production bundle contains no dedicated image-transform UI diff --git a/frontend/src/components/MessageComposer.test.tsx b/frontend/src/components/MessageComposer.test.tsx index 35237be..47ef652 100644 --- a/frontend/src/components/MessageComposer.test.tsx +++ b/frontend/src/components/MessageComposer.test.tsx @@ -48,6 +48,13 @@ function ComposerHarness({ } describe("MessageComposer", () => { + it("keeps the utility row quiet and model-focused", () => { + render(); + + expect(screen.queryByText("LOCAL ENGINE")).not.toBeInTheDocument(); + expect(screen.getByRole("button", { name: "Selected local model: local-chat:7b" })).toBeVisible(); + }); + it("submits once with Enter and clears only after acceptance", async () => { const user = userEvent.setup(); const request = deferred(); diff --git a/frontend/src/components/MessageComposer.tsx b/frontend/src/components/MessageComposer.tsx index 1a0a26d..e4f06ae 100644 --- a/frontend/src/components/MessageComposer.tsx +++ b/frontend/src/components/MessageComposer.tsx @@ -195,7 +195,6 @@ export function MessageComposer({ />
- LOCAL ENGINE
- - {status} + + + {status} + + {showCounter && {remaining.toLocaleString()} characters left} - {showCounter && {remaining.toLocaleString()} characters left}
{isGenerating ? ( @@ -224,7 +225,7 @@ export function MessageComposer({ ) : (