Skip to content

[Bug Fix] DropdownMenu: typeahead on indicator items, and Tab moves on past the trigger - #658

Open
pierry01 wants to merge 3 commits into
ruby-ui:mainfrom
pierry01:fix/menu-typeahead-and-tab
Open

pierry01 wants to merge 3 commits into
ruby-ui:mainfrom
pierry01:fix/menu-typeahead-and-tab

Conversation

@pierry01

@pierry01 pierry01 commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Related issue

None opened. Follow-up of the shadcn audit on #579 (the DataTable Columns menu).

Description

Two menu keys behaved differently from shadcn (Base UI):

  • Typeahead did nothing on items with an indicator (checkbox and radio items). labelOf() also read comment nodes, so with Rails' annotate_rendered_view_with_filenames the label became Before RubyUI::DropdownMenuItemIndicatorStatus and no prefix matched. It now reads only text nodes and elements, in DropdownMenu and ContextMenu.
  • Tab with the menu open closed it and left focus on the trigger. Base UI moves on to the next control, and Shift+Tab stops on the trigger. close() already returns focus to the trigger, so Tab's default now runs from there; Shift+Tab is still prevented. The docs text and the controller header say so.

typeahead light
tab light

Dark

typeahead dark
tab dark

shadcn audit · main
shadcn audit  ruby-ui/ruby_ui
  base 1fd93db0  head 1fd93db0  shadcn 8a353667
✅ Theme  neutral tokens match shadcn
DataTable  (ref: bases/base/ui/dropdown-menu.tsx + style-vega.css @ 8a353667)
  ✅ Behavior   click/Enter/ArrowDown open; ArrowDown/ArrowUp wrap; Home/End; Esc and outside click close and return focus to the trigger; menuitemcheckbox + aria-checked
               Driven with Playwright on both sides, same key sequence.
               ↳ bases/base/ui/dropdown-menu.tsx
  ⚠️ Behavior   typeahead: focus on Reviewer, type s -> focus stays on Reviewer
               shadcn: typeahead: focus moves to Status
               labelOf() reads comment nodes too: with annotate_rendered_view_with_filenames the label is "Before RubyUI::DropdownMenuItemIndicatorStatus", so no prefix ever matches. Same code in ContextMenu.
               ↳ bases/base/ui/dropdown-menu.tsx
  ⚠️ Behavior   Tab with the menu open: closes, focus stays on the trigger
               shadcn: Tab: closes, focus moves to the next control (Select all); Shift+Tab: closes, focus on the trigger
               The controller prevented Tab's default after close().
               ↳ bases/base/ui/dropdown-menu.tsx
  ✅ Animation  exit@dropdown-menu-content on close
               Sampled right after Esc on both sides.
               ↳ style-vega.css
shadcn audit · this PR
shadcn audit  ruby-ui/ruby_ui
  base 1fd93db0  head ee918f1e  shadcn 8a353667
✅ Theme  neutral tokens match shadcn
DataTable  (ref: bases/base/ui/dropdown-menu.tsx + style-vega.css @ 8a353667)
  ✅ Behavior   click/Enter/ArrowDown open; ArrowDown/ArrowUp wrap; Home/End; Esc and outside click close and return focus to the trigger; menuitemcheckbox + aria-checked
               Driven with Playwright on both sides, same key sequence.
               ↳ bases/base/ui/dropdown-menu.tsx
  ✅ Behavior   typeahead: focus on Reviewer, type s -> Status
               labelOf() keeps only text nodes and elements. ContextMenu gets the same fix.
               ↳ bases/base/ui/dropdown-menu.tsx
  ✅ Behavior   Tab: closes, focus on Select all; Shift+Tab: closes, focus on the trigger
               close() focuses the trigger first, then Tab's default moves on from it; Shift+Tab is prevented so it stops on the trigger.
               ↳ bases/base/ui/dropdown-menu.tsx
  ✅ Animation  exit@dropdown-menu-content on close
               Sampled right after Esc on both sides.
               ↳ style-vega.css

Testing instructions

  • cd gem && bundle exec rake → 775 runs, 0 failures, StandardRB clean. cd mcp && bundle exec rake → 33 runs, 0 failures.
  • /docs/data_table, Columns menu: ArrowDown to Reviewer, type s → focus on Status.
  • Same menu: Tab → it closes and focus lands on the "Select all" checkbox; reopen, Shift+Tab → focus on Columns.
  • /docs/context_menu: typeahead still moves through plain items.

🤖 Generated with Claude Code


Summary by cubic

Fixes two DropdownMenu and ContextMenu keyboard behaviors to match Base UI: typeahead now works on items with an indicator, and Tab moves focus past the trigger instead of leaving it on the trigger.

Changes

  • Typeahead: labelOf() reads only text nodes and elements, so comment nodes from Rails' annotate_rendered_view_with_filenames no longer break prefix matching on checkbox and radio items.
  • Tab: closing the menu returns focus to the trigger first, so Tab's default carries on to the next control; Shift+Tab is still prevented and stops on the trigger. The closing menu is kept inert while it animates out so focus doesn't land back inside it, and reopening clears that.

Updated the docs text and the controller header comment to describe the new Tab behavior.

Written for commit b5b632d. Summary will update on new commits.

View guided diff

@pierry01
pierry01 requested a review from cirdes as a code owner November 5, 2026 16:57
@pierry01
pierry01 removed the request for review from cirdes November 5, 2026 16:58

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

All reported issues were addressed across 6 files

Reply with feedback, questions, or to request a fix.

View guided diff | Re-trigger cubic

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@pierry01 pierry01 self-assigned this Nov 5, 2026

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

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant