thomwolf HF Staff Claude Opus 5 (1M context) commited on
Commit
082a73e
·
1 Parent(s): c3f933d

Review fixes: stop the title growing over the header's own furniture

Browse files

Two real defects the reviewer found, both reproduced in a browser before
believing them and after fixing them.

The header is a three-column grid whose centre track is `auto`, and an `auto`
track is sized to its max-content BEFORE the two `1fr` side tracks get
anything. So a wide title does not shrink — it takes its width out of its
neighbours, and the title's box grows over the logo on one side and the close
button on the other. Measured at a 900px window in a 2x2: `[Agent-manager]
claude-code-8` overlapped `.ph-left` by 4px, and a 31-character name overlapped
both sides by 28px and 16px. The long-name half of that is on main already; the
prefix made it reachable at ordinary names. A `min-content` floor on the two
side tracks fixes both: the title is capped at what is actually free and
ellipsises inside its own box.

Second, `flex-shrink` distributes a deficit proportionally, so weighting the
group heavier still took a sliver off the name — and a name that misses its
natural width by 0.03px renders an ellipsis anyway. `claude-code-8` read
`claude-code…` in every tile of a 2x2 at 900px. The name now has shrink 0 and
is bounded by `max-width` instead, which also puts the ellipsis on the name
itself when the name alone is too long for the header.

Also from the review: `align-items: center` rather than a synthesised baseline
on two overflow-clipped boxes, drop the `text-align` that a blockified flex
item ignores, and cite the endpoint the app actually reads (`/api/tree`) rather
than the agent roster.

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

Files changed (2) hide show
  1. web/src/lib/sessionTitle.ts +5 -3
  2. web/src/styles.css +23 -11
web/src/lib/sessionTitle.ts CHANGED
@@ -14,9 +14,11 @@
14
  /**
15
  * The group's display name, or null when the session sits loose in the tree.
16
  *
17
- * Ungrouped is an absence here, not a word: the tree simply has no group that
18
- * lists the session, and `/api/agents` serialises that as `group: null`. So the
19
- * empty cases all collapse to the same bare name there is no `[None] foo`.
 
 
20
  */
21
  export function groupLabel(name?: string | null): string | null {
22
  const trimmed = (name ?? '').trim();
 
14
  /**
15
  * The group's display name, or null when the session sits loose in the tree.
16
  *
17
+ * Ungrouped is an absence here, not a word: `/api/tree` gives the app groups
18
+ * with their `sessionIds`, so a loose session is simply one no group lists and
19
+ * the caller has nothing to pass. Every empty shape collapses to the same bare
20
+ * name — there is no `[None] foo`. (The roster that agents read, `/api/agents`,
21
+ * spells the same absence as `group: null`.)
22
  */
23
  export function groupLabel(name?: string | null): string | null {
24
  const trimmed = (name ?? '').trim();
web/src/styles.css CHANGED
@@ -560,16 +560,28 @@ body {
560
  .welcome-reopen { font-size: 11px; color: var(--muted); }
561
  .welcome-foot .btn-primary { flex: none; padding: 8px 18px; }
562
 
563
- .pane-head { container-type: inline-size; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, auto) minmax(0, 1fr); align-items: center; gap: 9px; padding: 7px 11px; background: var(--panel); border-bottom: 1px solid var(--border); font-size: 12px; flex: none; }
 
 
 
 
 
 
 
564
  .pane-head .ph-left { grid-column: 1; justify-self: start; display: inline-flex; align-items: center; gap: 7px; }
565
- .pane-head .ph-title { grid-column: 2; min-width: 0; max-width: 100%; display: inline-flex; align-items: baseline; justify-content: center; gap: 5px; text-align: center; font-family: var(--font-mono); font-weight: 600; white-space: nowrap; overflow: hidden; cursor: text; }
566
- /* `[Group] name` is one title in two parts, and the group is the part that
567
- gives way: it is weighted to shrink hundreds of times faster than the name,
568
- so a tile too narrow for both truncates the context rather than the thing you
569
- are looking for. Below a tile width where a clipped prefix would say nothing
570
- anyway, it drops out entirely and the name gets the whole header. */
571
- .pane-head .ph-group { flex: 0 500 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted); font-weight: 500; }
572
- .pane-head .ph-name { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
 
 
 
 
 
573
  .pane-head .ph-right { grid-column: 3; min-width: 0; display: inline-flex; align-items: center; justify-self: end; gap: 6px; }
574
  .pane-head .ph-path { min-width: 0; max-width: min(24vw, 220px); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted); font-family: var(--font-mono); font-size: 10.5px; font-weight: 500; }
575
  .pane-head .ph-title-input { width: 100%; text-align: center; font: inherit; font-family: var(--font-mono); font-weight: 600; padding: 1px 6px; border: 1px solid var(--accent); border-radius: var(--r-sm); background: var(--panel-2); color: var(--text); min-width: 0; }
@@ -577,8 +589,8 @@ body {
577
  @container (max-width: 520px) {
578
  .pane-head .ph-path { display: none; }
579
  }
580
- /* Narrower than this a prefix could only ever be a sliver of itself, and a
581
- header that reads "[A… name" is worse than one that just reads "name". */
582
  @container (max-width: 260px) {
583
  .pane-head .ph-group { display: none; }
584
  }
 
560
  .welcome-reopen { font-size: 11px; color: var(--muted); }
561
  .welcome-foot .btn-primary { flex: none; padding: 8px 18px; }
562
 
563
+ /* The side columns keep a min-content floor. Without one the centre track is
564
+ sized to its max-content BEFORE the two `1fr` tracks get anything, so a wide
565
+ title takes its width out of its neighbours: the logo and the close button
566
+ keep their place in the flow but the title's box grows over them. That was
567
+ already reachable with a long enough agent name; putting the group in front
568
+ of the name made it reachable at ordinary ones. With the floor the title is
569
+ capped at what is actually free and ellipsises instead. */
570
+ .pane-head { container-type: inline-size; display: grid; grid-template-columns: minmax(min-content, 1fr) minmax(0, auto) minmax(min-content, 1fr); align-items: center; gap: 9px; padding: 7px 11px; background: var(--panel); border-bottom: 1px solid var(--border); font-size: 12px; flex: none; }
571
  .pane-head .ph-left { grid-column: 1; justify-self: start; display: inline-flex; align-items: center; gap: 7px; }
572
+ .pane-head .ph-title { grid-column: 2; min-width: 0; max-width: 100%; display: inline-flex; align-items: center; justify-content: center; gap: 5px; font-family: var(--font-mono); font-weight: 600; white-space: nowrap; overflow: hidden; cursor: text; }
573
+ /* `[Group] name` is one title in two parts, and the group is the only part that
574
+ gives way: a tile too narrow for both truncates the context, never the thing
575
+ you are looking for. The squeeze passes through a band where the prefix reads
576
+ as a stub (`[Agent-man…`); below a tile width where that is all it could ever
577
+ be, it drops out entirely and the name has the header to itself. */
578
+ .pane-head .ph-group { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted); font-weight: 500; }
579
+ /* flex-shrink 0, not a small weight: shrinking is proportional, so ANY shared
580
+ deficit takes a sliver off the name too — and a name that misses by 0.03px
581
+ still renders an ellipsis. So the name never shrinks, and `max-width` is what
582
+ bounds it: it can fill the whole title but no more, which is what puts the
583
+ ellipsis on the name itself when the name alone is too long for the header. */
584
+ .pane-head .ph-name { flex: 0 0 auto; min-width: 0; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
585
  .pane-head .ph-right { grid-column: 3; min-width: 0; display: inline-flex; align-items: center; justify-self: end; gap: 6px; }
586
  .pane-head .ph-path { min-width: 0; max-width: min(24vw, 220px); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted); font-family: var(--font-mono); font-size: 10.5px; font-weight: 500; }
587
  .pane-head .ph-title-input { width: 100%; text-align: center; font: inherit; font-family: var(--font-mono); font-weight: 600; padding: 1px 6px; border: 1px solid var(--accent); border-radius: var(--r-sm); background: var(--panel-2); color: var(--text); min-width: 0; }
 
589
  @container (max-width: 520px) {
590
  .pane-head .ph-path { display: none; }
591
  }
592
+ /* Narrower than this the prefix could only ever be a stub, and a header that
593
+ reads "[A… name" is worse than one that just reads "name". */
594
  @container (max-width: 260px) {
595
  .pane-head .ph-group { display: none; }
596
  }