fix(ui): titlebar tooltips reveal, not repeat, the session name - #5639
Conversation
Hovering the title chip or the "..." button re-announced the whole session name plus an action tail — no new information, longer wrap. The name tooltip now appears only when the visible name is ellipsized and shows exactly the hidden text; the "..." tooltip is the action alone. Accessible names keep the name plus action suffix, so screen-reader users lose nothing. The truncation could not be measured before: the segment span was display:inline, whose scrollWidth/clientWidth are always 0. Make it a constrained block (same recipe as quote-ref-chip) so the ellipsis is real layout the hook can observe via ResizeObserver across resizes. New unit test pins the untruncated case (no tooltip) and the menu tooltip; the titlebar-identity-truncated story gains a play that hovers both triggers on real layout and asserts the tooltip accessible names. Generated-by: Maka
Review: a fully visible chip's missing information is the click affordance, not nothing — show 重命名任务 on hover while the name is intact, and keep the full-name reveal for the truncated state. Read-only chips stay truncation- gated: they are not clickable, so the rename hint would lie there. The titlebar-project-feedback-narrow play pins the visible-state tooltip. Generated-by: Maka
…ity node Adversarial review (Codex, PR apache#5639): two lifecycle holes let the clipped flag describe a node that no longer exists. The read-only span never carried the measure ref, so shared-session titles could never regain their full-name title after the gating replaced the always-on one; and entering/leaving the rename input swapped the span without any sessionName change, leaving the observer on the unmounted node — the next resize could desync tooltip and layout. Rebind in the render-phase effect (inactive = renaming) and attach the ref in the read-only branch. The unit test now records which nodes the ResizeObserver sees, so a missing binding fails immediately, and the narrow titlebar play walks a rename round-trip before its hover assertion. Generated-by: Maka
Drop the unit tests whose content the story plays already assert on real layout; keep only the measurement-binding test, which is the one claim the famous-Node harness is decisive for (both branches must hand their rendered span to the observer). Shorten the prose comments to the two things a maintainer could otherwise get wrong: the span-swap rebinding and the two-state tooltip rule. Generated-by: Maka
jackwener
left a comment
There was a problem hiding this comment.
I reviewed 2cb8eda2a820c8db41d0fbd8d138b4fd762610a3.
No P0–P2.
A tooltip should show what the surface cannot. The name chip now measures real overflow (display: block + ResizeObserver on the rendered span, including after a rename swap). Truncated: tooltip is the hidden full name. Fully visible: tooltip is the rename action. The "…" menu tooltip is 任务操作 only; the session name stays in its accessible name. Read-only titles keep a native title only when clipped.
Hosted test was not waited on.
简体中文
我审查了 2cb8eda2a820c8db41d0fbd8d138b4fd762610a3。没有 P0–P2。
标题栏 tooltip 只揭示表面上看不到的东西:截断给全名,未截断给「重命名任务」;「…」只提示「任务操作」。本审查没有等 hosted test。
Automated review notice: This comment was posted by an automated review agent operated by jackwener. It is not an independent human review and does not replace one.
Summary
The titlebar identity's two hover tooltips repeated what was already on screen: the name chip re-announced the full session name plus a " — 重命名任务" tail, and the "…" button re-announced the whole session name before its own action. Neither added information, and the tail forced the tooltip into multi-line wraps.
A tooltip only earns its hover when it reveals what the surface cannot show. The name chip hides two different things depending on its state, so its tooltip is two-state:
重命名任务, the click affordance the surface otherwise never advertises; truncated: the tooltip shows exactly the hidden full text (reading the tail of your own title is the missing information then, and…→重命名keeps the action reachable). The " — 重命名任务" tail is gone in both states.任务操作alone; the session name sits right next to it and stays in its accessible name (label), so screen-reader context is unchanged.titlestays truncation-gated only (full name when ellipsized, none otherwise).Truncation could not be measured before:
.maka-titlebar-identity__segment--sessionwasdisplay: inline, and inline elements always reportscrollWidth/clientWidthof 0 — which is also why the old code could not tell whether truncation ever happened. The span now follows thequote-ref-chiprecipe (display: block; min-width: 0; max-width: 100%), making the ellipsis real measurable layout; aResizeObserverkeeps the clipped state current across resizes.No behavior changes beyond the two tooltips: clicking the title still renames, the "…" menu still lists 重命名, accessible names are byte-identical to before.
Name chip, truncated state — light / dark


Name chip, fully visible state — light / dark


(Each row is the same story at the same 1280px viewport, left BEFORE
main/ right AFTER this branch. The truncated pair's BEFORE fixture name happens to fit, which makes the defect plain: a fully visible title still gets a tooltip that repeats it, twice as long as needed.)Verification
packages/ui/src/__tests__/titlebar-session-identity.test.tsxpins the fake-DOM wiring: accessible names keep thename — actionform, the chip always has a tooltip configured, and the read-only branch's nativetitleis truncation-gated; tooltip contents are asserted in the browser tier.packages/ui:npm run build+node --test --test-concurrency=4 "dist/**/*.test.js"→ 642/643 pass; the 1 failure (prompt-rail-reading-positionhover-card assertion) fails identically on a cleanmaincheckout.npm --workspace @maka/desktop run typecheck:storiespasses.apps/desktop: fullbuild-storybook+smoke:storybook—titlebar-identity-truncated(truncated → full-name tooltip,…→ 任务操作) andtitlebar-project-feedback-narrow(visible → 重命名任务 hint) both pass with theirplayfunctions. The one smoke failure,design-system-functional-motion, is a pre-existing animation-timing flake: it fails identically when running the smoke againstmain's existing storybook-static.npm run format/npm run lintclean.AI use
Select exactly one:
Tool(s) and scope: Maka (GLM) — diagnosis, implementation, tests, story plays, and screenshot automation; reviewed locally before commits. Commits carry
Generated-by.Checklist
Does this PR entail a change in behavior?