Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(autocomplete): focus behaviour #2854

Open
wants to merge 35 commits into
base: canary
Choose a base branch
from
Open

fix(autocomplete): focus behaviour #2854

wants to merge 35 commits into from

Conversation

wingkwong
Copy link
Member

@wingkwong wingkwong commented Apr 24, 2024

📝 Description

In react aria, popover can be closed by clicking or interacting outside or by escape key (handled by useOverlay). When the popover is closed, focus is back to the trigger, i.e. the input. Since we have different focus behaviours in autocomplete, this PR is to handle them on our side instead of doing them internally on react aria side for better flexibilty.

here's the updated focus behaviour for autocomplete.

  • click selector button -> open listbox -> click selector button -> close listbox -> input stay focused
  • click selector button -> open listbox -> click outside autocomplete-> close listbox -> input stay blurred
  • click selector button -> open listbox -> input stay focused
  • click autocomplete input -> open listbox -> input stay focused
  • open listbox -> select an item -> close listbox -> input stay focused
  • with selected item -> click clear button -> input stay focused and listbox is open
  • whenever it is focus -> click outside -> input stay blurred

the behaviours are consistent even the autocomplete is in the modal.

⛳️ Current behavior (updates)

Please describe the current behavior that you are modifying

🚀 New behavior

Please describe the behavior or changes this PR adds

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

📝 Additional Information

Summary by CodeRabbit

  • New Features

    • Added new focus management options to Autocomplete and Popover components.
    • Enhanced the Select component by simplifying popover rendering logic.
  • Bug Fixes

    • Improved Modal component by incorporating disableFocusManagement property to better control focus behavior.
    • Adjusted focus handling across various components for enhanced user interaction.
  • Refactor

    • Streamlined test cases for the Autocomplete component to cover new functionality scenarios.
    • Updated use-autocomplete logic for better focus management and interaction handling.
  • Tests

    • Expanded and refactored test suites for Autocomplete component to ensure robustness and reliability.

Copy link

linear bot commented Apr 24, 2024

Copy link

vercel bot commented Apr 24, 2024

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

Name Status Preview Comments Updated (UTC)
nextui-docs-v2 ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 12, 2024 6:55am
nextui-storybook-v2 ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 12, 2024 6:55am

Copy link

changeset-bot bot commented Apr 24, 2024

🦋 Changeset detected

Latest commit: 99d4e1e

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

This PR includes changesets to release 7 packages
Name Type
@nextui-org/autocomplete Patch
@nextui-org/modal Patch
@nextui-org/popover Patch
@nextui-org/select Patch
@nextui-org/react Patch
@nextui-org/date-picker Patch
@nextui-org/dropdown 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

Copy link
Contributor

coderabbitai bot commented Apr 24, 2024

Walkthrough

The changes made across various components aim to enhance focus management and interaction behaviors in UI components like Autocomplete and Modal. These adjustments include refining focus handling on interactions, updating popover content rendering logic, and introducing new props to provide more precise control over focus behavior.

Changes

Files Summary
packages/components/autocomplete/__tests__/autocomplete.test.tsx
packages/components/autocomplete/src/use-autocomplete.ts
Refactored test cases and updated state management in the Autocomplete component to improve focus and interaction handling.
packages/components/autocomplete/src/autocomplete.tsx
packages/components/popover/src/free-solo-popover.tsx
packages/components/popover/src/use-aria-popover.ts
Modified popover components to enhance focus management through new props and logic updates.
packages/components/modal/src/modal.tsx Updated the Modal component to handle focus management using the new disableFocusManagement prop.
packages/components/select/src/select.tsx Simplified popover rendering logic in the Select component by removing unnecessary props.

Assessment against linked issues

Objective Addressed Explanation
Ensure Autocomplete maintains focus when the modal opens and on re-opening with options [#2849]
Autocomplete should not reopen the listbox after clearing the value and selecting a new one [#2834]
Enable closing of the Autocomplete dropdown inside a modal [#2779]
Autocomplete should be focused on the initial click and manage focus correctly on outside click [#2962]

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

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>.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

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 as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

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.

Copy link
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: 0

Review Details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits Files that changed from the base of the PR and between 633f9d2 and 55ee11e.
Files selected for processing (8)
  • .changeset/good-crabs-clap.md (1 hunks)
  • packages/components/autocomplete/tests/autocomplete.test.tsx (4 hunks)
  • packages/components/autocomplete/src/autocomplete.tsx (2 hunks)
  • packages/components/autocomplete/src/use-autocomplete.ts (8 hunks)
  • packages/components/modal/src/modal.tsx (1 hunks)
  • packages/components/popover/src/free-solo-popover.tsx (3 hunks)
  • packages/components/popover/src/use-aria-popover.ts (1 hunks)
  • packages/components/select/src/select.tsx (1 hunks)
Files skipped from review due to trivial changes (2)
  • .changeset/good-crabs-clap.md
  • packages/components/popover/src/use-aria-popover.ts
Additional comments not posted (8)
packages/components/modal/src/modal.tsx (1)

21-21: Ensure that the disableFocusManagement prop is properly handled in all relevant contexts.

Verification successful

The disableFocusManagement prop is indeed used across various components in the codebase, including Popover, Modal, and within the useAutocomplete hook. This confirms that the prop is handled in multiple contexts, which aligns with the initial review comment's concern about ensuring proper handling in all relevant contexts.

  • In free-solo-popover.tsx, the prop is declared, given a default value, and passed to the Overlay component.
  • In modal.tsx, the prop is directly used in the Overlay component without passing a specific value, implying it defaults to true.
  • In use-autocomplete.ts, the prop is set to true explicitly.

This usage suggests that the prop's handling is consistent with its intended functionality across different components, although the default behavior and explicit settings vary slightly, which is typical given different component requirements.

Conclusion:
The disableFocusManagement prop is consistently used and handled across the codebase in components that integrate the Overlay component or similar functionalities. The review comment is verified as the code correctly implements the functionality as intended.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify that the `disableFocusManagement` prop is used consistently across the codebase.

# Test: Search for the usage of `disableFocusManagement` prop. Expect: Consistent usage across components.
rg --type typescript $'disableFocusManagement'

Length of output: 80



Script:

#!/bin/bash
# Corrected script to verify the usage of `disableFocusManagement` prop across TypeScript files.

# Search for the usage of `disableFocusManagement` prop in '.ts' and '.tsx' files.
rg 'disableFocusManagement' --glob '*.ts' --glob '*.tsx'

Length of output: 648

packages/components/autocomplete/src/autocomplete.tsx (1)

35-35: Ensure that the FreeSoloPopover component receives all necessary props after the removal of state.

Verification successful

The verification process has confirmed that the FreeSoloPopover component is used in the Autocomplete component without any reliance on a state prop directly passed to it. The component receives its properties through the getPopoverProps() function, which does not include state as a direct prop. This aligns with the changes mentioned in the review comment.

  • The usage of FreeSoloPopover in packages/components/autocomplete/src/autocomplete.tsx correctly receives properties through getPopoverProps() without any direct state prop.
Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify that the `FreeSoloPopover` component functions correctly without the `state` prop.

# Test: Search for the usage of `FreeSoloPopover` in the context of `Autocomplete`. Expect: No reliance on `state` prop.
rg --type typescript $'FreeSoloPopover' -A 10 -B 10

Length of output: 85



Script:

#!/bin/bash
# Description: Verify that the `FreeSoloPopover` component functions correctly without the `state` prop.

# Test: Search for the usage of `FreeSoloPopover` in the context of `Autocomplete`. Expect: No reliance on `state` prop.
rg --type ts 'FreeSoloPopover' -A 10 -B 10

Length of output: 24576

packages/components/popover/src/free-solo-popover.tsx (2)

26-26: Ensure that the disableFocusManagement prop is properly documented and its default value is justified.


133-133: Review the usage of disableFocusManagement in the Overlay component to ensure it aligns with the intended focus behavior.

Verification successful

The search results from the script have successfully located the usage of the Overlay component with the disableFocusManagement property in various parts of the codebase, including the specific instance in the free-solo-popover.tsx file. This confirms that the property is actively being used as intended across different components.

Given this information, the usage of disableFocusManagement in the Overlay component aligns with the intended focus behavior as it is consistently applied where needed. Therefore, the original review comment has been verified as accurate.

  • File: packages/components/popover/src/free-solo-popover.tsx
  • Usage: <Overlay disableFocusManagement={disableFocusManagement} portalContainer={portalContainer}>
Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify that the `Overlay` component's focus behavior aligns with the intended usage when `disableFocusManagement` is set.

# Test: Search for the usage of `Overlay` with `disableFocusManagement`. Expect: Correct behavior as intended.
rg --type typescript $'Overlay' -A 5 -B 5

Length of output: 75



Script:

#!/bin/bash
# Description: Verify that the `Overlay` component's focus behavior aligns with the intended usage when `disableFocusManagement` is set.

# Test: Search for the usage of `Overlay` with `disableFocusManagement`. Expect: Correct behavior as intended.
rg --type ts 'Overlay' -A 5 -B 5

Length of output: 45494

packages/components/select/src/select.tsx (1)

108-108: Ensure that the FreeSoloPopover component receives all necessary props after the changes in popover rendering logic.

Verification successful

The verification process has confirmed that the FreeSoloPopover component is being used correctly within the Select component. The component is receiving all necessary props as indicated by the usage of {...getPopoverProps()} in the Select component's rendering logic. This pattern is consistent across other components as well, suggesting a standardized approach to handling popover properties.

  • Location: packages/components/select/src/select.tsx
  • Usage: <FreeSoloPopover {...getPopoverProps()}>

This confirms that the integration of the FreeSoloPopover component within the Select component adheres to the expected implementation pattern, receiving all necessary properties to function correctly.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify that the `FreeSoloPopover` component functions correctly with the new popover rendering logic.

# Test: Search for the usage of `FreeSoloPopover` in the context of `Select`. Expect: Correct functioning with new logic.
rg --type typescript $'FreeSoloPopover' -A 10 -B 10

Length of output: 85



Script:

#!/bin/bash
# Correcting the file type and re-running the search for `FreeSoloPopover` usage in TypeScript files.
rg 'FreeSoloPopover' -A 10 -B 10 --type ts

Length of output: 24576

packages/components/autocomplete/__tests__/autocomplete.test.tsx (1)

140-167: Verify that the focus behavior tests align with the new focus management logic introduced in the Autocomplete component.

Verification successful

The search results from the script have provided relevant information regarding the focus management logic in the Autocomplete component. Specifically, the output from packages/components/autocomplete/src/use-autocomplete.ts indicates that the component explicitly disables the default focus management behavior (disableFocusManagement: true) and manages focus on its own.

This information is crucial because it confirms that the Autocomplete component has a custom focus management implementation. The test snippet provided in the review comment checks if the component is focused after interaction, which is consistent with the component managing its own focus as indicated by the disableFocusManagement: true setting.

Given this alignment between the test behavior and the component's focus management logic, the focus behavior tests are verified to be consistent with the new focus management logic introduced in the Autocomplete component.

  • The test checks if the component is focused after being clicked, which is a valid scenario to test given the custom focus management.
  • The component's logic to manage focus on its own side supports the necessity of such a test.

Therefore, the verification of the focus behavior tests with the new focus management logic in the Autocomplete component is successful.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify that the focus behavior tests are consistent with the new focus management logic.

# Test: Search for the focus management logic in the `Autocomplete` component. Expect: Consistency with tests.
rg --type typescript $'focus management' -A 10 -B 10

Length of output: 88



Script:

#!/bin/bash
# Corrected script to search for the focus management logic in the `Autocomplete` component.
# Using 'ts' as the recognized file type for TypeScript files in the ripgrep command.

rg --type ts 'focus management' -A 10 -B 10

Length of output: 3588

packages/components/autocomplete/src/use-autocomplete.ts (2)

202-202: Ensure that the introduction of shouldFocus state is well-integrated and does not conflict with existing focus management logic.

Verification successful

The search results from the rg command have provided us with the necessary context to assess the integration of the shouldFocus state within the useAutocomplete hook. The output shows several instances where shouldFocus is used in the use-autocomplete.ts file, particularly in relation to focus management logic.

From the provided snippets, it is evident that shouldFocus is used to conditionally focus or blur the input element based on its state and the state of isOpen. This is a common pattern in UI development where focus management needs to be explicitly handled to enhance user experience and accessibility. The use of shouldFocus in this manner does not appear to conflict with existing focus management logic but rather complements it by providing a controlled way to manage focus based on component state.

Given this analysis, the introduction of the shouldFocus state seems to be well-integrated and functioning as intended without conflicts with existing focus management logic.

  • The shouldFocus state is used to conditionally focus the input element based on its state and other conditions.
  • The logic surrounding shouldFocus includes checks and balances that ensure it does not interfere with other focus-related behaviors but enhances the component's interactivity and accessibility.

Based on the evidence from the code snippets provided by the script output, the integration of the shouldFocus state in the useAutocomplete hook is verified to be correct and functioning as intended.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify that the `shouldFocus` state is integrated correctly and does not conflict with existing logic.

# Test: Search for the usage of `shouldFocus` in the context of focus management. Expect: No conflicts.
rg --type typescript $'shouldFocus' -A 10 -B 10

Length of output: 81



Script:

#!/bin/bash
# Description: Verify that the `shouldFocus` state is integrated correctly and does not conflict with existing logic.

# Test: Search for the usage of `shouldFocus` in the context of focus management. Expect: No conflicts.
rg 'shouldFocus' -A 10 -B 10

Length of output: 23016


283-289: Review the new focus behavior on selector button click to ensure it aligns with the intended user experience.

@iqingting
Copy link

This is a relatively large interaction, can this pr be merged and release? Thanks @jrgarciadev

Copy link
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: 0

Review Details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits Files that changed from the base of the PR and between 55ee11e and 2272b71.
Files selected for processing (2)
  • packages/components/autocomplete/src/use-autocomplete.ts (8 hunks)
  • packages/components/popover/src/free-solo-popover.tsx (1 hunks)
Files skipped from review as they are similar to previous changes (2)
  • packages/components/autocomplete/src/use-autocomplete.ts
  • packages/components/popover/src/free-solo-popover.tsx

Copy link
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: 0

Review Details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits Files that changed from the base of the PR and between 2272b71 and 3bc9b6c.
Files selected for processing (1)
  • .changeset/good-crabs-clap.md (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • .changeset/good-crabs-clap.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants