Skip to content

fix(autocomplete): auto-selection on blur when input is empty#5432

Closed
adi-ray wants to merge 7 commits into
heroui-inc:canaryfrom
adi-ray:fix/autocomplete-blur-empty
Closed

fix(autocomplete): auto-selection on blur when input is empty#5432
adi-ray wants to merge 7 commits into
heroui-inc:canaryfrom
adi-ray:fix/autocomplete-blur-empty

Conversation

@adi-ray
Copy link
Copy Markdown

@adi-ray adi-ray commented Jul 1, 2025

Closes #5396

📝 Description

Fixed a bug where tabbing away from an empty Autocomplete input would automatically select the top option instead of leaving the input empty. This was causing accessibility issues for keyboard users who couldn't leave optional inputs empty.

⛳️ Current behavior (updates)

  • When an empty autocomplete input loses focus (e.g., by tabbing away), the component automatically selects the first available option
  • This happens because the focus management logic sets a focused key on the first item when the dropdown opens, and the blur event saves this selection
  • Keyboard users cannot leave optional autocomplete inputs empty, creating an accessibility barrier

🚀 New behavior

  • When an empty autocomplete input loses focus, no option is automatically selected
  • The input remains empty as expected
  • The focused key and selected key are properly cleared when blurring from an empty input
  • Keyboard users can successfully leave optional autocomplete inputs empty

💣 Is this a breaking change (Yes/No):

No - This is a bug fix that corrects unintended behavior. The change makes the component behave as users would expect and improves accessibility without breaking existing functionality.

Summary by CodeRabbit

  • Bug Fixes
    • Resolved an issue where an autocomplete option was automatically selected when the input field was empty and lost focus. Now, no option will be selected in this scenario, preventing unintended selections.
  • Tests
    • Added tests to verify blur behavior ensuring no option is selected when input is empty and focus is lost, and preserving selection when input has a value.
    • Updated focus management tests to reflect new behavior for empty input scenarios.

@adi-ray adi-ray requested a review from jrgarciadev as a code owner July 1, 2025 20:35
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Jul 1, 2025

🦋 Changeset detected

Latest commit: b628b16

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@heroui/autocomplete Patch
@heroui/react Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link
Copy Markdown

vercel Bot commented Jul 1, 2025

@adi-ray is attempting to deploy a commit to the HeroUI Inc Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jul 1, 2025

Walkthrough

A patch was applied to the autocomplete component to change its behavior when the input field loses focus. Now, if the input is empty and the dropdown is open, no autocomplete option is selected upon blur, resolving an accessibility bug where tabbing away would previously select the top option.

Changes

File(s) Change Summary
packages/components/autocomplete/src/use-autocomplete.ts Modified blur handling: prevents auto-selection when input is empty and dropdown is open; refactored input props logic; improved effect dependencies.
packages/components/autocomplete/tests/autocomplete.test.tsx Added tests for blur behavior ensuring no auto-selection on empty input blur and preserving selection on non-empty input; updated existing focus tests.
.changeset/clever-bikes-pull.md Added changeset describing the patch and its purpose.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant InputField
    participant AutocompleteDropdown

    User->>InputField: Blur (tab away)
    InputField->>AutocompleteDropdown: Check if open and input is empty
    alt Input is empty and dropdown is open
        AutocompleteDropdown-->>InputField: Clear focused and selected key
    else Input is not empty or dropdown closed
        AutocompleteDropdown-->>InputField: No change to selection
    end
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Assessment against linked issues

Objective Addressed Explanation
Prevent auto-selection of top option when tabbing away from empty autocomplete input (#5396)
Ensure input remains empty when tabbing away from an empty autocomplete input (#5396)
Match React-Aria combobox behavior for blur on empty input (#5396)

Assessment against linked issues: Out-of-scope changes

No out-of-scope changes identified.

Possibly related PRs

Suggested reviewers

  • wingkwong
  • jrgarciadev

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8fb7596 and b628b16.

📒 Files selected for processing (1)
  • packages/components/autocomplete/src/use-autocomplete.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/components/autocomplete/src/use-autocomplete.ts
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@adi-ray adi-ray changed the title Fix autocomplete auto-selection on blur when input is empty (fix #5396) fix(autocomplete): auto-selection on blur when input is empty (fix #5396) Jul 1, 2025
@adi-ray adi-ray changed the title fix(autocomplete): auto-selection on blur when input is empty (fix #5396) fix(autocomplete): auto-selection on blur when input is empty Jul 1, 2025
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 584d1c2 and 994e99d.

📒 Files selected for processing (2)
  • .changeset/clever-bikes-pull.md (1 hunks)
  • packages/components/autocomplete/src/use-autocomplete.ts (4 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: TypeScript
  • GitHub Check: Continuous Release
  • GitHub Check: Build
  • GitHub Check: ESLint
🔇 Additional comments (3)
packages/components/autocomplete/src/use-autocomplete.ts (3)

354-356: Good optimization to prevent unnecessary focus updates.

The early return when the dropdown is closed prevents unnecessary focus management operations, improving performance and avoiding potential side effects.


375-375: Correctly updated dependency array to include state.isOpen.

Adding state.isOpen to the dependency array ensures the effect properly responds to dropdown open/close state changes, which is essential for the early return logic added above.


484-516: Excellent fix for the accessibility issue with proper fallback handling.

The onBlur override correctly addresses the auto-selection problem by:

  • Clearing focused key when input is empty and dropdown is open
  • Clearing selected key if one exists
  • Preserving and calling the original onBlur handler

This ensures keyboard users can leave optional autocomplete inputs empty without unwanted auto-selection, fixing the accessibility barrier described in issue #5396.

Comment thread .changeset/clever-bikes-pull.md Outdated
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Jul 1, 2025

Open in StackBlitz

@heroui/accordion

npm i https://pkg.pr.new/@heroui/accordion@5432

@heroui/alert

npm i https://pkg.pr.new/@heroui/alert@5432

@heroui/autocomplete

npm i https://pkg.pr.new/@heroui/autocomplete@5432

@heroui/avatar

npm i https://pkg.pr.new/@heroui/avatar@5432

@heroui/badge

npm i https://pkg.pr.new/@heroui/badge@5432

@heroui/breadcrumbs

npm i https://pkg.pr.new/@heroui/breadcrumbs@5432

@heroui/button

npm i https://pkg.pr.new/@heroui/button@5432

@heroui/calendar

npm i https://pkg.pr.new/@heroui/calendar@5432

@heroui/card

npm i https://pkg.pr.new/@heroui/card@5432

@heroui/checkbox

npm i https://pkg.pr.new/@heroui/checkbox@5432

@heroui/chip

npm i https://pkg.pr.new/@heroui/chip@5432

@heroui/code

npm i https://pkg.pr.new/@heroui/code@5432

@heroui/date-input

npm i https://pkg.pr.new/@heroui/date-input@5432

@heroui/date-picker

npm i https://pkg.pr.new/@heroui/date-picker@5432

@heroui/divider

npm i https://pkg.pr.new/@heroui/divider@5432

@heroui/drawer

npm i https://pkg.pr.new/@heroui/drawer@5432

@heroui/dropdown

npm i https://pkg.pr.new/@heroui/dropdown@5432

@heroui/form

npm i https://pkg.pr.new/@heroui/form@5432

@heroui/image

npm i https://pkg.pr.new/@heroui/image@5432

@heroui/input

npm i https://pkg.pr.new/@heroui/input@5432

@heroui/input-otp

npm i https://pkg.pr.new/@heroui/input-otp@5432

@heroui/kbd

npm i https://pkg.pr.new/@heroui/kbd@5432

@heroui/link

npm i https://pkg.pr.new/@heroui/link@5432

@heroui/listbox

npm i https://pkg.pr.new/@heroui/listbox@5432

@heroui/menu

npm i https://pkg.pr.new/@heroui/menu@5432

@heroui/modal

npm i https://pkg.pr.new/@heroui/modal@5432

@heroui/navbar

npm i https://pkg.pr.new/@heroui/navbar@5432

@heroui/number-input

npm i https://pkg.pr.new/@heroui/number-input@5432

@heroui/pagination

npm i https://pkg.pr.new/@heroui/pagination@5432

@heroui/popover

npm i https://pkg.pr.new/@heroui/popover@5432

@heroui/progress

npm i https://pkg.pr.new/@heroui/progress@5432

@heroui/radio

npm i https://pkg.pr.new/@heroui/radio@5432

@heroui/ripple

npm i https://pkg.pr.new/@heroui/ripple@5432

@heroui/scroll-shadow

npm i https://pkg.pr.new/@heroui/scroll-shadow@5432

@heroui/select

npm i https://pkg.pr.new/@heroui/select@5432

@heroui/skeleton

npm i https://pkg.pr.new/@heroui/skeleton@5432

@heroui/slider

npm i https://pkg.pr.new/@heroui/slider@5432

@heroui/snippet

npm i https://pkg.pr.new/@heroui/snippet@5432

@heroui/spacer

npm i https://pkg.pr.new/@heroui/spacer@5432

@heroui/spinner

npm i https://pkg.pr.new/@heroui/spinner@5432

@heroui/switch

npm i https://pkg.pr.new/@heroui/switch@5432

@heroui/table

npm i https://pkg.pr.new/@heroui/table@5432

@heroui/tabs

npm i https://pkg.pr.new/@heroui/tabs@5432

@heroui/toast

npm i https://pkg.pr.new/@heroui/toast@5432

@heroui/tooltip

npm i https://pkg.pr.new/@heroui/tooltip@5432

@heroui/user

npm i https://pkg.pr.new/@heroui/user@5432

@heroui/react

npm i https://pkg.pr.new/@heroui/react@5432

@heroui/system

npm i https://pkg.pr.new/@heroui/system@5432

@heroui/system-rsc

npm i https://pkg.pr.new/@heroui/system-rsc@5432

@heroui/theme

npm i https://pkg.pr.new/@heroui/theme@5432

@heroui/use-aria-accordion

npm i https://pkg.pr.new/@heroui/use-aria-accordion@5432

@heroui/use-aria-accordion-item

npm i https://pkg.pr.new/@heroui/use-aria-accordion-item@5432

@heroui/use-aria-button

npm i https://pkg.pr.new/@heroui/use-aria-button@5432

@heroui/use-aria-link

npm i https://pkg.pr.new/@heroui/use-aria-link@5432

@heroui/use-aria-modal-overlay

npm i https://pkg.pr.new/@heroui/use-aria-modal-overlay@5432

@heroui/use-aria-multiselect

npm i https://pkg.pr.new/@heroui/use-aria-multiselect@5432

@heroui/use-aria-overlay

npm i https://pkg.pr.new/@heroui/use-aria-overlay@5432

@heroui/use-callback-ref

npm i https://pkg.pr.new/@heroui/use-callback-ref@5432

@heroui/use-clipboard

npm i https://pkg.pr.new/@heroui/use-clipboard@5432

@heroui/use-data-scroll-overflow

npm i https://pkg.pr.new/@heroui/use-data-scroll-overflow@5432

@heroui/use-disclosure

npm i https://pkg.pr.new/@heroui/use-disclosure@5432

@heroui/use-draggable

npm i https://pkg.pr.new/@heroui/use-draggable@5432

@heroui/use-form-reset

npm i https://pkg.pr.new/@heroui/use-form-reset@5432

@heroui/use-image

npm i https://pkg.pr.new/@heroui/use-image@5432

@heroui/use-infinite-scroll

npm i https://pkg.pr.new/@heroui/use-infinite-scroll@5432

@heroui/use-intersection-observer

npm i https://pkg.pr.new/@heroui/use-intersection-observer@5432

@heroui/use-is-mobile

npm i https://pkg.pr.new/@heroui/use-is-mobile@5432

@heroui/use-is-mounted

npm i https://pkg.pr.new/@heroui/use-is-mounted@5432

@heroui/use-measure

npm i https://pkg.pr.new/@heroui/use-measure@5432

@heroui/use-pagination

npm i https://pkg.pr.new/@heroui/use-pagination@5432

@heroui/use-real-shape

npm i https://pkg.pr.new/@heroui/use-real-shape@5432

@heroui/use-ref-state

npm i https://pkg.pr.new/@heroui/use-ref-state@5432

@heroui/use-resize

npm i https://pkg.pr.new/@heroui/use-resize@5432

@heroui/use-safe-layout-effect

npm i https://pkg.pr.new/@heroui/use-safe-layout-effect@5432

@heroui/use-scroll-position

npm i https://pkg.pr.new/@heroui/use-scroll-position@5432

@heroui/use-ssr

npm i https://pkg.pr.new/@heroui/use-ssr@5432

@heroui/use-theme

npm i https://pkg.pr.new/@heroui/use-theme@5432

@heroui/use-update-effect

npm i https://pkg.pr.new/@heroui/use-update-effect@5432

@heroui/use-viewport-size

npm i https://pkg.pr.new/@heroui/use-viewport-size@5432

@heroui/aria-utils

npm i https://pkg.pr.new/@heroui/aria-utils@5432

@heroui/dom-animation

npm i https://pkg.pr.new/@heroui/dom-animation@5432

@heroui/framer-utils

npm i https://pkg.pr.new/@heroui/framer-utils@5432

@heroui/react-rsc-utils

npm i https://pkg.pr.new/@heroui/react-rsc-utils@5432

@heroui/react-utils

npm i https://pkg.pr.new/@heroui/react-utils@5432

@heroui/shared-icons

npm i https://pkg.pr.new/@heroui/shared-icons@5432

@heroui/shared-utils

npm i https://pkg.pr.new/@heroui/shared-utils@5432

@heroui/stories-utils

npm i https://pkg.pr.new/@heroui/stories-utils@5432

@heroui/test-utils

npm i https://pkg.pr.new/@heroui/test-utils@5432

commit: b628b16

@vercel
Copy link
Copy Markdown

vercel Bot commented Jul 2, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
heroui ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 28, 2025 9:14am
heroui-sb ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 28, 2025 9:14am

Copy link
Copy Markdown
Member

@wingkwong wingkwong left a comment

Choose a reason for hiding this comment

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

  1. Please include a new test to cover the logic you added
  2. Focus ring is gone in your PR after the first tab (see below screenshot)
  3. The label and the cursor are overlapping after the first tab (see below screenshot)

Your PR:

image

Production:
image

adi-ray added 2 commits July 7, 2025 15:44
- Address label positioning issues during focus transitions
@craigbehnke
Copy link
Copy Markdown

Sorry to nag, but I'm really looking forward to having this change be shipped. Is there an update on this?

Copy link
Copy Markdown
Member

@wingkwong wingkwong left a comment

Choose a reason for hiding this comment

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

This PR will alter the existing focusing the first non-disabled item behaviour.

Expected:

  • press tab
    • autocomplete is focused
    • listbox is shown with the first non-disabled item highlighted (your PR broke here)
  • press tab again
    • autocomplete is closed
    • no value will be set in autocomplete

Comment thread packages/components/autocomplete/src/use-autocomplete.ts Outdated
Comment thread packages/components/autocomplete/src/use-autocomplete.ts Outdated
@wingkwong
Copy link
Copy Markdown
Member

@adi-ray May I know if there is any update on this PR?

@wingkwong
Copy link
Copy Markdown
Member

Closing - inactivity

@wingkwong wingkwong closed this Nov 16, 2025
@adi-ray adi-ray deleted the fix/autocomplete-blur-empty branch November 16, 2025 17:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] - Tabbing away from empty Autocomplete input selects the top option

3 participants