Skip to content

refactor(studio): use Label for the settings switch labels (#2201 group B) - #2359

Merged
peppescg merged 2 commits into
mainfrom
refactor/studio-settings-toollist-primitives
Oct 15, 2026
Merged

peppescg merged 2 commits into
mainfrom
refactor/studio-settings-toollist-primitives

Conversation

@peppescg

Copy link
Copy Markdown
Contributor

Summary

Handles the #2340 and #2337 call sites in chat/tool-call-list.tsx, settings/interface-settings.tsx and settings/settings-workspace.tsx, which #2352 skipped because other open PRs were changing those files at the time. Three native <label> elements move to the Label primitive. The tool-activity disclosure and the running-status pulse stay as they are; the decision table below gives the reasons. Names, roles, keyboard and pointer behaviour are unchanged, and every captured state is pixel-identical.

Part of #2340
Part of #2337
Part of #2201
Part of #2210

What changed

  • settings/interface-settings.tsx: the Starter prompts and Show tools labels in Appearance → Chat are now Label.
  • settings/settings-workspace.tsx: each model card's Visible label is now Label.
  • The two labels with text add font-normal, which keeps the text at its old weight against Label's font-medium. Their existing text-sm and text-xs classes already replace Label's leading-none through cn, so line heights stay. The Starter prompts label has no text, so Label's type classes have nothing to style.
  • chat/tool-call-list.tsx is unchanged.

Every call site

<label>, aria-expanded=, role="alert" and animate-pulse in the three files. Lines are on main (550c67fee); the #2352 base lines are in brackets.

Call site (apps/web/src/features/) Pattern Decision
settings/interface-settings.tsx:183 [181] <label> Changed → Label. Starter prompts, wrapping its switch.
settings/interface-settings.tsx:219 [208] <label> Changed → Label. Show tools with its eye icon, wrapping its switch.
settings/settings-workspace.tsx:530 [569] <label> Changed → Label. A model card's Visible, wrapping its switch.
settings/settings-workspace.tsx [150] <label> Gone: #2330 removed the phone section picker, and its label with it.
chat/tool-call-list.tsx:187 [209] aria-expanded Kept for now. This is a disclosure, so its primitive is Collapsible, which is added in #2352 and isn't on main yet. Accordion doesn't fit: its trigger is wrapped in an h3, which would add a heading for every tool group in the transcript. It also brings its own chevron, padding and underline. Its content unmounts when closed unless forced, but the closed list keeps its rows in the document, hidden, so tool names stay findable. This site moves to Collapsible after #2352 merges.
chat/tool-call-list.tsx:28 animate-pulse Kept: it pulses the status dot of a running call. That is a status indicator, not a loading placeholder, so Skeleton doesn't apply.

None of the three files has a role="alert". No title= attribute was touched.

Behaviour differences

None visible, and none to assistive technology. The label is still a <label for> the switch. Label adds data-slot="label". Radix Label also prevents text selection when the label text is double-clicked; a double-click on the switch itself is unaffected.

No regression

  • Pins first (bb17023de): settings/settings-switch-labels.pinning.test.tsx (3 tests), passing on main's code and on the head. For each of the three labels, the tests check that:

    • the label targets the switch and contains it;
    • the switch keeps its accessible name;
    • a click on the label toggles the switch once (for Visible, it also stores the preference);
    • the label keeps its layout and size classes;
    • the text labels carry neither font-medium nor leading-none.

    Existing tests also cover these controls: settings-accessibility.test.tsx (44px label targets), settings-alignment.test.tsx (Starter prompts) and settings-workspace.test.tsx (Visible). No existing test was modified.

  • Mutation proof. Each mutation was applied alone, and the pin file was rerun:

    Mutation Failing tests
    Show tools label without font-normal 1
    Visible label without font-normal 1
    Starter prompts label without htmlFor 1
    Show tools label without text-sm 1
    Visible label without text-xs 1
  • Pixels. 16 captures: 2 surfaces × 2 states × desktop and 390px × light and dark. Each Before is main's two files in the same tree, captured twice. After vs Before differs by 0 pixels in all 16, except 7 pixels in two mobile dark model captures, and those 7 pixels also differ between the two Before runs. pixel-report.txt

Screenshots

Before (main, 550c67fee) | After (9f4d63c81) | Prototype (stack-08). Red boxes mark the labels this PR touches. They aren't diff boxes, because every pair is pixel-identical. The prototype columns show the closest prototype pages: Personalise for Appearance, and the provider's model table for Models. Studio keeps its own layout for both pages; this PR doesn't change it.

Appearance → Chat, switches on. Pixel-identical. The Starter prompts switch matches the prototype's; the prototype has no Show tools row.

Appearance, desktop light

Models, Visible on. Pixel-identical. The prototype lists models in a table with an Enabled switch rather than in cards; Studio's cards are unchanged.

Models, desktop light

All 16 composites (open states: switches turned off by clicking their labels)

Appearance, switches on:



Appearance, both switches turned off by clicking their labels:




Models, Visible on:



Models, the first card's Visible turned off by clicking its label:




Gates

On the head (9f4d63c81), run through the shared gate lock:

  • task studio:check: passes. Server 252/252 tests (27 files); web 1589/1589 tests (182 files), 3 of them new.
  • task studio:browser: 136 passed, 38 skipped, 0 failed.

🤖 Generated with Claude Code

peppescg and others added 2 commits October 15, 2026 16:22
Pins the Starter prompts, Show tools and model Visible labels: the label
targets the switch, the switch keeps its accessible name, a click on the
label toggles the switch once, and the text keeps its weight and line
height.

Refs #2340

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The Starter prompts and Show tools labels in Appearance and each model
card's Visible label now use the Label primitive. font-normal keeps the
text at its old weight against Label's font-medium; the text-sm and
text-xs sizes already replace Label's leading-none, so line heights stay.

Refs #2340

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

@kantord kantord left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this, the decision table covers every call site and the Label swaps are correct. Approving, with a few non-blocking nits:

  • The tests assert that font-medium and leading-none are absent. That ties them to class names rather than behaviour. The first two pins (the label wraps and targets the switch, one toggle per click) are the useful ones.
  • Where leading-none is dropped without an explicit override (Tool activity, model card), it relies on tailwind-merge treating text-sm/text-xs as conflicting with leading-*. That works and the test pins it, but it is implicit.
  • The Starter prompts Label has no text, so the swap has no visible effect there.

Fully or partially written by an AI agent.

@peppescg
peppescg merged commit 43c1a02 into main Oct 15, 2026
31 checks passed
@peppescg
peppescg deleted the refactor/studio-settings-toollist-primitives branch October 15, 2026 17:02
@toolhive-release-app toolhive-release-app Bot mentioned this pull request Oct 20, 2026
2 tasks
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.

2 participants