Skip to content

fix(ui): keep card menus whole at the window edge, fold active forwards (#610) - #612

Merged
kipavy merged 1 commit into
devfrom
fix/pf-menu-fit-collapse-610
Oct 11, 2026
Merged

kipavy merged 1 commit into
devfrom
fix/pf-menu-fit-collapse-610

Conversation

@kipavy

@kipavy kipavy commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

Closes #610

Problem

  • Menu cut off. A card's "more options" menu opened under its button with max-height set to the space left below it. On a card near the bottom of the window only one entry showed (the reporter's rule menu shows just "Edit"), and with the button at the very edge the height went negative. ContextMenu already fitted itself horizontally; it never did vertically.
  • Rules pushed off the page. "Active session forwards" lists every auto-detected port of every connected host above the saved rules, with no way to put it aside.

Fix

  • ContextMenu: the root menu's top goes through the same useFittedStart helper as its left edge and as submenus, so it slides up until it fits. max-height is the window height minus margins, and accounts for UI scale.
  • The upward variant (terminal status bar) used a separate bottom-anchored branch with the mirror bug: in the top pane of a split it shrank to the space above the pointer. Both directions now share one path; useFittedStart takes an endsAtAnchor flag. Where there is room the upward menu still ends at the pointer.
  • ActiveTunnelsSection: the section header toggles the cards, using the collapsed/onToggle support SectionHeader already had. The state lives in uiStore (activeTunnelsCollapsed), persisted on the device and not synced.
  • The header shows a red error count when any forward failed, so a folded section cannot hide a broken tunnel.

Every card menu goes through ContextMenu (hosts, keys, snippets, rules, members, known hosts), so the one change covers them all.

Other floating surfaces checked

  • PickerSurface (form selects, snippet and notes menus): already flips above the anchor when less than 150px is left below. Unchanged.
  • Submenus: already fitted vertically. Unchanged.
  • Title bar popovers and toolbar dropdowns: anchored at the top of the window. Unchanged.
  • PanelActionsMenu (edit panel header): has its own unclamped menu shell, but its trigger always sits at the top of the panel. Left as is; moving it onto ContextMenu changes its alignment and deserves its own change.

Cons

  • A menu that slides up covers the button that opened it and part of its card.
  • The upward menu is now positioned by top after a measurement rather than by bottom. The correction happens in a layout effect, before paint.
  • With the section folded, the header's green total still counts working, failed and paused forwards together, as it did before. Only failures get their own count.
  • The fold state is one flag for the whole section, not per host.

Tests

  • ContextMenu.test.tsx: a menu opened low is shifted up and keeps full height; an upward menu ends at the pointer when there is room; an upward menu opened high is pushed down.
  • ActiveTunnelsSection.test.tsx (renamed from .identity.test.tsx, which it outgrew): the header folds and unfolds the cards and keeps the totals; a folded section stays folded on the next render; a folded section still shows the error count; no error count without a failure.
  • vitest on components/shared, components/port_forwarding, components/terminal, stores: 153 files, 985 tests pass. tsc --noEmit: clean.
  • Live, headless desktop build with a real SSH session and 11 auto-detected ports:
    • rule menu opened from a button at the bottom edge of an 800px window: all 9 entries visible, bottom edge at 792px, no scrolling (the old formula gave -12px);
    • section folds, the flag is persisted, rules sit directly under the toolbar;
    • status bar menu still ends at the pointer.
  • Not run live: the error count (the test host would not produce a failed auto forward) and the upward menu in a top split pane. Not run on Android. The app binary in the container predates 0.53.0; the frontend was this branch.

…ds (#610)

A card's "more options" menu opened under its button and was given
only the height left below it. On a card near the bottom of the window
that left a sliver showing one entry, or nothing at all. The menu was
already moved sideways to fit the window; it is now moved vertically
the same way, through the same helper, so it slides up until every
entry is visible. Hosts, keys, snippets, rules, members and known
hosts share this menu and all get the fix.

The terminal status bar menu opens upward and had the mirror problem
in the top pane of a split: it shrank to the space above the pointer.
It goes through the same fit now and is pushed down instead. Where
there is room it still ends at the pointer.

On the Port Forwarding page the "Active session forwards" header folds
the host cards away, so a host with many detected ports no longer
pushes the saved rules off the page. The choice is kept on the device.
The header keeps the host count and tunnel total, and shows an error
count when a forward failed so a folded section cannot hide it.
@kipavy kipavy mentioned this pull request Oct 11, 2026
@kipavy
kipavy merged commit eb06faa into dev Oct 11, 2026
5 checks passed
@kipavy
kipavy deleted the fix/pf-menu-fit-collapse-610 branch October 11, 2026 09:12
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