Skip to content

Hide filtered-out groups and dangling dividers in select listboxes - #434

Merged
czarandy merged 1 commit into
mainfrom
worktree-issue-413-group-filtering
Aug 5, 2026
Merged

Hide filtered-out groups and dangling dividers in select listboxes#434
czarandy merged 1 commit into
mainfrom
worktree-issue-413-group-filtering

Conversation

@czarandy

@czarandy czarandy commented Aug 5, 2026

Copy link
Copy Markdown
Owner

Fixes #413.

Problem

The shared listbox renderer emitted each section's role="group" wrapper, its title heading, and every divider unconditionally, while the actual filtering happened per-option inside renderOption (which returns null for non-matches). Searching for a term that matched nothing in a group left that group's header stranded above an empty group; searching zzz in a fully grouped Select showed a stack of orphan headers separated by stray dividers.

Fix

renderSelectListboxOptions now:

  • renders a section's options first and skips the wrapper (heading included) entirely when nothing survived the filter;
  • resolves dividers in a second pass, keeping only the ones that still separate two visible entries — leading, trailing, and now-adjacent dividers are dropped, so a divider left dangling by a hidden group (or a hidden top-level option) disappears with it.

Section and divider counters still advance over skipped entries so React keys stay stable as the query changes.

Note the divider pass also collapses a run of adjacent dividers into one. That's required for the hidden-group case and is what a consumer would want from a literal [{divider}, {divider}] anyway.

Tests

Three regression tests, all verified to fail on main:

  • Select — grouped options under a query that matches one group (other header and the divider go away) and under a no-match query (no headers, no groups, no options).
  • Select — dividers left dangling by the query: two dividers around a filtered-out option collapse to one; a single surviving option keeps none.
  • MultiSelect — the same grouped scenarios.

Full suite, lint, typecheck, and format all pass.

https://claude.ai/code/session_01XFkkvUQfynGRedEYDNxKoY

Filtering happened per-option in `renderOption`, but the shared listbox
renderer emitted the `role="group"` wrapper, its heading, and every divider
unconditionally. A query that matched nothing in a group left its header
stranded over an empty group, and searching for a term that matched nothing at
all showed a stack of orphan headers and stray dividers.

`renderSelectListboxOptions` now renders a section's options first and skips
the whole wrapper when nothing survived the filter, then resolves dividers in a
second pass so only the ones still separating two visible entries are kept --
leading, trailing, and now-adjacent dividers are dropped. Section and divider
counters still advance over skipped entries so React keys stay stable as the
query changes.

Fixes #413

Claude-Session: https://claude.ai/code/session_01XFkkvUQfynGRedEYDNxKoY
@vercel

vercel Bot commented Aug 5, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
silver-ui-site Ready Ready Preview Aug 5, 2026 10:02pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
silver-ui Ignored Ignored Aug 5, 2026 10:02pm

@czarandy
czarandy merged commit b297707 into main Aug 5, 2026
4 checks passed
@czarandy
czarandy deleted the worktree-issue-413-group-filtering branch August 5, 2026 22:46
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.

Select/MultiSelect show orphaned group headers when search filters out a whole group

1 participant