Skip to content

[codex] Fix AG-UI App-mode sidebar collapse regression#752

Merged
blove merged 1 commit into
mainfrom
codex/ag-ui-postrelease-backlog
Jul 6, 2026
Merged

[codex] Fix AG-UI App-mode sidebar collapse regression#752
blove merged 1 commit into
mainfrom
codex/ag-ui-postrelease-backlog

Conversation

@blove

@blove blove commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Move the AG-UI chat sidebar panel below the demo toolbar so its close control is actually clickable.
  • Add an App-mode sidebar e2e regression that closes and reopens the chat rail, then verifies the map remains framed in the sidebar content slot.

Root cause

The demo toolbar has a higher z-index for portaled select menus. The App-mode chat sidebar panel was top-aligned under that toolbar stacking context, leaving the close button visible but intercepted by toolbar elements.

Validation

  • npx playwright test examples/ag-ui/angular/e2e/app-mode-promo.spec.ts -c examples/ag-ui/angular/e2e/playwright.config.ts
  • npx nx lint examples-ag-ui-angular (0 errors; existing warnings remain)

@vercel

vercel Bot commented Jul 6, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
threadplane Ready Ready Preview, Comment Jul 6, 2026 5:36pm

Request Review

@github-actions github-actions Bot 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.

Automated approval: this PR received an intelligent (AI) code review. See the review comments on this PR.

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Claude finished @blove's task in 1m 33s —— View job


PR Review

  • Gather context
  • Read PR diff and changed files
  • Review CSS changes
  • Review e2e test additions
  • Post findings

Summary

The fix is correct and well-scoped. The root cause (toolbar z-index intercepting the panel close button) is accurately described, and changing top: 0top: var(--demo-toolbar-height) cleanly resolves it without touching z-index values. The ::ng-deep usage is deprecated but consistent with the existing shell stylesheet pattern and appropriately scoped.

The new regression test is thorough — it covers open, close, and reopen state transitions with layout assertions at each step. Three minor notes left as inline comments:

  1. occupyRight string assertion (line 114) — asserting '0px' exactly is slightly fragile; parseFloat(…) would be more robust. Suggestion included.
  2. Magic number thresholds (lines 98–104) — the > 300 and > 500 values are implicit sidebar-width assumptions; a brief comment would make future adjustments obvious. Inline note.
  3. Double layoutState() call after poll (line 110) — no real bug, but there's a small window between poll settling and the re-evaluation; worth knowing if the test flakes. Inline note.

No correctness bugs, no security issues, no type-safety problems. Good to merge after considering the inline suggestions.

@blove blove enabled auto-merge (squash) July 6, 2026 17:34
await expect(sidebar).toHaveAttribute('data-open', 'false');
await expect(panel).toHaveAttribute('data-open', 'false');
await expect(page.getByRole('button', { name: 'Open chat' })).toBeVisible();
await expect.poll(async () => parseFloat((await layoutState()).marginRight)).toBe(0);

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.

Minor: after expect.poll() resolves on this line, layoutState() is called again immediately on line 112. There's a tiny window where layout could still be transitioning. In practice the poll acts as a synchronisation barrier, so this is unlikely to flake — just worth knowing if this test is occasionally unstable in CI.


const closedLayout = await layoutState();
expect(closedLayout.rootClaim).toBeNull();
expect(closedLayout.occupyRight).toBe('0px');

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.

Potential brittleness: asserts the CSS variable is exactly '0px'. If the library ever sets --tplane-chat-occupy-right to '0' (no unit suffix) on close, this fails incorrectly. Using parseFloat would be more robust and consistent with how marginRight is checked elsewhere.

Suggested change
expect(closedLayout.occupyRight).toBe('0px');
expect(parseFloat(closedLayout.occupyRight)).toBe(0);

Comment on lines +98 to +104
await expect.poll(async () => parseFloat((await layoutState()).marginRight)).toBeGreaterThan(300);
const openLayout = await layoutState();
expect(openLayout.rootClaim).toBe('open');
expect(parseFloat(openLayout.marginRight)).toBeGreaterThan(300);
expect(openLayout.contentWidth).toBeGreaterThan(500);
expect(openLayout.mapWidth).toBeCloseTo(openLayout.contentWidth, 0);
expect(openLayout.mapRight).toBeCloseTo(openLayout.contentRight, 0);

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.

The > 300 (margin-right) and > 500 (content width) thresholds are implicit assumptions about the sidebar panel width at 1280 × 800. A short comment — e.g. // sidebar panel is ~350px wide — makes the intent clear and makes future threshold adjustments obvious if the default panel width ever changes.

await expect(sidebar).toHaveAttribute('data-open', 'false');
await expect(panel).toHaveAttribute('data-open', 'false');
await expect(page.getByRole('button', { name: 'Open chat' })).toBeVisible();
await expect.poll(async () => parseFloat((await layoutState()).marginRight)).toBe(0);

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.

Minor: parseFloat((await layoutState()).marginRight).toBe(0) is consistent with the rest of the test, but once the sidebar is closed the computed marginRight will be "0px"parseFloat0, so this works. The same approach as line 98 / 123 is fine.

One thing worth noting: after expect.poll() resolves on line 110, the test calls layoutState() again on line 112. There's a tiny window where the layout could still be transitioning. In practice the poll settling acts as a synchronisation barrier, so this is unlikely to flake — just worth knowing if this test is occasionally unstable in CI.


const closedLayout = await layoutState();
expect(closedLayout.rootClaim).toBeNull();
expect(closedLayout.occupyRight).toBe('0px');

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.

Potential brittleness: this asserts the CSS variable is the string '0px' exactly. If the library ever sets --tplane-chat-occupy-right to '0' (no unit) when the sidebar closes, this assertion fails incorrectly. Using parseFloat(closedLayout.occupyRight)toBe(0) would be more robust and consistent with how marginRight is checked elsewhere.

Suggested change
expect(closedLayout.occupyRight).toBe('0px');
expect(parseFloat(closedLayout.occupyRight)).toBe(0);

Comment on lines +98 to +104
await expect.poll(async () => parseFloat((await layoutState()).marginRight)).toBeGreaterThan(300);
const openLayout = await layoutState();
expect(openLayout.rootClaim).toBe('open');
expect(parseFloat(openLayout.marginRight)).toBeGreaterThan(300);
expect(openLayout.contentWidth).toBeGreaterThan(500);
expect(openLayout.mapWidth).toBeCloseTo(openLayout.contentWidth, 0);
expect(openLayout.mapRight).toBeCloseTo(openLayout.contentRight, 0);

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.

The > 300 (margin-right) and > 500 (content width) thresholds are implicit assumptions about the sidebar panel width at a 1280 × 800 viewport. They'll silently regress if the default panel width changes. A short comment stating the expected relationship — e.g. "sidebar panel is ~350px wide" — makes the intent clear and makes future threshold adjustments obvious.

@blove blove merged commit 9fe701a into main Jul 6, 2026
28 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.

1 participant