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(dropdown): respect closeOnSelect prop on DropdownItem #2598

Merged
merged 10 commits into from
Aug 16, 2024

Conversation

gtoxlili
Copy link
Contributor

@gtoxlili gtoxlili commented Mar 27, 2024

Closes #2290

📝 Description

This PR fixes an issue where the closeOnSelect prop on DropdownItem was being overridden by the DropdownMenu settings, causing the dropdown to close even when closeOnSelect was set to false on an individual DropdownItem.

⛳️ Current behavior (updates)

Currently, setting closeOnSelect to false on a DropdownItem does not prevent the dropdown from closing when that item is selected. This is because the onAction event handler on DropdownItem is deprecated and the closing behavior is controlled by the DropdownMenu settings.

🚀 New behavior

The logic has been updated to respect the closeOnSelect prop on DropdownItem. Now, if closeOnSelect is set to false on a DropdownItem, selecting that item will not close the dropdown menu.

The relevant changes are:

+ const onAction = (key: Key) => {
+   if (closeOnSelect) {
+     onTopAction?.(key);
+   }
+ };

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

No

📝 Additional Information

N/A

Summary by CodeRabbit

  • New Features
    • Introduced nuanced handling of the closeOnSelect property for dropdown items, allowing them to remain open or close based on user selection.
    • Added a new template to showcase dropdown behavior with the closeOnSelect property.
  • Bug Fixes
    • Addressed an issue related to the closeOnSelect prop in the dropdown component.
  • Tests
    • Added tests to verify the behavior of the closeOnSelect property in the DropdownItem component.

Copy link

changeset-bot bot commented Mar 27, 2024

🦋 Changeset detected

Latest commit: c33b918

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

This PR includes changesets to release 2 packages
Name Type
@nextui-org/dropdown Patch
@nextui-org/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

Copy link

vercel bot commented Mar 27, 2024

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

Name Status Preview Comments Updated (UTC)
nextui-storybook-v2 ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 16, 2024 9:02am

Copy link
Contributor

coderabbitai bot commented Mar 27, 2024

Walkthrough

The update enhances the dropdown menu's functionality by ensuring that when the closeOnSelect property is set to false, the menu remains open after item selection. This is achieved by modifying the event handling in the menu.tsx file and introducing improved logic within the useDropdown hook, thereby providing a more predictable user experience.

Changes

File Change Summary
packages/components/menu/src/menu.tsx - Added Key type import from React
- Renamed onAction to onTopAction
- Introduced new onAction function for key actions
packages/components/dropdown/src/use-dropdown.ts - Updated onAction logic to check closeOnSelect property for more nuanced behavior
packages/components/dropdown/__tests__/dropdown.test.tsx - Added test case for closeOnSelect functionality in DropdownItem
packages/components/dropdown/stories/dropdown.stories.tsx - Introduced ItemCloseOnSelectTemplate for demonstrating closeOnSelect functionality in the story
.changeset/warm-planets-smile.md - Added patch details for addressing the closeOnSelect issue in @nextui-org/dropdown package

Assessment against linked issues

Objective Addressed Explanation
Dropdown closes on item selection despite closeOnSelect being false (#2290)

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.
    • @coderabbitai help me debug CodeRabbit configuration file.

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 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 resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

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

CodeRabbit Configuration 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

vercel bot commented Mar 27, 2024

@gtoxlili is attempting to deploy a commit to the NextUI Inc Team on Vercel.

A member of the Team first needs to authorize it.

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.

Review Status

Actionable comments generated: 0

Configuration used: .coderabbit.yaml

Commits Files that changed from the base of the PR and between cf0d4e4 and 8e21dc2.
Files selected for processing (1)
  • packages/components/menu/src/menu.tsx (3 hunks)
Additional comments: 3
packages/components/menu/src/menu.tsx (3)
  • 2-2: The import statement has been updated to include the Key type from React, which is utilized in the newly added onAction function. This change is necessary for the implementation and ensures that the Key type is available for use within the file.
  • 21-21: The onAction function has been renamed to onTopAction. This renaming is part of the changes to ensure that the closeOnSelect property functions as expected. It's important to verify that all references to the old onAction function within this file and potentially in other parts of the codebase have been updated to reflect this change.
Verification successful

The search results indicate that references to onAction are still present throughout the project, not only within the menu component but also in other components like listbox, dropdown, breadcrumbs, and their respective stories, tests, and documentation. This suggests that the renaming of onAction to onTopAction was specific to the menu.tsx file and does not imply that all occurrences of onAction across the project should have been renamed. The presence of onAction in other components and contexts appears to be intentional and unrelated to the change made in menu.tsx.

Given this context, the review comment about verifying that all references to the old onAction function within this file and potentially in other parts of the codebase have been updated to reflect this change is partially correct. It is accurate in the sense that within menu.tsx, the renaming to onTopAction should be consistent. However, the comment may imply a broader scope of renaming across the project, which is not supported by the evidence from the search results. The references to onAction in other components and documentation are valid and expected to remain unchanged.

Therefore, the verification process concludes that the review comment is correct regarding the need to ensure consistency within the menu.tsx file but may be misleading if interpreted as applying to the entire codebase. The renaming to onTopAction seems to be a specific change within the menu component to address a particular issue, and the presence of onAction in other parts of the codebase does not contradict this change.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Search for any remaining references to the old `onAction` function name within the project.
rg --type tsx 'onAction' 

Length of output: 52



Script:

#!/bin/bash
# Search for any remaining references to the old `onAction` function name within the project, without specifying file type.
rg 'onAction'

Length of output: 7457

* 30-34: The addition of the new `onAction` function is a key part of the fix for the `closeOnSelect` issue. This function checks the `closeOnSelect` property's value and conditionally triggers `onTopAction` if `closeOnSelect` is true. This implementation allows individual `DropdownItem`s to override the default closing behavior of the dropdown menu. It's crucial to ensure that this new logic does not introduce any side effects, especially in scenarios where `closeOnSelect` might be dynamically changed or in complex dropdown structures.

Copy link
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 add a changeset
  2. please provide before & after videos to demonstrate if possible

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.

Review Status

Actionable comments generated: 1

Configuration used: .coderabbit.yaml

Commits Files that changed from the base of the PR and between 8e21dc2 and e65e9fa.
Files selected for processing (1)
  • .changeset/warm-planets-smile.md (1 hunks)

.changeset/warm-planets-smile.md Outdated Show resolved Hide resolved
@gtoxlili
Copy link
Contributor Author

  1. please add a changeset
  2. please provide before & after videos to demonstrate if possible

Thanks for the reminder, I've added the changeset.

@KoJem9Ka
Copy link

Really waiting for this fix in the release)

Copy link
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.

Just tested with the same code from the issue, the menu is still closed after clicking New file. Also please add tests to cover this case.

<Dropdown>
  <DropdownTrigger>
    <Button variant="bordered">Open Menu</Button>
  </DropdownTrigger>
  <DropdownMenu aria-label="Static Actions">
    <DropdownItem key="new" closeOnSelect={false}>
      New file
    </DropdownItem>
    <DropdownItem key="copy">Copy link</DropdownItem>
    <DropdownItem key="edit">Edit file</DropdownItem>
    <DropdownItem key="delete" className="text-danger" color="danger">
      Delete file
    </DropdownItem>
  </DropdownMenu>
</Dropdown>

@gtoxlili
Copy link
Contributor Author

Currently, if a DropdownItem has closeOnSelect explicitly set to false, the menu will remain open when that item is selected. Otherwise, it follows the DropdownMenu's closeOnSelect setting.

I have added the relevant templates. Please test the changes based on the provided templates.

@wingkwong

@wingkwong
Copy link
Member

@gtoxlili apart from storybook, I was asking for tests to be added in /packages/components/dropdown/__tests__/dropdown.test.tsx

@gtoxlili
Copy link
Contributor Author

@gtoxlili apart from storybook, I was asking for tests to be added in /packages/components/dropdown/__tests__/dropdown.test.tsx

Added

Copy link
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.

Tests are not passing. Please check.

@gtoxlili
Copy link
Contributor Author

gtoxlili commented May 8, 2024

The previous changes I proposed indeed had some issues. I have fixed them, uploaded the updated version, and conducted further testing. @wingkwong

@gtoxlili
Copy link
Contributor Author

gtoxlili commented May 8, 2024

The main reason for the issue is that the component's previous design coupled the onAction and closeOnSelect behaviors.

const getMenuProps = <T>(
  props?: Partial<MenuProps<T>>,
  _ref: Ref<any> | null | undefined = null,
) => {
  return {
    ref: mergeRefs(_ref, menuRef),
    menuProps,
    closeOnSelect,
    ...mergeProps(props, {
      onAction: () => onMenuAction(props?.closeOnSelect),
      onClose: state.close,
    }),
  } as MenuProps;
};

In the previous design, the user-provided onAction was merged with the close event based on DropdownMenu's closeOnSelect using mergeProps. The merged onAction was then passed to the item. When the event was triggered, the item directly executed the onAction method passed from the menu. (This is also the reason why the closeOnSelect of the item component was ineffective.)

My previous modification did not consider the possibility of the user passing their own onAction. So, I chose to directly skip executing the onAction passed from DropdownMenu if the item had closeOnSelect. (I assumed mergeProps was an override-like setting, but it turned out to execute all events with the same name in sequence.)

Now, I have changed the close event to:

onAction: (key: any) => {
  // @ts-ignore
  const item = props?.children?.find((item) => item.key === key);

  if (item?.props?.closeOnSelect === false) {
    onMenuAction(false);

    return;
  }
  onMenuAction(props?.closeOnSelect);
}

Since the item passes its key when triggering onAction, I try to find whether it has closeOnSelect based on the key. I think this logic should be correct now (although the logic is still messy, mainly because this coupled design is not a good design).

@wingkwong wingkwong self-assigned this May 8, 2024
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: 1

Review Details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits Files that changed from the base of the PR and between e65e9fa and 0b82163.
Files selected for processing (1)
  • .changeset/warm-planets-smile.md (1 hunks)

.changeset/warm-planets-smile.md Show resolved Hide resolved
@wingkwong wingkwong assigned jrgarciadev and unassigned wingkwong May 16, 2024
@wingkwong wingkwong added this to the v2.3.7 milestone May 16, 2024
@jrgarciadev
Copy link
Member

Hey @gtoxlili please fix the conflicts

@wingkwong wingkwong modified the milestones: v2.4.0, v2.4.1, v2.4.2 May 27, 2024
@jrgarciadev
Copy link
Member

@gtoxlili sorry for the delay, please fix the conflicts

@wingkwong wingkwong modified the milestones: v2.4.2, v2.5.0 Jun 15, 2024
@wingkwong wingkwong modified the milestones: v2.5.0, v2.4.7 Aug 16, 2024
@wingkwong wingkwong changed the title fix(dropdown): respect closeOnSelect prop on DropdownItem(#2290) fix(dropdown): respect closeOnSelect prop on DropdownItem Aug 16, 2024
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 0b82163 and c33b918.

Files selected for processing (3)
  • packages/components/dropdown/tests/dropdown.test.tsx (1 hunks)
  • packages/components/dropdown/src/use-dropdown.ts (1 hunks)
  • packages/components/dropdown/stories/dropdown.stories.tsx (2 hunks)
Additional comments not posted (4)
packages/components/dropdown/src/use-dropdown.ts (1)

155-165: Ensure props?.children is correctly typed.

The onAction function uses props?.children?.find to locate an item by key. Ensure that props?.children is correctly typed as an array of elements with a key property to avoid runtime errors.

packages/components/dropdown/stories/dropdown.stories.tsx (2)

156-189: Great addition for demonstrating closeOnSelect functionality.

The ItemCloseOnSelectTemplate effectively showcases the behavior of dropdown items and menus with the closeOnSelect property set to false. This is a valuable addition for testing and demonstrating the feature.


778-784: Ensure consistency in export naming.

The export ItemCloseOnSelect aligns with the naming convention used in other exports. Ensure that this naming is consistent across the codebase to maintain clarity and predictability.

Verification successful

Export Naming Consistency Verified

The export ItemCloseOnSelect follows a descriptive naming convention consistent with other exports in the codebase. No inconsistencies were found in the naming pattern.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify consistency in export naming for `ItemCloseOnSelect`.

# Test: Search for all exports in the stories file to ensure naming consistency.
rg --type tsx --no-heading --line-number --color never 'export const'

Length of output: 99


Script:

#!/bin/bash
# Locate the dropdown.stories.tsx file and search for all exports to ensure naming consistency.
fd --type f --extension tsx --exec rg --no-heading --line-number --color never 'export const' {}

Length of output: 35030

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

799-833: Excellent test coverage for closeOnSelect functionality.

The test case "should respect closeOnSelect setting of DropdownItem" effectively verifies the new behavior. It ensures that the dropdown remains open when closeOnSelect is set to false and closes otherwise. This is a critical addition to the test suite.

@wingkwong wingkwong merged commit 4f8ae50 into nextui-org:canary Aug 16, 2024
5 of 7 checks passed
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.

Dropdown Unexpectedly Closes on Item Selection Despite closeOnSelect Being Set to False
4 participants