From f66377b0d4281797357efc432b8e06fc0c578740 Mon Sep 17 00:00:00 2001
From: Col0ring <1561999073@qq.com>
Date: Thu, 17 Sep 2026 16:47:19 +0800
Subject: [PATCH 1/2] feat(webui): drop the pill width cap and keep the row on
one line
- let a pill grow to its label with `min-w-24` as the only width constraint,
replacing `fitContent`
- keep the pills row nowrap so a tight row shrinks and truncates instead of
wrapping
- lower the inline threshold to 550px
---
.../app/components/common/Composer.tsx | 35 +++++++++----------
.../app/components/common/PillButton.tsx | 18 ++++------
2 files changed, 24 insertions(+), 29 deletions(-)
diff --git a/webui/frontend/app/components/common/Composer.tsx b/webui/frontend/app/components/common/Composer.tsx
index 156fe534a..154c8eeb4 100644
--- a/webui/frontend/app/components/common/Composer.tsx
+++ b/webui/frontend/app/components/common/Composer.tsx
@@ -1289,11 +1289,13 @@ export function Composer({
viewport, so keep the pills inline" and let them wrap into
three rows there.
- 600px is what one row costs: the four standing pills come
- to ~510px with a long model name (PillButton caps each at
- 240px) plus ~90px for the attach/send cluster. A session
- can carry two more pills, so this is the common case, not a
- guarantee.
+ 550px is the threshold: the four standing pills plus the
+ ~90px attach/send cluster fit inline in a fairly narrow
+ column, so opening the workspace panel (which splits the
+ chat column) no longer collapses them into the toggle right
+ away. Above it the pills shrink to one line; below it
+ collapses to the scroll row. A session can carry two more
+ pills, so this is the common case, not a guarantee.
Visibility is CSS-driven so the first paint is correct with
no SSR/hydration flash. When expanded on a narrow footer
@@ -1309,22 +1311,22 @@ export function Composer({
transcript. One line can never do that, whatever the pill
count or label length.
- `flex-wrap` is declared per branch instead of on the base:
- it and `flex-nowrap` are the same utility group, so keeping
- both here would let stylesheet order — not this class
- list — decide the winner. */}
+ Pills never wrap: `flex-nowrap` plus `min-w-0` on every
+ wrapper let an over-long row shrink each pill to its
+ `min-w-24` floor and truncate the label instead of spilling
+ onto a second line. */}
{/* Toggle button: shown only while collapsed */}
{!pillsExpanded && (
}
onClick={() => setPillsExpanded(true)}
/>
@@ -1333,8 +1335,8 @@ export function Composer({
{/* Model pill */}
@@ -1399,14 +1401,11 @@ export function Composer({
hand-rolled button) so the background, padding and
height match the selector pills exactly — copying its
classes by hand drifted on all of them. `caret={false}`:
- it navigates rather than opening a panel. `fitContent`
- drops the shared width cap so the whole "search not set
- up" message reads instead of collapsing to "Searc…". */}
+ it navigates rather than opening a panel. */}
{searchNeedsKey && (
navigate('/settings/search')}
icon={}
className="!text-msa-text-3"
diff --git a/webui/frontend/app/components/common/PillButton.tsx b/webui/frontend/app/components/common/PillButton.tsx
index 2ade4471c..b77c6f64c 100644
--- a/webui/frontend/app/components/common/PillButton.tsx
+++ b/webui/frontend/app/components/common/PillButton.tsx
@@ -30,10 +30,6 @@ interface PillButtonProps extends Omit {
/** Panel open state — flips the caret (same 180° + transition as the
* accordion headers) so the pill reads as expanded. */
open?: boolean
- /** Drop the shared max-width cap so the pill grows to its full label instead
- * of truncating. Used by the search-not-configured hint, whose message has to
- * read in full rather than collapse to "Searc…". */
- fitContent?: boolean
}
export const PillButton = forwardRef(
@@ -41,7 +37,6 @@ export const PillButton = forwardRef(
{
caret = true,
open = false,
- fitContent = false,
children,
className = '',
classNames,
@@ -69,12 +64,13 @@ export const PillButton = forwardRef(
classNames && typeof classNames === 'object'
? (classNames as Record)
: {}
- // The width cap is `!important`, so a caller can't undo it with its own
- // `max-w-*`; `fitContent` omits it here instead. `min-w-24` stays either way
- // so a short label keeps the shared minimum pill size.
- const width = fitContent
- ? 'min-w-24'
- : '!max-w-[min(96px,55cqw)] min-w-24'
+ // No max cap: a pill grows to its full label whenever the row has room.
+ // `min-w-24` (96px) is the floor. Overflow is the pills row's job, not the
+ // pill's — it wraps (`flex-wrap`) or scrolls sideways (collapsed footer), so
+ // a tight row wraps/scrolls instead of pinning every pill to a fixed width.
+ // If flex still forces a pill narrower than its label, the inner span
+ // truncates and the label tooltip engages.
+ const width = 'min-w-24'
return (
Date: Thu, 17 Sep 2026 16:56:23 +0800
Subject: [PATCH 2/2] feat(webui): cap the pill at 250px and widen the composer
actions gap
- give the pill a `max-w-[250px]` cap so a long label truncates instead of
growing without bound, keeping `min-w-24` as the floor
- widen the composer actions gap to 32px
---
webui/frontend/app/components/common/Composer.tsx | 2 +-
webui/frontend/app/components/common/PillButton.tsx | 13 ++++++-------
2 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/webui/frontend/app/components/common/Composer.tsx b/webui/frontend/app/components/common/Composer.tsx
index 154c8eeb4..72ce629a4 100644
--- a/webui/frontend/app/components/common/Composer.tsx
+++ b/webui/frontend/app/components/common/Composer.tsx
@@ -1278,7 +1278,7 @@ export function Composer({
// rather than the viewport — the composer can be narrow while
// the viewport stays wide (e.g. a detail rail is open), where a
// viewport-relative rule overflows or wraps.
-
+
{/* Left: pills. Collapsed behind a toggle while the footer
is narrower than the row needs, inline above that.
diff --git a/webui/frontend/app/components/common/PillButton.tsx b/webui/frontend/app/components/common/PillButton.tsx
index b77c6f64c..827d73a81 100644
--- a/webui/frontend/app/components/common/PillButton.tsx
+++ b/webui/frontend/app/components/common/PillButton.tsx
@@ -64,13 +64,12 @@ export const PillButton = forwardRef(
classNames && typeof classNames === 'object'
? (classNames as Record)
: {}
- // No max cap: a pill grows to its full label whenever the row has room.
- // `min-w-24` (96px) is the floor. Overflow is the pills row's job, not the
- // pill's — it wraps (`flex-wrap`) or scrolls sideways (collapsed footer), so
- // a tight row wraps/scrolls instead of pinning every pill to a fixed width.
- // If flex still forces a pill narrower than its label, the inner span
- // truncates and the label tooltip engages.
- const width = 'min-w-24'
+ // `min-w-24` (96px) is the floor, `max-w-[250px]` the cap: a pill grows with
+ // its label up to 250px, then truncates. The pills row still owns the rest of
+ // overflow — a tight row shrinks each pill (flex) toward the floor and scrolls
+ // once collapsed. When flex forces a pill narrower than its label the inner
+ // span truncates and the label tooltip engages.
+ const width = 'min-w-24 max-w-[250px]'
return (