Skip to content

FilterPanel dropdown does not clamp to the viewport - opens off-screen when its trigger sits near the right edge #200

Description

@einari

What happened

FilterPanel positions itself with position: fixed, computing left/top purely from the trigger's getBoundingClientRect():

useEffect(() => {
    if (isOpen && anchorRef.current) {
        const rect = anchorRef.current.getBoundingClientRect();
        setPosition({ top: rect.bottom + 8, left: rect.left });
    }
}, [isOpen]);

(Source/JavaScript/Filter/FilterPanel.tsx, compiled output at dist/esm/Filter/FilterPanel.js.)

The panel then renders at that left and extends rightward by its own intrinsic width, with no check against window.innerWidth and no fallback to open leftward (right-aligned) when there isn't enough room. If the trigger sits close to the right edge of the viewport - a completely ordinary layout, e.g. a filter button placed at the end of a full-width toolbar row (search box flex: 1 + trailing filter button) - most of the panel renders past the edge of the viewport and is unreachable/unreadable.

Repro

  1. Put a FilterPanel trigger button as the last item in a full-width flex row (so its right edge is near the browser window's right edge) - a very common toolbar pattern.
  2. Give it 2+ facets with several options each (panel's natural width ends up ~260-320px).
  3. Open the panel.

Expected: the panel repositions (e.g. right-aligns to the trigger, or clamps left so left + panelWidth <= window.innerWidth) so it stays fully visible.
Observed: the panel opens at left: <trigger's left edge> regardless of remaining viewport width, so most of its content (facet labels, checkboxes, the label search box) renders off-screen to the right - functionally unusable without manually resizing the window or scrolling in a way the page doesn't support.

Impact

Every consumer whose natural UI placement for a filter trigger is "at the end of a toolbar" (arguably the most common placement for this kind of control - see e.g. GitHub's own "Filters"-style buttons, which right-align their dropdowns for exactly this reason) hits this. The only workaround today is avoiding that placement altogether (e.g. moving the trigger to the start of the row instead), which isn't always the right layout for the surrounding UI.

Suggested direction

On open, after the panel has its natural size, check whether rect.left + panelWidth would exceed window.innerWidth (and similarly for vertical overflow against window.innerHeight) and flip to right-aligning against the trigger's right edge (and/or clamp) in that case - the same kind of collision detection most portal-based dropdown/popover libraries do. Leaving the exact approach to whoever owns the component.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions