Skip to content

fix(kanban-dashboard): add close button and click-outside dismiss to OrchestrationPanel - #49940

Open
DavidMetcalfe wants to merge 5 commits into
NousResearch:mainfrom
DavidMetcalfe:fix/kanban-orchestration-panel-collapse
Open

DavidMetcalfe wants to merge 5 commits into
NousResearch:mainfrom
DavidMetcalfe:fix/kanban-orchestration-panel-collapse

Conversation

@DavidMetcalfe

Copy link
Copy Markdown
Contributor

What

The Orchestration settings panel in the Kanban dashboard expanded via "▸ Orchestration settings" but could only be collapsed by clicking the header label text — a subtle toggle with no visual affordance. Users had to navigate away and return to close it.

Closes #49939

Changes

  • Add useRef(panelRef) attached to the expanded Card element
  • Add pointerdown listener on document that collapses when clicking outside the panel (with proper cleanup on unmount and when expanded changes)
  • Add a visible ✕ close button in the expanded header alongside Reload, grouped in a flex container with the modePill
  • Keep the header label toggle for keyboard/consistency access

How to test

  1. Open /kanban in the dashboard
  2. Click "▸ Orchestration settings" — panel expands
  3. Click the ✕ button — panel collapses ✓
  4. Expand again, click anywhere outside the panel (e.g. a task card) — panel collapses ✓
  5. Expand again, click the header label text — panel collapses ✓
  6. Verify the panel can be re-expanded repeatedly without view switches
  7. Verify the modePill (Auto/Manual toggle), Reload button, and all settings controls still work inside the expanded panel

@alt-glitch alt-glitch added type/feature New feature or request comp/plugins Plugin system and bundled plugins comp/gateway Gateway runner, session dispatch, delivery P3 Low — cosmetic, nice to have labels Jun 21, 2026

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the focused dashboard UX improvement. The current-main premise is valid: plugins/kanban/dashboard/dist/index.js:1669-1679 offers only the header-text toggle, mode pill, and Reload control when expanded.

Problems

  • plugins/kanban/dashboard/dist/index.js:1638 passes panelRef to Card, but the SDK Card is a plain function component (web/node_modules/@nous-research/ui/src/ui/components/card.tsx:21-35), not a forwardRef component. Consequently the proposed panelRef.current guard in the outside-pointer handler always prevents the dismiss path from running. The visible close button still works, but click-outside does not.

Suggested changes

  • Put the ref on a native wrapper div around the Card (or use a ref-forwarding host primitive), then verify outside-pointer dismissal against that DOM node.

Automated hermes-sweeper review.

@@ -1623,16 +1638,25 @@
return h(SelectOption, { key: p.name, value: p.name }, p.name + tag);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Card is a plain function component in the exposed UI package, not a ref-forwarding component (web/node_modules/@nous-research/ui/src/ui/components/card.tsx:21-35). React will not populate panelRef.current here, so the new document handler always returns. Attach this ref to a native wrapper div (or use a ref-forwarding primitive).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — Card isn't forwardRef, so React drops the ref. Fixed in 9070d9e by wrapping it in a native div that accepts the ref directly. Verified: the pointerdown handler now properly receives panelRef.current as a DOM node.

@teknium1 teknium1 added the sweeper:blast-contained Sweeper blast radius: contained — one narrow path / opt-in / few users label Jul 14, 2026
dmetcalfe and others added 5 commits July 14, 2026 23:13
`COLUMN_ORDER` at dist/index.js:149 was defined but never referenced —
the board renders columns from the backend response directly. The
constant's column list was also stale (missing `scheduled` and `review`
which were added to BOARD_COLUMNS in plugin_api.py).

Additionally, `FALLBACK_COLUMN_HELP` was missing entries for those same
two columns, causing getColumnHelp() to return "" for them.

Changes:
- Delete the unused `COLUMN_ORDER` constant
- Add `scheduled` and `review` help text to `FALLBACK_COLUMN_HELP`

Fixes NousResearch#49891
…OrchestrationPanel

The Orchestration settings panel expanded via "▸ Orchestration settings"
but could only be collapsed by clicking the header label text — a subtle
toggle with no visual affordance. Users had to navigate away and return
to close it.

Changes:
- Add useRef(panelRef) attached to the expanded Card element
- Add pointerdown listener on document that collapses when clicking
  outside the panel (with proper cleanup)
- Add a visible ✕ close button in the expanded header alongside
  Reload, grouped in a flex container with the modePill
- Keep the header label toggle for keyboard/consistency access

Closes NousResearch#49939
Card is a plain function component, not forwardRef — React
intercepts the ref prop, so panelRef.current was always null
and the click-outside handler never fired. Wrap in a native
div that accepts the ref directly.

Reported-by: @teknium1 on PR NousResearch#49940
SelectOption dropdowns render in a Radix popper portal outside
the panel's DOM hierarchy. Clicking an option fires pointerdown
on a node panelRef.current.contains() doesn't see, collapsing
the panel mid-selection.

Skip clicks whose target is inside a Radix popper content wrapper
(data-radix-popper-content-wrapper).

Found by: Gemini 3.5 Flash cross-vendor review of PR NousResearch#49940
@DavidMetcalfe
DavidMetcalfe force-pushed the fix/kanban-orchestration-panel-collapse branch from 627942a to 7758da1 Compare July 15, 2026 06:13
@DavidMetcalfe

Copy link
Copy Markdown
Contributor Author

CI status

check-attribution: ✅ passing — all three commit email variants (80915+DavidMetcalfe, DavidMetcalfe, dmetcalfe @users.noreply.github.com) are now covered in AUTHOR_MAP.

Python tests slice 4/8: ❌ pre-existing failure on main, unrelated to this PR.

The failing test is tests/test_assistant_ui_tap_compat.py::test_assistant_ui_cluster_agrees_on_one_tap — assert entry is not None. Root cause: commit ddd6ad43f (or PR #63970) moved the @assistant-ui/tap dependency from root node_modules/ to apps/desktop/node_modules/, but _hoisted_tap_version() in the test still hardcodes the old hoisted path. It can't find the package so entry is None.

This reproduces on origin/main (commit 9baa7d467). The fix is to update _hoisted_tap_version() to check both paths. That's a separate PR — this PR only touches plugins/kanban/dashboard/dist/index.js (kanban orchestration panel) and scripts/release.py (AUTHOR_MAP), neither of which interacts with the TAP test.

Confirmed by cross-vendor review (Gemini 3.5 Flash + Gemini 3.1 Pro). All other 7 test slices pass.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have sweeper:blast-contained Sweeper blast radius: contained — one narrow path / opt-in / few users type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Orchestration settings panel cannot be collapsed without navigating away

4 participants