Skip to content

fix(desktop): settings chat-defaults column alignment + assistant-tone textarea resize [AI cross reviewed] - #2256

Merged
Astro-Han merged 2 commits into
apache:mainfrom
GabrielDrapor:fix/settings-control-alignment
Aug 5, 2026
Merged

fix(desktop): settings chat-defaults column alignment + assistant-tone textarea resize [AI cross reviewed]#2256
Astro-Han merged 2 commits into
apache:mainfrom
GabrielDrapor:fix/settings-control-alignment

Conversation

@GabrielDrapor

@GabrielDrapor GabrielDrapor commented Aug 5, 2026

Copy link
Copy Markdown
Contributor
image

Two Settings → 通用 paper cuts, one commit each.

1. The chat-defaults selects staggered by 60px

The 默认模型 and 默认权限模式 rows are meant to form one trailing-control column — select.css sizes both triggers to 260px and its comment prescribes exactly that. But the 默认权限模式 selector passed width={320} to Astryx Selector, which sizes the outer field, while the CSS sizes the inner trigger: the 260px trigger left-aligned inside the 320px field and the two adjacent rows staggered by the 60px difference.

The Selector branch of PermissionModeSelect has no other consumer (the composer uses the icon appearance), so the prop served nobody. Dropping it lets the field wrap the trigger and the CSS own the column. The select.css comment now states the contract explicitly: the rule works only while neither component passes Selector's width prop.

The two triggers also rendered at different sizes (sm vs md). ModelPicker's sm dated from the composer footer, which has since moved to ghost DropdownMenus — General Settings is its only production host, and settings rows are md. The size is hardcoded md now, and the EmptyCatalog story renders the production size inside a 260px frame matching the column the desktop's select.css imposes (the one part a packages/ui story cannot import; the annotation says so per FIDELITY.md).

Measured after the fix: both controls at left 916 / right 1176 / height 32, aligned at 1280/900/620/480 viewport widths with no horizontal overflow.

2. Dragging the assistant-tone textarea's resize grip moved only the grip

The field passed style={{ height: calc(…) }} to TextArea, which lands as an inline height on the visible wrapper and pins it at 84px. The inner native textarea keeps the design system's resize: vertical, so dragging resized an element with a transparent background overflowing an unmoving box — only the grip appeared to travel.

Dropped the fixed height (and the boxSizing that existed for it): rows={4} already owns the default height (90px vs the pinned 84), and the wrapper follows the textarea, so the grip now resizes the visible control. Verified live: textarea 80→220px moves the wrapper 90→230px.

Validation

  • @maka/ui suite 382/382; typecheck (ui + desktop), biome lint, full monorepo build clean
  • Both fixes verified in the running app via DOM measurement (numbers above)

Co-Authored-By: Claude noreply@anthropic.com

https://claude.ai/code/session_01Ac5rv6WUKWtMZgQb5QPN16

GabrielDrapor and others added 2 commits August 5, 2026 23:38
The 默认权限模式 selector passed width={320} to Astryx Selector, which
sizes the OUTER field, while the settings CSS sizes the inner trigger to
260px — the trigger left-aligned inside the wider field and the two
adjacent rows staggered by 60px. The Selector branch of
PermissionModeSelect has no other consumer (the composer uses the icon
appearance), so the prop served nobody; dropping it lets the field wrap
the trigger and the CSS own the column, as the select.css comment
already prescribed. That comment now also states the contract: the rule
works only while neither component passes Selector's width prop.

The two triggers also rendered at different sizes (sm vs md). ModelPicker's
sm dated from the composer footer, which has since moved to ghost
DropdownMenus — General Settings is its only production host, and settings
rows are md. The size is a fact of the component now, hardcoded md, and
its EmptyCatalog story renders the production size inside a 260px frame
matching the column the desktop's select.css imposes (the one part a
packages/ui story cannot import; the annotation says so per FIDELITY.md).

Measured after the fix: both controls at left 916 / right 1176 / height 32.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ac5rv6WUKWtMZgQb5QPN16
The field passed style={{ height: calc(…) }} to TextArea, which lands as
an inline height on the visible wrapper and pins it at 84px. The inner
native textarea keeps the design system's resize: vertical, so dragging
the grip resized an element with a transparent background overflowing an
unmoving box — only the grip appeared to travel.

Drop the fixed height (and the boxSizing that existed for it): rows={4}
already owns the default height (90px vs the pinned 84), and the wrapper
follows the textarea, so the grip now resizes the visible control.
Verified live: textarea 80→220px moves the wrapper 90→230px.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ac5rv6WUKWtMZgQb5QPN16
@GabrielDrapor GabrielDrapor changed the title fix(desktop): settings chat-defaults column alignment + assistant-tone textarea resize fix(desktop): settings chat-defaults column alignment + assistant-tone textarea resize [AI cross reviewed] Aug 5, 2026
@GabrielDrapor

Copy link
Copy Markdown
Contributor Author

CI note: the failing e2e_shard (2/2) is the prompt-rail spec ('the active tick stays visible once the rail overflows'), which is pre-existing on main — main's own CI runs for a3e6620 (#2198) and 07c1e68 fail on the exact same test (last green: 317d2d5). This branch's diff touches only the settings selects, ModelPicker and the tone textarea; the spec also fails locally on a checkout of bare main. Bisect points at #2198, whose settings/side-rail alignment changes moved geometry the rail assertion measures.

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice catch on both — I verified the mechanics in the source and they hold up:

  • width={320} on the permission-mode Selector indeed lands on the outer Field (Astryx's width sizes the whole field, while className lands on the trigger container), so the 60px stagger is exactly as described. Dropping it restores the 260px trigger column, and select.css's contract is structurally safe: neither product component exposes Selector's width prop.
  • The textarea style lands on the visible wrapper while rows and the native resize: vertical live on the inner textarea — the pinned-wrapper explanation checks out.
  • No side effects: ModelPicker's only production consumer is Settings (composer uses NewChatModelPicker), and the Selector branch of PermissionModeSelect is Settings-only (composer goes through appearance="icon").
  • Re-ran locally on this branch: @maka/ui 382/382, ui + desktop typecheck, biome lint & format clean.
  • The failing e2e_shard (2/2) (prompt-rail) doesn't touch this diff — consistent with your pre-existing-on-main note.

Non-blocking P3 nits for later:

  1. The alignment fix has no regression test. A cheap computed-style contract (both triggers at 260px) would lock it in if the renderer test infra can run DOM.
  2. No live-app screenshot or settings-pages.stories.tsx update per the repo's visual-change convention (the DOM measurements are solid evidence regardless).
  3. The tone textarea default grows 84→90px (rows={4} owning the height) — a small visible change, already called out in the PR.
  4. Pre-existing: align="end" passed by Settings isn't consumed by either branch of PermissionModeSelect — a dead prop that could be dropped while touching this area.

Thanks for the clean two-commit split and the measurements!

@Astro-Han
Astro-Han merged commit fcbff01 into apache:main Aug 5, 2026
10 of 12 checks passed
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