Skip to content

fix(#5250): let settings search results escape the menu clip - #5254

Merged
2 commits merged into
nesquena:masterfrom
rodboev:pr/5250-settings-search-menu-clip
Jun 30, 2026
Merged

2 commits merged into
nesquena:masterfrom
rodboev:pr/5250-settings-search-menu-clip

Conversation

@rodboev

@rodboev rodboev commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Thinking Path

  • Settings search already renders and navigates correctly, but the dropdown lives inside the same scroll container as the Settings section list.
  • The clipping comes from layout ownership, not from ranking or search logic: .side-menu makes #settingsMenu scroll, and the absolute dropdown is clipped by that boundary.
  • The fix keeps the current search renderer and dropdown ids intact, then moves vertical scrolling to a wrapper around the Settings section buttons so the dropdown can escape the menu clip.

What Changed

  • static/index.html: wraps the Settings section buttons in a .settings-menu-items container below the existing search shell.
  • static/style.css: keeps the shared .side-menu rule unchanged, makes #settingsMenu overflow visibly, and gives only .settings-menu-items vertical scrolling.
  • tests/test_3850_settings_search.py: updates the searchable-settings layout contract without changing the search semantics it already covers.
  • tests/test_issue5250_settings_search_dropdown_escape.py: adds a focused browser-level regression proof for the clipped dropdown case.

Why It Matters

Users can now see and click Settings search results even when the dropdown extends past the visible menu boundary. The existing match list, result cap, and click-to-setting flow stay intact.

Verification

pytest tests/test_3850_settings_search.py tests/test_issue5250_settings_search_dropdown_escape.py -v --timeout=60

If present after restacking with the ranking work from #5211:

pytest tests/test_5149_settings_search_ranking.py -v --timeout=60

Manual browser proof fallback if Playwright is unavailable locally: open Settings, type a query with multiple matches, confirm a result remains visible and hit-testable below the menu boundary, then click it and confirm the target section switches and highlights the field.

Full-suite CI context, not a required local check unless explicitly run: pytest tests/ -v --timeout=60.

Upstream

Closes #5250.

Model Used

GPT 5.5 via Codex CLI

@greptile-apps

greptile-apps Bot commented Jun 30, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes settings search dropdown clipping by moving vertical-scroll ownership from #settingsMenu to a new .settings-menu-items child wrapper, allowing the absolutely-positioned results dropdown to escape the menu's overflow boundary.

  • static/style.css: Overrides the inherited overflow-y: auto on #settingsMenu with overflow: visible (higher ID specificity wins over the .side-menu class), and assigns overflow-y: auto; flex: 1 to the new #settingsMenu .settings-menu-items rule so section buttons still scroll internally.
  • static/index.html: Wraps the eight section buttons in <div class=\"settings-menu-items\"> beneath the existing search shell, preserving all data-settings-section attributes and onclick handlers.
  • Tests: test_3850_settings_search.py gains a layout-contract test with properly anchored full-selector regexes; test_issue5250_settings_search_dropdown_escape.py adds a Playwright hit-test that confirms elementFromPoint lands on a search result below the menu's visible boundary, with a graceful pytest.skip when Playwright is absent.

Confidence Score: 5/5

Safe to merge — the change is narrowly scoped to the settings sidebar layout with no impact on routing, data, or auth logic.

The CSS cascade is correct: #settingsMenu { overflow: visible } cleanly overrides the .side-menu class's overflow-y: auto, and scrolling is properly re-delegated to .settings-menu-items. The min-height: 0 guards are present on both the menu and the items wrapper, preventing the common flex-shrink pitfall. The HTML change is mechanical (wrapping siblings in a div) with no attribute mutations. The new Playwright test and updated regex in the existing test both cover the changed contract directly.

No files require special attention.

Important Files Changed

Filename Overview
static/index.html Wraps the eight settings section buttons in a new .settings-menu-items div; structurally clean, preserves all data-settings-section and onclick attributes.
static/style.css Overrides .side-menu's overflow-y:auto on #settingsMenu with overflow:visible, delegates scrolling to #settingsMenu .settings-menu-items; cascade and specificity are correct.
tests/test_3850_settings_search.py Adds test_settings_menu_layout_ownership_contract with properly anchored full-selector regex patterns for both #settingsMenu and #settingsMenu .settings-menu-items.
tests/test_issue5250_settings_search_dropdown_escape.py New Playwright regression test that renders a minimal reproduction page and uses elementFromPoint to verify the dropdown is hit-testable below the menu's clipping boundary; gracefully skips if Playwright is unavailable.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["#settingsMenu.side-menu\n(overflow: visible ← new)"] --> B[".settings-search\n(position: relative)"]
    A --> C[".settings-menu-items\n(overflow-y: auto ← new)"]
    B --> D["input#settingsSearch"]
    B --> E["#settingsSearchResults\n.settings-search-results\n(position: absolute; top:100%; z-index:200)"]
    C --> F["button.side-menu-item × 8\n(scroll within .settings-menu-items)"]
    E -. "escapes clip boundary" .-> G["Visible below #settingsMenu"]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A["#settingsMenu.side-menu\n(overflow: visible ← new)"] --> B[".settings-search\n(position: relative)"]
    A --> C[".settings-menu-items\n(overflow-y: auto ← new)"]
    B --> D["input#settingsSearch"]
    B --> E["#settingsSearchResults\n.settings-search-results\n(position: absolute; top:100%; z-index:200)"]
    C --> F["button.side-menu-item × 8\n(scroll within .settings-menu-items)"]
    E -. "escapes clip boundary" .-> G["Visible below #settingsMenu"]
Loading

Reviews (2): Last reviewed commit: "test(#5250): harden settings menu select..." | Re-trigger Greptile

Comment thread tests/test_3850_settings_search.py
@cutter-sh

cutter-sh Bot commented Jun 30, 2026

Copy link
Copy Markdown

🎬 Cutter preview — PR #5254

/settings
/settings — Settings search results now extend fully below the sidebar instead of being clipped.
Click a previously clipped settings search result
Click a previously clipped settings search result — Settings search jumps to the matching section, here Appearance with its theme and skin options.

@nesquena-hermes nesquena-hermes added the size:M Medium PR (≤10 files, ≤250 LOC) label Jun 30, 2026
@nesquena-hermes

Copy link
Copy Markdown
Collaborator

🔬 Gate certification — GREEN ✅ (visible CSS fix; clip-escape verified live via getComputedStyle)

Certified head: sha:c2a0472514d7 · PR: #5254 · rodboev — "let settings search results escape the menu clip (#5250)" · crit=3 · concept fit: 4/5
Verdict: Clean CSS-layout fix for a clipped-dropdown bug — the settings-search results dropdown now escapes the menu's scroll-clip instead of being cut off. Codex SAFE, suite green, the overflow restructure verified live via getComputedStyle. Ready to merge.

What I ran (isolated worktree /tmp/wt-gate-5254, fresh-based on current master — no rebase needed)

Gate Result
Codex (reproduce) SAFE TO SHIP (no findings — clip-escape works, no menu-scroll/layout/selector regression, z-index correct)
Full pytest suite (-p no:xdist) 11157 passed, 0 failed
PR's tests (test_issue5250 + test_3850_settings_search) 24 passed
Live verification (getComputedStyle) #settingsMenu overflow:visible ✓ · .settings-menu-items overflow-y:auto ✓ · .settings-search-results position:absolute, z-index:200, display:block, renders results ✓

Findings (clean)

  • ✅ Correct clip-escape pattern — the fix wraps the settings side-menu buttons in a new .settings-menu-items flex container that takes the overflow-y:auto scrolling, and sets #settingsMenu to overflow:visible. So the absolutely-positioned .settings-search-results dropdown (top:100%, z-index:200) now overlays outside the scroll container instead of being clipped by it. Verified live: menu overflow:visible, inner wrapper overflow-y:auto, dropdown position:absolute/z-index:200/display:block rendering results.
  • ✅ No menu-scroll regression — scrolling moved cleanly to the inner .settings-menu-items container (the side-menu still scrolls; only the clip boundary moved). Codex confirmed no layout regression.
  • ✅ DOM reparent safe — the side-menu-item buttons moved into the new wrapper retain their data-settings-section + switchSettingsSection(...) handlers; the PR's test hardens the selector contract so this can't silently break. Codex confirmed switchSettingsSection/selectors intact.
  • ✅ Fresh-based on current master; 24 settings-search tests pass.

Note: I attempted a headless screenshot of the open dropdown, but the settings modal didn't paint in the headless-driven state (0×0 rects / no PNG). The fix is a low-visual-risk CSS clip-escape (the "after" simply shows the previously-clipped dropdown rows), and I verified the exact overflow/position contract live via getComputedStyle + Codex. If a visual glance is wanted before merge, opening Settings → typing in the search box on a running instance shows the dropdown overflowing the menu cleanly.

Concept: 4/5 — fixes a real usability bug (#5250: settings-search results clipped/hidden by the menu's overflow); existing-flow polish.

Recommendation to the next agent

Ready to merge — cert fresh for sha:c2a0472514d7. crit=3 CSS clip-escape for the settings-search dropdown; Codex SAFE, full suite green, 24 tests, the overflow restructure (menu visible + inner-wrapper auto + dropdown absolute/z-200) verified live via getComputedStyle, DOM reparent preserves switchSettingsSection/selectors. Fresh-based. Low visual risk (clip-escape). Concept 4/5. Cert valid only at sha:c2a0472514d7.


Gate-certifier layer (warm-up → gate → release). I do not merge/tag/deploy/close. Cert valid only at sha:c2a0472514d7; a new push invalidates it → re-gate.

@nesquena-hermes nesquena-hermes added the gate-pass Full gate passed (Codex+Opus+suite+browser); queued Tier 1 for release agent label Jun 30, 2026
@nesquena-hermes nesquena-hermes closed this pull request by merging all changes into nesquena:master in 8d5ff4c Jun 30, 2026
@nesquena-hermes

Copy link
Copy Markdown
Collaborator

Shipped in v0.51.765 (Wave 1 batch, via release PR #5277). Thanks @rodboev! Combined-stage Codex SAFE + full pytest suite green + ESLint/ruff gates clean. 🎉

franksong2702 pushed a commit to franksong2702/hermes-webui-fork that referenced this pull request Jun 30, 2026
franksong2702 pushed a commit to franksong2702/hermes-webui-fork that referenced this pull request Jun 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gate-pass Full gate passed (Codex+Opus+suite+browser); queued Tier 1 for release agent size:M Medium PR (≤10 files, ≤250 LOC)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Settings search results dropdown gets clipped by the panel boundary

2 participants