Skip to content

feat(studio): align Settings sections and About with the prototype - #2252

Merged
kantord merged 10 commits into
mainfrom
feat/studio-settings-2206b
Oct 14, 2026
Merged

kantord merged 10 commits into
mainfrom
feat/studio-settings-2206b

Conversation

@peppescg

@peppescg peppescg commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Stack: part of gh stack #2227, on top of #2251 (chat approvals). It was rebased there after the screenshots were taken, with no conflicts. The gates were rerun on the rebased head: server 195, web 1,039, browser 66. The screenshots are labelled with the pre-rebase head ea96ca9de, which has identical settings code.

Summary

This is part (b) of the Settings, Shortcuts, and About alignment (#2206, part of #2210). It's stacked on part (a), the shortcuts page, so review that first. Settings now uses the prototype's section grouping, labels, icons, and navigation look, and the prototype's per-section UI for Personalise, Agent, Permissions, Providers, Models, Storage, Diagnostics, and Labs. About is split into a Studio card and an agent card. Personalise gains the prototype's Starter prompts preference, and the new-chat greeting honours it.

Studio keeps its route structure and slugs (/workspace/settings/$section with providers, models, mcp-tools, about, and the rest), its section order, and its legacy redirects. Settings stays read-only, and it only shows data the BFF already serves. The "No regression" section has the proof.

What changed

Navigation (settings-sections.ts, settings-workspace.tsx)

  • Groups: Preferences, Agent runtime, Experimental (new, holds Labs), and Support. Each section now carries the prototype's lucide icon (UserRound, Palette, Bot, ShieldCheck, Server, Network, Database, Brain, GraduationCap, Activity, FlaskConical, CircleHelp; Models, which the prototype doesn't have, uses Boxes).
  • Labels: Profile becomes You and Appearance becomes Personalise, as in the prototype. The slugs stay profile and appearance.
  • Desktop nav: the prototype's w-44 column, gap-5 groups, px-2 items with bg-muted for the current section, and a gap-10 gutter before the content. Like the prototype's desktop nav, it shows no icons.
  • Phone picker: the native section picker takes the prototype's inset-grouped row look (rounded-2xl bg-muted/50, 15px text) with the current section's icon on the left and a chevron on the right.
  • Breakpoints: the nav and picker pivot at 500px (min-[500px]:), and so does every grid in the files this PR touches. No sm: or md: classes are left in them.
  • Layout: the content column keeps the prototype's max-w-3xl reading width, with space-y-5 between cards.

Section pages

  • Shared grammar (settings-card.tsx): adds the prototype's SettingsRow (label and description on the left, control on the right, hairline dividers) and a FactList/FactRow pair for read-only facts, in the prototype's About-card look. SettingsCard and Note are unchanged.
  • You: the name and picture are SettingsRows ("Your display name", "Shown on your messages."), with a labelled input. The sign-in session facts become a fact list.
  • Personalise: three cards, as in the prototype:
    • Appearance: Theme, Palette, Interface scale (round 44px steppers), and Sidebar side, which is hidden below 500px because the chat list is full screen there.
    • Chat: Start on, Starter prompts (new), Messages while the agent works, and Tool activity.
    • Notifications: Browser notifications, when the browser supports them.
  • Agent: the name and picture rows match You. The Agent behavior card shows "Steering during a run" as an Available/Not enabled badge row, plus the managed note.
  • Permissions: a read-only Safety level row with the prototype's posture badge: Strict (outline), Trusted (info), Auto (warning), Yolo (destructive). An unknown tier shows as reported, and a missing one shows "Not reported".
  • Providers: the prototype's bordered list. Each row has a status dot, the provider name, its state and model count ("Ready · 1 model"), and the BFF's hint when the provider isn't ready. The whole row links to Studio's provider detail page.
  • Models: Default model and Routing become a fact list. The model cards and the personal Visible switch are unchanged.
  • MCP tools: MCP support and Connector status become a fact list.
  • Storage: as in the prototype, the status badge and a round Refresh button share the first row, and the facts follow. Studio's managed-by-deployment note moves below the facts. Loading, failure, and "cannot report" states now sit inside the Storage card instead of replacing it.
  • Diagnostics: the daemon facts are the same component About uses, followed by the storage-health line and the logs and usage note.

About (about-cards.tsx)

  • About Mecatl Studio: Studio build and SDK version, then Documentation, Report a problem, and Keyboard shortcuts.
  • About the agent: daemon build, daemon implementation, runtime source, connection, and deployment, then Copy support summary and "Include these details when you report a problem." The copied summary is byte-identical to before.
  • Sign-in: its own card, shown only when someone is signed in, with the existing sign-out control.

Runtime status line and live regions

Each runtime-backed section now shows its loading, offline, or failure note inside the section's own card, through one RuntimeStatusLine component. Loading notes carry a small spinner. Loading and offline notes are role="status". Failed reads, and an incompatible agent, are role="alert". The same applies to the storage states, the sign-in session check, and the "no providers" and "no models" notes. The wording is unchanged, and cached facts stay hidden until the runtime validates, as before.

Starter prompts

  • useShowStarterPrompts() in lib/profile-preferences.ts stores studio.profile.starter-prompts through Studio's account-scoped storage. The prompts are shown by default, and the key holds hidden only while they're off. A sign-out or account change clears it, like every other studio. preference.
  • DraftGreeting reads the preference and leaves out the chips when it's off. The heading stays. The chat change is limited to draft-greeting.tsx; chat-workspace.tsx is untouched.

Docs

user-docs/operating/studio.md names Personalise, the Starter prompts switch, the Safety level, and About's two cards.

Differences from the prototype

  • Phone navigation: Studio keeps its native section picker, restyled as one of the prototype's inset rows with the section icon, instead of the prototype's drill-down index and back bar. /workspace/settings must keep redirecting to /workspace/settings/profile, and settings-accessibility.test.tsx pins the native select#settings-section. For the same reason, the "Settings" title stays on phones. This is a native <select> where Studio: use shadcn/ui primitives like the prototype and SEP (no custom components) #2201 prefers a primitive; it stays only because of that pinned contract.
  • Section order: Studio keeps its order, which the route tests pin. So Diagnostics stays under Agent runtime (the prototype puts it under Support), and Providers, Models, MCP tools, and Storage come before Memory and Learning.
  • Models: Studio keeps its Models section. The prototype folds models into Providers.
  • Touch targets: nav items, steppers, the Starter prompts switch's hit area, and About's actions keep Studio's 44px minimum. The prototype uses about 32px.
  • Page title: keeps Studio's shared text-page-title (34px) instead of the prototype's text-3xl, matching the other Studio pages.
  • Personalise:
    • The scale row stays "Interface scale", because its buttons' pinned names are "Decrease/Increase interface scale". The prototype calls it "Text size".
    • Tool activity stays in the Chat card, because Studio has no chat-menu home for it and the accessibility test pins it. The prototype moved it to the chat menu.
    • Messages while the agent works keeps Studio's two choices (Queue message, Steer agent) and their wording. Studio's EnterSendBehavior has no "Always wait".
    • Notifications keeps Studio's copy and first-paint behaviour.
  • Agent behavior: keeps Studio's spelling and its steering fact. The prototype shows only "The agent is run somewhere else…".
  • Permissions, Providers, MCP tools, and Storage: keep Studio's managed-by-deployment notes instead of the prototype's generic external note. Providers keeps Studio's four states (Ready, Sign-in needed, Unavailable, Not ready), drawn with Studio's status tokens.
  • About: the agent card lists Studio's five safe daemon facts and copies Studio's support summary. The prototype shows "Version" and "Managed here" and copies two lines. Studio links its own documentation and issue tracker.
  • Runtime status line: Studio keeps masking a section until the runtime validates, so the line sits inside the section's card. The prototype shows a corner spinner above cards that keep rendering. The prototype's deployment label (behind its developer-tools switch) isn't ported, because About already shows the deployment.
  • Starter prompts storage: Studio's account-scoped key (studio.profile.starter-prompts), cleared on sign-out, instead of the prototype's device key (mecatl-studio.hide-starter-prompts).
  • Labs: Studio has no demo chat or developer tools, so Labs keeps its single note.

Out of scope

These need a product decision and are tracked separately:

  • the MCP gateway sign-in card,
  • the Diagnostics logs and usage cards (Diagnostics keeps its one-line note),
  • the learning mode and sensitivity display, and
  • any write path. Settings stays read-only.

Gaps

  • Sign-in session check in the offline harness, pre-existing: in the screenshot harness, You's Sign-in session card stays on "Checking sign-in details…" on both trees. It doesn't happen in the unit tests, and this PR doesn't change that query. It should be looked at separately.

No regression

Pinning tests

settings-alignment.pinning.test.tsx was committed first, alone (8e07554d0), and passed on the old code (6 tests). It passes unchanged on the new code. It pins:

  • the 13 slugs and their order, each loading /workspace/settings_/$section without a redirect
  • the redirects: /workspace/settings and unknown slugs (including the prototype's own help, provider, gateway, chat, and notifications) go to profile; /workspace/settings/memory?item= goes to the fact page; /workspace/memory and /workspace/provider without an item go back to their sections
  • both navigation modes: 13 nav buttons with one aria-current, a native picker with the 13 values and its label, and both calling onSectionChange
  • the exact runtime, offline, and inventory state wording in all 11 runtime-backed sections, with cached facts and raw errors hidden
  • the read-only contract: no inputs beyond the personal name fields and the model filter, no other select, and no save, apply, clean-up, posture, or gateway controls
  • today's deployment facts per section, the provider detail link, and About's three links
  • the greeting's four starter prompts with nothing stored

Existing tests

settings-accessibility.test.tsx, settings-navigation.test.tsx, and settings-route-interactions.test.tsx are unchanged and pass. So are settings-routes.test.tsx, about-page.test.tsx (including the exact copied summary and the five "Not reported" facts), settings-card.test.tsx, and storage-settings.test.ts.

Modified tests

  • settings-workspace.test.tsx, "titles every section with a plain card heading": the expected headings change for two sections, as Studio alignment: settings, shortcuts, and About #2206 asks. About goes from ["About"] to ["About Mecatl Studio", "About the agent"], and Personalise from ["Appearance"] to ["Appearance", "Chat"] (Notifications isn't rendered in the test DOM). The assertion is still an exact toEqual on every section's headings.

New tests

settings-alignment.test.tsx (9 tests) covers the groups, labels, and icons; the 500px pivots in every section this PR owns; the live-region roles for each state; the Safety level badge for every tier; the provider row; About's two cards and the conditional Sign-in card; the shared daemon facts; and the Starter prompts preference end to end (switch, account-scoped key, greeting, reset on sign-out).

Gate counts

Gate Base (b7ca46bbe) This branch
Biome 428 files 431 files
Server 24 files / 195 tests 24 files / 195 tests
Web 136 files / 980 tests 138 files / 995 tests
Browser 66 66

task studio:check and task studio:browser pass on both. The web delta is the two new files: 6 pinning tests and 9 alignment tests. matlatl check --strict passes for the docs change (0 broken links or anchors).

Screenshots

Before is b7ca46bbe, After is ea96ca9de, and Prototype is stack-08. Each tree was captured twice; the repeat runs differ by at most 194 pixels (the composer caret), so every red box is a real change. Desktop is 1280 wide and mobile is 390, both grown to the full height of the scrolling content. Where Before and After differ in height, the shorter shot is padded with a flat grey band, and the shell's top gradient, which scales with the viewport, gets a red box on phones. Both are capture artifacts, not changes.

You

Matches the prototype's rows (Your name, Picture). Deviations: Studio keeps its explanatory note and the Sign-in session card; the phone keeps the section picker and the "Settings" title instead of the back bar.

You, desktop light

Desktop dark, mobile light, mobile dark

You, desktop dark

You, mobile light

You, mobile dark

Personalise

Matches the prototype's Appearance, Chat (with the new Starter prompts switch), and Notifications cards. Deviations: "Interface scale" instead of "Text size", Studio's Tool activity row and busy-message wording, 44px steppers.

Personalise, desktop light

Desktop dark, mobile light, mobile dark

Personalise, desktop dark

Personalise, mobile light

Personalise, mobile dark

Agent

Matches the prototype's name and picture rows. Deviation: Agent behavior shows Studio's steering badge and managed note instead of the prototype's external-agent note.

Agent, desktop light

Desktop dark, mobile light, mobile dark

Agent, desktop dark

Agent, mobile light

Agent, mobile dark

Permissions

Matches the prototype's read-only Safety level row and posture badge (Auto shown in warning). Deviation: Studio's managed-by-deployment note.

Permissions, desktop light

Desktop dark, mobile light, mobile dark

Permissions, desktop dark

Permissions, mobile light

Permissions, mobile dark

Providers

Matches the prototype's bordered provider list with status dots, state, model count, and the hint for a provider that isn't ready. Deviations: Studio's management notes and its four state words; rows link to Studio's provider detail.

Providers, desktop light

Desktop dark, mobile light, mobile dark

Providers, desktop dark

Providers, mobile light

Providers, mobile dark

Models

Studio-only section (the prototype folds models into Providers, shown for reference). Default model and Routing move to the prototype's fact-list grammar; the model cards are unchanged.

Models, desktop light

Desktop dark, mobile light, mobile dark

Models, desktop dark

Models, mobile light

Models, mobile dark

MCP tools

Fact-list grammar. Deviation: the prototype's gateway sign-in card is out of scope.

MCP tools, desktop light

Desktop dark, mobile light, mobile dark

MCP tools, desktop dark

MCP tools, mobile light

MCP tools, mobile dark

Storage

Matches the prototype: status badge and Refresh on one row, then the facts. Deviation: Studio keeps its managed-by-deployment note, now below the facts.

Storage, desktop light

Desktop dark, mobile light, mobile dark

Storage, desktop dark

Storage, mobile light

Storage, mobile dark

Memory

Content unchanged (aligned in #2222 and #2229); only the navigation changes.

Memory, desktop light

Desktop dark, mobile light, mobile dark

Memory, desktop dark

Memory, mobile light

Memory, mobile dark

Learning

Content unchanged (aligned in #2232); only the navigation changes. The prototype column shows its fixture's learning data.

Learning, desktop light

Desktop dark, mobile light, mobile dark

Learning, desktop dark

Learning, mobile light

Learning, mobile dark

Diagnostics

Daemon facts in the prototype's About-card grammar, shared with About. Deviation: the Logs and Usage statistics cards are out of scope, so Diagnostics keeps one card with the storage-health line and the logs note.

Diagnostics, desktop light

Desktop dark, mobile light, mobile dark

Diagnostics, desktop dark

Diagnostics, mobile light

Diagnostics, mobile dark

Labs

Nav only; the content is unchanged. Studio has no demo chat or developer tools to switch.

Labs, desktop light

Desktop dark, mobile light, mobile dark

Labs, desktop dark

Labs, mobile light

Labs, mobile dark

About

Matches the prototype's split: About Mecatl Studio, About the agent, and Sign-in. Deviations: Studio's build, SDK, and five daemon facts, and Copy support summary.

About, desktop light

Desktop dark, mobile light, mobile dark

About, desktop dark

About, mobile light

About, mobile dark

New chat, Starter prompts on

Unchanged, as intended (the only differing pixels are the composer caret, equal to the capture noise). Matches the prototype's greeting with chips.

New chat, Starter prompts on, desktop light

Desktop dark, mobile light, mobile dark

New chat, Starter prompts on, desktop dark

New chat, Starter prompts on, mobile light

New chat, Starter prompts on, mobile dark

New chat, Starter prompts off

Matches the prototype: the chips are hidden and the heading stays.

New chat, Starter prompts off, desktop light

Desktop dark, mobile light, mobile dark

New chat, Starter prompts off, desktop dark

New chat, Starter prompts off, mobile light

New chat, Starter prompts off, mobile dark

Review fixes

Fixes from the final regression and security review of the stack (stack #2227). Each one comes with a test that fails without the fix.

Finding Result Commit Test
[minor] The Studio guide named the "Message during a run" preference Fixed: the guide now names Messages while the agent works in Settings > Personalise 92a26e62d Docs only; task docs passes. No prose test (AGENTS.md: don't pin documentation prose).
[minor] The visible label "Your name" didn't match the accessible name "Your display name" (WCAG 2.5.3) Fixed: the visible label is now "Your display name", and the accessible name the read-only pins check stays the same c313489db settings-accessibility.test.tsx: "keeps each identity field's visible label inside its accessible name" (fails before, passes after)
[minor] Overflow at 500–640px: fixed-width inputs and a two-column models grid Fixed e175641c7, f67b9340d e2e/settings-layout.spec.ts: "settings sections fit at 500/568/640px, between the 500px pivot and a tablet"
[audit] The Settings nav pushed the current item below the fold at 1280×800 (Labs, About) Fixed: the nav is sticky, scrolls on its own, and scrolls the current item into view. Targets stay 44px. cd1a4791f e2e/settings-layout.spec.ts: "the settings nav keeps the current section on screen at 1280x800"
[audit] The phone section picker had about 1.05:1 contrast against the page Fixed: added a muted-foreground border, about 4.9:1 in light and 6.8:1 in dark (WCAG 1.4.11) cd1a4791f e2e/settings-layout.spec.ts: "the phone section picker reads as a control in light/dark mode"
[found by the new check] About's Copy support summary and Sign out ran into the card padding at 500px Fixed: long action labels wrap, and Sign out drops under its text b082e8b84 Same 500–640px journey, which now measures against the card's content edge
[optional] Show "OpenAI" instead of humanize(id) Not done — The provider inventory contract has no display name, so the fix needs a contract and BFF change, not a one-line UI fix.

How the 500–640px layout works now. From 500px the section nav takes 176px, which leaves a section card about 190–330px wide.

  • A settings row's control never grows past the row, so the name inputs narrow. Phones still get 176px and desktops 240px.
  • The Models grid is a container query: two columns from 480px of card, three from 700px. On a 1280px desktop it still shows three columns.
  • A model card's Visible switch drops under a long name instead of squeezing it.
  • A fact value drops below its label only when its longest word would not fit beside it. Words no longer split ("Manag-ed by deploy-ment"), and phones look the same as before.
  • The memory facts table switches to its stacked cells by its own width (container query) instead of a 500px viewport, so it stops scrolling sideways beside the nav.

The browser journey checks every section at 500, 568, and 640px:

  • no sideways scroll;
  • nothing past a card's content edge;
  • fact prose breaks only between words;
  • model cards are at least 180px wide, with one-line names and labels.

Before the fix it failed on profile, agent, models, memory, MCP tools, diagnostics, and about.

Differences from the prototype.

  • The label reads "Your display name" (the prototype says "Your name"). This keeps the accessible name the read-only pins check.
  • The phone picker has a visible border, where the prototype's inset row has none, so the control meets 3:1.

Gates on e001f782b:

  • studio:check: server 195/195, web 1040/1040 (139 files; +1 vitest test).
  • studio:browser: 70 passed, 4 skipped. The new spec adds 4 tests per project, and each runs on only one project.

Screenshots

Before is 7f5301a89 and After is e001f782b. Red boxes mark pixel differences. These are responsive fixes for widths and states the prototype does not define, so there is no prototype column.

Models at 500px: one readable column instead of two 87px columns, and fact values keep their words whole.

Models at 500px, light

The current nav item at 1280×800 (the window as a user sees it, About): before, About sat below the fold; after, the nav scrolls it into view.

About at 1280x800, light

The phone section picker now has a visible border, and the label reads "Your display name":

You at 390px, light

More: 500/568/640px sections, desktop, dark

You at 500px: the input stays inside the card.

You at 500px

Agent at 500px:

Agent at 500px

Models at 568px and 640px:

Models at 568px

Models at 640px

Models at 568px, dark

Models at 1280px still shows three columns; a long name now puts Visible under it:

Models at 1280px

Memory at 500, 568, and 640px: stacked cells, no sideways scroll.

Memory at 500px

Memory at 568px

Memory at 640px

About at 500px and 568px: fact values keep their words whole, and the buttons stay inside the card.

About at 500px

About at 568px

MCP tools and Diagnostics at 500px:

MCP tools at 500px

Diagnostics at 500px

Labs at 1280×800, light and dark:

Labs at 1280x800

Labs at 1280x800, dark

Phone picker, dark:

About at 390px, dark

Re-verification (2026-10-11)

  • CI: the 500–640px journey outran its budgets. It reloaded the app 39 times in one test: 56s of its 60s timeout on this branch's CI run, a timeout on every branch above, and then Playwright's 300s global timeout cut the suite short. It is now one test per width with one page load each; sections open from the Settings nav, and each step also checks the URL and aria-current. The measurements and assertions are unchanged, each test takes about 2.5s, and with the layout fix reverted they still fail on every section that spilled. globalTimeout moves from 300s to 600s: it is a backstop for a hung run, each test keeps its 60s timeout, and the serial suite grew from 54 to over 100 journeys (5.3 minutes on CI at the stack top). (e6fd0022a)
  • Sign out was 36px tall (minor). About's other actions keep the 44px minimum; Sign out, now in its own Sign-in card, kept the button's default height. It now has min-h-11. (485f25242) Test: settings-accessibility.test.tsx "gives About's Sign out a 44px touch area" (fails without the fix).

Sign out, before and after the fix (36px → 44px on desktop; the images are labelled with the pre-restack hashes):

Sign out, desktop light

More: mobile, dark

Sign out, mobile light
Sign out, desktop dark
Sign out, mobile dark

Gates on the restacked head 485f25242: studio:check passes (web 1,152, server 210 tests). At the stack top (#2256): studio:browser 118 passed, 30 skipped; the mecated --mock integration suite 8 passed. The browser suite takes 5.3 minutes on a CI runner.

Commit hashes cited earlier in this body predate the restacks; the current commits keep the same subjects. Hashes in Review fixes are updated.

Closes #2206

🤖 Generated with Claude Code

peppescg and others added 7 commits October 14, 2026 12:48
…ter prompts

Pins the behaviour the Settings alignment must keep before any change:
Studio's thirteen slugs and their order, the legacy redirects, both
navigation modes, the runtime and inventory state wording that masks
cached facts, the read-only contract, today's deployment facts, and the
draft chat's starter prompts with nothing stored.

Refs #2206

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Settings takes the prototype's grouping, labels, icons, and navigation
visuals while keeping Studio's slugs, section order, and redirects:

- Navigation: Preferences, Agent runtime, Experimental, and Support
  groups; "You" and "Personalise" labels; a lucide icon per section; the
  prototype's w-44 nav, 500px pivots, and inset-row look on the phone
  picker, which carries the current section's icon.
- Sections: the prototype's row and fact-list grammar for You, Agent,
  Permissions (a read-only "Safety level" badge), Providers (status rows
  linked to the detail page), Models, MCP tools, Storage, Diagnostics,
  and Labs. Personalise splits into Appearance, Chat, and Notifications.
- About: an app card (Studio build, SDK version, help links) and an agent
  card (daemon facts, copy support summary), plus a Sign-in card when
  signed in. Diagnostics shares the daemon facts.
- Live regions: loading and offline notes are role="status"; failed
  reads are role="alert".
- Starter prompts: a new account-scoped Personalise preference, shown by
  default. The draft chat greeting reads it and hides the chips when off.

Settings stays read-only. The gateway sign-in card, the Diagnostics logs
and usage cards, and the learning mode display are out of scope.

Refs #2206

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The You section showed "Your name" above an input named "Your display
name", so a speech user saying the visible words would not reach it
(WCAG 2.5.3, Label in Name). Show "Your display name" as the label. The
accessible name, which the read-only pins check, stays the same.

Refs #2206

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The Studio guide said the shortcuts page follows the "Message during a
run" preference. This branch renamed that row to "Messages while the
agent works" in Settings > Personalise, so the guide named a setting
that no longer exists.

Refs #2206

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Settings > Memory switched the facts table between its stacked and
two-column layouts at a 500px viewport. Beside the Settings nav, a
500-640px window leaves the table about 190-330px, so the fixed 280px
Name column made the table scroll sideways. Switch on the table's own
width with a container query instead, so a phone and a narrow Settings
column both get the stacked cells.

Refs #2206

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
From 500px the section nav takes 176px beside the content, so at
500-640px a section card has about 190-330px. In that range:

- The display and agent name inputs kept a fixed 240px width and spilled
  out of the card. A settings row's control now never grows past the
  row, so the input narrows instead; phones and desktops keep 176px and
  240px.
- The Models grid went to two columns at 500px, which made 87-157px
  cards that split names and labels. Columns now follow the card's own
  width (two from 480px, three from 700px), and a card's Visible switch
  drops under a long name instead of squeezing it.
- Fact values split words ("Manag-ed by deploy-ment") beside their
  label. A value now drops below its label only when its longest word
  would not fit beside it.

A browser journey checks every section at 500, 568, and 640px: no
sideways scroll, nothing spilling out of a card, fact prose broken only
between words, and model cards at least 180px wide with one-line labels.

Refs #2206

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… visible

- At 1280x800 the section nav is about 900px tall and scrolled with the
  page, so on Labs and About the highlighted item sat below the fold.
  The nav is now sticky, scrolls on its own within the window, and
  scrolls the current section into view. Targets stay 44px, with room
  for focus outlines.
- The phone section picker's fill was about 1.05:1 against the page in
  both themes, so it did not read as a control. It now has a
  muted-foreground border, about 4.9:1 in light and 6.8:1 in dark
  (WCAG 1.4.11).

Browser checks cover the current nav item at 1280x800 for every section
and the picker boundary contrast in both themes.

Refs #2206

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
peppescg and others added 3 commits October 14, 2026 12:48
At 500px, Copy support summary ran 10px and Sign out 20px into the About
card's padding. Long action labels now wrap within the card, and the
sign-in row puts Sign out under its text when they do not fit side by
side. The 500-640px browser check now measures spill against the card's
content edge, not its border.

Refs #2206

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The 500-640px journey reloaded the app 39 times in one test. On a CI
runner it took 56s of its 60s timeout on this branch and timed out on
every branch above it, and the serial suite then ran into Playwright's
300s global timeout, so later journeys never ran.

- One test per width, one page load per test. Each section opens from
  the Settings nav, as a person opens it; the test now also checks the
  URL and aria-current for each section. The measurements and their
  assertions are unchanged. Locally the three tests take about 2.5s
  each, against 40s for the single test before. With the layout fix
  reverted they still fail on every section that spilled.
- globalTimeout is a backstop for a hung run, not a pace target: each
  test keeps its 60s timeout. The serial suite grew from 54 to over 100
  journeys and a CI runner takes about 1.5x a local run, so the backstop
  moves from 300s to 600s.

Refs #2206

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
About's other actions keep Studio's 44px minimum, but Sign out, now in
its own Sign-in card, kept the button's default 36px height.

Refs #2206

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@kantord
kantord force-pushed the feat/studio-settings-2206b branch from 41d97f9 to 1f7bd41 Compare October 14, 2026 09:48
@kantord
kantord merged commit fb50bb2 into main Oct 14, 2026
31 checks passed
@kantord
kantord deleted the feat/studio-settings-2206b branch October 14, 2026 10:02
@kantord kantord mentioned this pull request Oct 14, 2026
41 tasks done
@kantord

kantord commented Oct 14, 2026

Copy link
Copy Markdown
Member

Post-merge review follow-ups for this PR. No blockers or regressions found. Items worth tracking were filed here:

Other candidate findings were checked and dropped as not worth tracking.

Fully or partially written by an AI agent.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Studio alignment: settings, shortcuts, and About

2 participants