GitGlimpse / processed_docs /pr_data_0_doc_12.txt
NathanAW24
add for streamlit_cot
fd27bb4
Pull Request Number: 4274
Title: fix: prevent multiple parent focus events on click
Base Branch: canary
Head Branch: fix/selection-components-parent-focus
Author: Peterl561
URL: https://github.com/nextui-org/nextui/pull/4274
State: OPEN
Created At: 2024-12-08T03:19:11Z
Merged At: None
Participants: Peterl561, macci001, wingkwong
Description:
Closes #4260
πŸ“ Description
caused by #4220
affects Checkbox, Radio, and Switch components
occurs when parent container is focusable (see sandbox)
need to call preventDefault to prevent parent focus from firing multiple times
⛳️ Current behavior (updates)
before.mp4
πŸš€ New behavior
after.mp4
πŸ’£ Is this a breaking change (Yes/No):
No
πŸ“ Additional Information
Summary by CodeRabbit
New Features
Improved focus behavior for checkbox, radio, and switch components to enhance user experience by preventing unnecessary focus events.
Bug Fixes
Resolved an issue where focus was incorrectly triggered multiple times on parent elements when interacting with checkbox, radio, and switch components.
Tests
Added new test cases to verify correct focus behavior for checkbox, radio, and switch components upon interaction.
Commits:
- test(checkbox): focusable parent test\n- test(radio): focusable parent test\n- test(switch): focusable parent test\n- fix(checkbox): prevent parent focus on click\n- fix(radio): prevent parent focus on click\n- fix(switch): prevent parent focus on click\n- chore(changeset): fixed slection components parent focus\n- chore(changeset): add issue number\n
Labels:
Comments:
- changeset-bot: ### πŸ¦‹ Changeset detected
Latest commit: 476761c8021a9c274e58b6ea0bbebe681f85ff45
**The changes in this PR will be included in the next version bump.**
<details><summary>This PR includes changesets to release 5 packages</summary>
| Name | Type |
| -------------------- | ----- |
| @nextui-org/checkbox | Patch |
| @nextui-org/switch | Patch |
| @nextui-org/radio | Patch |
| @nextui-org/table | Patch |
| @nextui-org/react | Patch |
</details>
Not sure what this means? [Click here to learn what changesets are](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md).
[Click here if you're a maintainer who wants to add another changeset to this PR](https://github.com/Peterl561/nextui/new/fix/selection-components-parent-focus?filename=.changeset/perfect-countries-approve.md&value=---%0A%22%40nextui-org%2Fcheckbox%22%3A%20patch%0A%22%40nextui-org%2Fradio%22%3A%20patch%0A%22%40nextui-org%2Fswitch%22%3A%20patch%0A---%0A%0Afix%3A%20prevent%20multiple%20parent%20focus%20events%20on%20click%0A)
\n- vercel: [vc]: #7uMUrbW9/bIiML1u8NE0ldx/viwzsB/5/Vi8qQyic2U=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJuZXh0dWktc3Rvcnlib29rLXYyIiwicm9vdERpcmVjdG9yeSI6InBhY2thZ2VzL3N0b3J5Ym9vayIsImluc3BlY3RvclVybCI6Imh0dHBzOi8vdmVyY2VsLmNvbS9uZXh0dWktb3JnL25leHR1aS1zdG9yeWJvb2stdjIvRTlMazdVcFB2dFhiTldMOWQzNzFiZlNGaEthciIsInByZXZpZXdVcmwiOiJuZXh0dWktc3Rvcnlib29rLXYyLWdpdC1mb3JrLXBldGVybDU2MS1maXgtc2UtMjE0NWFjLW5leHR1aS1vcmcudmVyY2VsLmFwcCIsIm5leHRDb21taXRTdGF0dXMiOiJERVBMT1lFRCIsImxpdmVGZWVkYmFjayI6eyJyZXNvbHZlZCI6MCwidW5yZXNvbHZlZCI6MCwidG90YWwiOjAsImxpbmsiOiJuZXh0dWktc3Rvcnlib29rLXYyLWdpdC1mb3JrLXBldGVybDU2MS1maXgtc2UtMjE0NWFjLW5leHR1aS1vcmcudmVyY2VsLmFwcCJ9fSx7Im5hbWUiOiJuZXh0dWktZG9jcy12MiIsInJvb3REaXJlY3RvcnkiOiJhcHBzL2RvY3MiLCJpbnNwZWN0b3JVcmwiOiJodHRwczovL3ZlcmNlbC5jb20vbmV4dHVpLW9yZy9uZXh0dWktZG9jcy12Mi9CemRvOWpZU3k4UW5acjhwaDJBd1d3a1RhQll1IiwicHJldmlld1VybCI6Im5leHR1aS1kb2NzLXYyLWdpdC1mb3JrLXBldGVybDU2MS1maXgtc2VsZWN0aS00MzFlZDUtbmV4dHVpLW9yZy52ZXJjZWwuYXBwIiwibmV4dENvbW1pdFN0YXR1cyI6IkRFUExPWUVEIiwibGl2ZUZlZWRiYWNrIjp7InJlc29sdmVkIjowLCJ1bnJlc29sdmVkIjowLCJ0b3RhbCI6MCwibGluayI6Im5leHR1aS1kb2NzLXYyLWdpdC1mb3JrLXBldGVybDU2MS1maXgtc2VsZWN0aS00MzFlZDUtbmV4dHVpLW9yZy52ZXJjZWwuYXBwIn19XX0=
**The latest updates on your projects**. Learn more about [Vercel for Git β†—οΈŽ](https://vercel.link/github-learn-more)
| Name | Status | Preview | Comments | Updated (UTC) |
| :--- | :----- | :------ | :------- | :------ |
| **nextui-docs-v2** | βœ… Ready ([Inspect](https://vercel.com/nextui-org/nextui-docs-v2/Bzdo9jYSy8QnZr8ph2AwWwkTaBYu)) | [Visit Preview](https://nextui-docs-v2-git-fork-peterl561-fix-selecti-431ed5-nextui-org.vercel.app) | πŸ’¬ [**Add feedback**](https://vercel.live/open-feedback/nextui-docs-v2-git-fork-peterl561-fix-selecti-431ed5-nextui-org.vercel.app?via=pr-comment-feedback-link) | Dec 9, 2024 6:01am |
| **nextui-storybook-v2** | βœ… Ready ([Inspect](https://vercel.com/nextui-org/nextui-storybook-v2/E9Lk7UpPvtXbNWL9d371bfSFhKar)) | [Visit Preview](https://nextui-storybook-v2-git-fork-peterl561-fix-se-2145ac-nextui-org.vercel.app) | πŸ’¬ [**Add feedback**](https://vercel.live/open-feedback/nextui-storybook-v2-git-fork-peterl561-fix-se-2145ac-nextui-org.vercel.app?via=pr-comment-feedback-link) | Dec 9, 2024 6:01am |
\n- vercel: @Peterl561 is attempting to deploy a commit to the **NextUI Inc** Team on [Vercel](https://vercel.com).
A member of the Team first needs to [authorize it](https://vercel.com/git/authorize?team=NextUI%20Inc&type=github&job=%7B%22headInfo%22%3A%7B%22sha%22%3A%2220d8d906ff20959e4a179e467abbd54a7a495ca7%22%7D%2C%22id%22%3A%22QmXV5BXNrb2f2w6dVMdkms6ZqGmNihCXkiVwK9hmK4ETfJ%22%2C%22org%22%3A%22nextui-org%22%2C%22prId%22%3A4274%2C%22repo%22%3A%22nextui%22%7D).
\n- coderabbitai: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- This is an auto-generated comment: rate limited by coderabbit.ai -->
> [!WARNING]
> ## Rate limit exceeded
>
> @wingkwong has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait **25 minutes and 22 seconds** before requesting another review.
>
> <details>
> <summary>βŒ› How to resolve this issue?</summary>
>
> After the wait time has elapsed, a review can be triggered using the `@coderabbitai review` command as a PR comment. Alternatively, push new commits to this PR.
>
> We recommend that you space out your commits to avoid hitting the rate limit.
>
> </details>
>
>
> <details>
> <summary>🚦 How do rate limits work?</summary>
>
> CodeRabbit enforces hourly rate limits for each developer per organization.
>
> Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.
>
> Please see our [FAQ](https://docs.coderabbit.ai/faq) for further information.
>
> </details>
>
> <details>
> <summary>πŸ“₯ Commits</summary>
>
> Reviewing files that changed from the base of the PR and between 20d8d906ff20959e4a179e467abbd54a7a495ca7 and 476761c8021a9c274e58b6ea0bbebe681f85ff45.
>
> </details>
>
> <details>
> <summary>πŸ“’ Files selected for processing (1)</summary>
>
> * `.changeset/tricky-panthers-build.md` (1 hunks)
>
> </details>
<!-- end of auto-generated comment: rate limited by coderabbit.ai -->
<!-- walkthrough_start -->
## Walkthrough
This update introduces a patch for the `@nextui-org/checkbox`, `@nextui-org/switch`, and `@nextui-org/radio` components to address an issue where these components were incorrectly triggering focus on their parent elements multiple times. The changes include the addition of `mouseProps` to manage mouse events more effectively, ensuring that focus behavior is corrected. New test cases have also been added to verify that focus is triggered only once on the parent element when the components are clicked.
## Changes
| File | Change Summary |
|------|----------------|
| `.changeset/tricky-panthers-build.md` | Patch applied for `@nextui-org/checkbox`, `@nextui-org/switch`, and `@nextui-org/radio` components. |
| `packages/components/checkbox/__tests__/checkbox.test.tsx` | Added test to verify focus on parent element is triggered once after Checkbox click. |
| `packages/components/checkbox/src/use-checkbox.ts` | Introduced `mouseProps` with `onMouseDown` to prevent parent focus on Checkbox click. |
| `packages/components/radio/__tests__/radio.test.tsx` | Added test to verify focus on parent element is triggered once after Radio click. |
| `packages/components/radio/src/use-radio.ts` | Introduced `mouseProps` with `onMouseDown` to prevent parent focus on Radio click. |
| `packages/components/switch/__tests__/switch.test.tsx` | Added test to verify focus on parent element is triggered once after Switch click. |
| `packages/components/switch/src/use-switch.ts` | Introduced `mouseProps` with `onMouseDown` to prevent parent focus on Switch click. |
## Assessment against linked issues
| Objective | Addressed | Explanation |
|-----------|-----------|-------------|
| Fix focus issue on Switch inside CardBody (#4260) | βœ… | |
| Ensure focus is triggered once on Checkbox, Switch, and Radio clicks | βœ… | |
## Possibly related PRs
- **#2854**: Addresses focus behavior in popovers, related to focus management in checkbox, switch, and radio components.
- **#3000**: Improves focus management in the autocomplete component, relevant to focus behavior changes in the checkbox, switch, and radio components.
- **#3552**: Resolves a double-click issue in checkbox, switch, and radio components, directly related to focus behavior changes in the main PR.
## Suggested labels
`πŸ‘€ Status: In Review`
## Suggested reviewers
- wingkwong
- jrgarciadev
<!-- walkthrough_end -->
<!-- internal state start -->
<!-- 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 -->
<!-- internal state end -->
<!-- tips_start -->
---
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?
<details>
<summary>❀️ Share</summary>
- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)
</details>
<details>
<summary>πŸͺ§ Tips</summary>
### Chat
There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai):
- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
- `I pushed a fix in commit <commit_id>, please review it.`
- `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 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 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 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 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](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.
</details>
<!-- tips_end -->\n- macci001: Hey @Peterl561, thanks a lot for fixing the issue.
The PR looks good to me.\n
Files Changed:
- .changeset/tricky-panthers-build.md (added, 7 changes)\n Patch: @@ -0,0 +1,7 @@
+---
+"@nextui-org/checkbox": patch
+"@nextui-org/switch": patch
+"@nextui-org/radio": patch
+---
+
+fixed checkbox, radio, and switch triggering focus on focusable parent multiple times (#4260)\n- packages/components/checkbox/__tests__/checkbox.test.tsx (modified, 16 changes)\n Patch: @@ -90,6 +90,22 @@ describe("Checkbox", () => {
expect(onFocus).toHaveBeenCalled();
});
+ it("should trigger focus on focusable parent once after click", async () => {
+ const onFocus = jest.fn();
+
+ const wrapper = render(
+ <div tabIndex={-1} onFocus={onFocus}>
+ <Checkbox data-testid="checkbox-test">Checkbox</Checkbox>
+ </div>,
+ );
+
+ const label = wrapper.getByTestId("checkbox-test");
+
+ await user.click(label);
+
+ expect(onFocus).toHaveBeenCalledTimes(1);
+ });
+
it("should have required attribute when isRequired with native validationBehavior", () => {
const {container} = render(
<Checkbox isRequired validationBehavior="native">\n- packages/components/checkbox/src/use-checkbox.ts (modified, 12 changes)\n Patch: @@ -264,6 +264,16 @@ export function useCheckbox(props: UseCheckboxProps = {}) {
const baseStyles = clsx(classNames?.base, className);
+ const mouseProps = useMemo(
+ () => ({
+ onMouseDown: (e: React.MouseEvent<HTMLLabelElement>) => {
+ // prevent parent from being focused
+ e.preventDefault();
+ },
+ }),
+ [],
+ );
+
const getBaseProps: PropGetter = useCallback(() => {
return {
ref: domRef,
@@ -277,7 +287,7 @@ export function useCheckbox(props: UseCheckboxProps = {}) {
"data-readonly": dataAttr(inputProps.readOnly),
"data-focus-visible": dataAttr(isFocusVisible),
"data-indeterminate": dataAttr(isIndeterminate),
- ...mergeProps(hoverProps, otherProps),
+ ...mergeProps(hoverProps, mouseProps, otherProps),
};
}, [
slots,\n- packages/components/radio/__tests__/radio.test.tsx (modified, 20 changes)\n Patch: @@ -142,6 +142,26 @@ describe("Radio", () => {
expect(onFocus).toHaveBeenCalled();
});
+ it("should trigger focus on focusable parent once after click", async () => {
+ const onFocus = jest.fn();
+
+ const wrapper = render(
+ <div tabIndex={-1} onFocus={onFocus}>
+ <RadioGroup defaultValue="1" label="Options">
+ <Radio data-testid="radio-test-1" value="1">
+ Option 1
+ </Radio>
+ </RadioGroup>
+ </div>,
+ );
+
+ const label = wrapper.getByTestId("radio-test-1");
+
+ await user.click(label);
+
+ expect(onFocus).toHaveBeenCalledTimes(1);
+ });
+
it("should have required attribute when isRequired with native validationBehavior", () => {
const {getByRole, getAllByRole} = render(
<RadioGroup isRequired label="Options" validationBehavior="native">\n- packages/components/radio/src/use-radio.ts (modified, 12 changes)\n Patch: @@ -150,6 +150,16 @@ export function useRadio(props: UseRadioProps) {
const baseStyles = clsx(classNames?.base, className);
+ const mouseProps = useMemo(
+ () => ({
+ onMouseDown: (e: React.MouseEvent<HTMLLabelElement>) => {
+ // prevent parent from being focused
+ e.preventDefault();
+ },
+ }),
+ [],
+ );
+
const getBaseProps: PropGetter = useCallback(
(props = {}) => {
return {
@@ -166,7 +176,7 @@ export function useRadio(props: UseRadioProps) {
"data-hover-unselected": dataAttr(isHovered && !isSelected),
"data-readonly": dataAttr(inputProps.readOnly),
"aria-required": dataAttr(isRequired),
- ...mergeProps(hoverProps, otherProps),
+ ...mergeProps(hoverProps, mouseProps, otherProps),
};
},
[\n- packages/components/switch/__tests__/switch.test.tsx (modified, 16 changes)\n Patch: @@ -184,6 +184,22 @@ describe("Switch", () => {
expect(wrapper.getByTestId("start-icon")).toBeInTheDocument();
expect(wrapper.getByTestId("end-icon")).toBeInTheDocument();
});
+
+ it("should trigger focus on focusable parent once after click", async () => {
+ const onFocus = jest.fn();
+
+ const wrapper = render(
+ <div tabIndex={-1} onFocus={onFocus}>
+ <Switch data-testid="switch-test">Switch</Switch>
+ </div>,
+ );
+
+ const label = wrapper.getByTestId("switch-test");
+
+ await user.click(label);
+
+ expect(onFocus).toHaveBeenCalledTimes(1);
+ });
});
describe("Switch with React Hook Form", () => {\n- packages/components/switch/src/use-switch.ts (modified, 12 changes)\n Patch: @@ -178,9 +178,19 @@ export function useSwitch(originalProps: UseSwitchProps = {}) {
const baseStyles = clsx(classNames?.base, className);
+ const mouseProps = useMemo(
+ () => ({
+ onMouseDown: (e: React.MouseEvent<HTMLLabelElement>) => {
+ // prevent parent from being focused
+ e.preventDefault();
+ },
+ }),
+ [],
+ );
+
const getBaseProps: PropGetter = (props) => {
return {
- ...mergeProps(hoverProps, otherProps, props),
+ ...mergeProps(hoverProps, mouseProps, otherProps, props),
ref: domRef,
className: slots.base({class: clsx(baseStyles, props?.className)}),
"data-disabled": dataAttr(isDisabled),\n