Skip to content

fix(assistant-panel): replace collapsed knob with a persistent icon rail#1762

Merged
kgabryje merged 4 commits into
mainfrom
fix-123-agent-tab-collapse-rail
Jul 7, 2026
Merged

fix(assistant-panel): replace collapsed knob with a persistent icon rail#1762
kgabryje merged 4 commits into
mainfrom
fix-123-agent-tab-collapse-rail

Conversation

@kasiazjc

@kasiazjc kasiazjc commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes https://github.com/preset-io/agor-cloud/issues/123 ("Agent tab: the expand affordance is hard to see"). Note: that issue was filed against agor-cloud, but the panel it describes lives in this repo (agor/apps/agor-ui) — the fix is here.

  • The left assistant/comments panel used to collapse to 0px width with a small floating circular knob as the only way to reopen it. That knob was clipped almost in half by the viewport edge (left: 0 + translateX(-50%)) and used low-contrast neutral tokens that blended into the canvas background.
  • Replaced it with AssistantPanelRail: a persistent, always-fully-visible 56px icon rail shown while the panel is collapsed, with one stacked icon+label button per tab (Assistant, Sessions, Comments — Slack-nav style). Clicking a button expands the panel directly onto that tab.
  • The Comments rail item carries the same unread-count badge (and mention-highlight color) that AppHeader's "Show comments tab" button already has.
  • Deleted the old floating knob entirely; the panel's own in-tab-bar "Collapse panel" button is unchanged.
  • AppHeader's "Show comments tab" button is left as-is — it's still a useful global comments shortcut regardless of panel state.

Before:
image

After:

image

Test plan

  • pnpm lint (apps/agor-ui) — clean
  • pnpm typecheck (apps/agor-ui) — clean
  • pnpm test (apps/agor-ui) — 665 tests passing, including new coverage: rail renders all 3 buttons, each button opens the correct tab, unread badge shows/hides correctly
  • Manual browser verification — not completed in this session (no browser automation tooling available in the sandbox); recommend a quick manual pass on the deployed preview before merging: collapse the panel, confirm the rail is fully visible with no clipping, click each icon to confirm it opens the right tab.

Follow-up: session panel width jump

Manual testing of this PR found that collapsing/expanding the left rail also resized the right session panel (its stored size was a percentage of the content panel, which grows/shrinks with the left panel, rather than of the full viewport). Fixed in a follow-up commit: the session panel's persisted size is now viewport-relative and converted to/from the content-panel-relative percentage react-resizable-panels needs. Verified with Playwright against the live dev environment: session panel width stayed within ~1px (Playwright layout rounding) across collapse, expand, and dragging the left panel's own resize handle — all previously produced a large, evident jump.

  • Manual browser verification — completed against the branch's dev environment: rail is fully visible (not clipped) on collapse, each of the 3 rail buttons opens the correct tab, unread badge shows on Comments, and the session panel width fix above was confirmed with pixel measurements before/after each interaction.

@kasiazjc kasiazjc requested a review from kgabryje July 2, 2026 13:29
@kgabryje

kgabryje commented Jul 2, 2026

Copy link
Copy Markdown
Member

Reviewed the diff plus the surrounding App.tsx, and reasoned through the react-resizable-panels dynamics. Nice fix for the clipped affordance — one real gap in the bundled sizing change.

The rail (issue #123) — 👍 solid

  • The persistent, fully-visible 56px rail is a clear win over the half-clipped knob. Collapse affordance is preserved (the in-panel Collapse button still sets commentsPanelCollapsed) and the rail reopens onto the clicked tab.
  • Focused, meaningful tests (rail renders all three buttons, each opens the correct tab, unread badge show/hide). Extracting the width math into a pure, unit-tested panelSizing.ts is the right call.

This part looks ready.

Session-panel width follow-up — one real correctness gap ⚠️

The viewport↔content conversion is symmetric (persisted viewport-relative on the way in, converted back out) and fixes the common case. But it isn't bounded by the canvas panel's minSize={20} (App.tsx:1354), so a wide persisted chat width can't be realized once the left panel expands — which reintroduces the very jump this commit is meant to fix.

Repro (1440px viewport):

  1. Collapse the left panel, then drag the chat panel wide (up to its 75vw max — reachable while collapsed since the content panel is ~96vw).
  2. Expand the left panel.

sessionPanelSizeWithinContent becomes 75 / 76 × 100 ≈ 98.7% of the content panel (App.tsx:537), which would leave the canvas at ~1.3% — below its 20% minimum. react-resizable-panels clamps the canvas to 20%, so the chat panel lands at ~80% of content ≈ 60.8vw instead of 75vw — a ~200px jump on toggle. sessionPanelMaxSizeWithinContent (App.tsx:545) has the same problem: it can exceed the ~80%-of-content the canvas min actually permits, so the declared max isn't realizable in the expanded state.

The jump triggers for any stored width above ~61vw (= 80% of expanded content), which is well inside the allowed 0–75vw range. It also bites at the default 50vw on narrower (≲900px) viewports, where the left panel takes a large share and squeezes the content panel.

Root cause: toContentRelativePercent clamps to [0, 100], but the session panel's true ceiling is 100 − canvasMin (= 80%) of the content panel.

Suggested fix: clamp the session size and max to 100 − CANVAS_MIN_SIZE_PERCENT of content — ideally introduce a shared CANVAS_MIN_SIZE_PERCENT = 20 used both here and for the canvas minSize. At very narrow viewports you genuinely can't honor both a wide chat and the canvas minimum, so the goal is graceful clamping (no fight/jump), not preserving an impossible width.

Since this touches the exact behavior the follow-up advertises, it might be cleanest to either land the clamp here, or split the sizing fix into its own PR so the rail — which is ready — isn't held up by it.

Worth one manual check (unconfirmed)

The programmatic-collapse effect deps are [effectiveCommentsPanelSize, leftPanelCollapsed] (App.tsx:607) and don't include leftPanelCollapsedSize. On a hard refresh where the panel is collapsed-by-default and currentBoard populates a beat later (flipping the rail width 0 → 56px), does the rail paint at full width immediately, or only after the next toggle? The CSS minWidth: 56 likely backstops it, but a single reload with the panel collapsed would confirm.

Nit

The App.tsx comment stating the rail uses "the same gating the old floating knob used" slightly overstates parity — the old knob was gated only on currentBoard, whereas the rail also requires !suppressLeftPanel (via leftPanelCollapsed). Better gating, just not identical.


Verdict: rail change is mergeable as-is; recommend addressing (or splitting out) the session-width clamp before merging the sizing follow-up, since it can still produce a visible width jump at wide chat widths / narrow viewports.

kasiazjc and others added 4 commits July 3, 2026 10:23
The floating reopen button for the collapsed left panel was clipped
almost in half by the viewport edge and used low-contrast neutral
tokens, making it hard to find. Swap it for an always-fully-visible
56px icon rail (Assistant / All sessions / Comments, Slack-nav style)
that opens the panel directly on the clicked tab, and carry the
unread-comments badge through to the collapsed state.
… toggles

The session panel's persisted size was a percentage of the content panel
(canvas + session panel), not the viewport. Collapsing the left panel to
the rail grew the content panel's absolute width, so the session panel
kept the same percentage but a different pixel width, and vice versa on
expand.

Reinterpret the stored size as a percentage of the full viewport and
convert to/from the content-panel-relative percentage react-resizable-panels
needs at render, resize, and drag-persist time, so the chat panel's pixel
width no longer drifts when the left rail toggles or is dragged.
Each rail button already shows a visible text label under its icon,
so the Tooltip just repeated it. aria-label stays for accessibility.
@kgabryje kgabryje force-pushed the fix-123-agent-tab-collapse-rail branch from 14166d2 to b5e4fb1 Compare July 3, 2026 10:25
@kgabryje kgabryje marked this pull request as ready for review July 3, 2026 10:30
@kgabryje kgabryje merged commit 71d0816 into main Jul 7, 2026
2 checks passed
@kgabryje kgabryje deleted the fix-123-agent-tab-collapse-rail branch July 7, 2026 09:58
kgabryje added a commit that referenced this pull request Jul 7, 2026
…tion (#1829)

The #1762 merge left two `unreadCommentsCount` declarations in App.tsx: a
stale block computing it from an undefined `activeComments` array (a leftover
from a pre-refactor version of the file, also referencing an unimported
`BoardComment` type) and the current store-selector version
(`makeUnreadCommentCountSelector`). The stale block broke agor-ui typecheck
and the App.rerender test import on main.

Delete the stale `activeComments`-based block; keep the store-derived value,
which the icon-rail render sites already consume.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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