Skip to content

Conversation

@Mash707
Copy link
Contributor

@Mash707 Mash707 commented Apr 10, 2025

Closes #10197
References:

Summary by CodeRabbit

  • Documentation

    • Added a new section describing split-toggle patterns that combine a control with a dropdown, including guidance on focus restoration after item selection and an example usage.
  • New Features

    • Added an example component demonstrating a dropdown with a split-button toggle and an integrated checkbox, showing open/close behavior, disabled/aria-disabled items, separators, and manual focus handling after selection.

✏️ Tip: You can customize this high-level summary in your review settings.

@Mash707
Copy link
Contributor Author

Mash707 commented Apr 10, 2025

@kmcfaul @thatblindgeye I have created a draft for the example. Let me know of the changes required.
Also could you guys also suggest the description and sub heading for the example, I am not sure of it. Thank You

@patternfly-build
Copy link
Collaborator

patternfly-build commented Apr 10, 2025

@Mash707
Copy link
Contributor Author

Mash707 commented Apr 10, 2025

There were some a11y issues regarding MenuToggle and MenuToggleCheckbox since I didn't add aria-label to them.
@thatblindgeye do check the aria-labels once, I have added them for now so that the tests don't fail.

Copy link
Contributor

@nicolethoen nicolethoen left a comment

Choose a reason for hiding this comment

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

Event handling is not quite ideal in this example.

In other dropdown examples, if I open the menu using the keyboard, i can hit tab and it will close the menu and put focus on the next focusable element on the page (in the docs, that's usually the button)

In the other dropdown examples, I can also click outside the menu and it will close the menu.

I think it's because this new example might be missing the 'onOpenChange' prop.

@Mash707 Mash707 force-pushed the dropdown-add-split-action-example branch from 6073673 to 6adca58 Compare April 23, 2025 19:57
@Mash707
Copy link
Contributor Author

Mash707 commented Apr 23, 2025

Yes, it was happening due to the missing onOpenChange prop. I have added it and now the menu is closing when clicking outside.

@Mash707 Mash707 requested a review from nicolethoen April 23, 2025 19:59
Copy link
Contributor

@nicolethoen nicolethoen left a comment

Choose a reason for hiding this comment

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

I'm noticing that if I select an option from the menu (with they keyboard or my mouse) browser focus is not returned to the MenuToggle as it does in other examples.

I think you're also missing the shouldFocusToggleOnSelect prop

@Mash707
Copy link
Contributor Author

Mash707 commented Apr 28, 2025

When adding the shouldFocusToggleOnSelect , it does not seem to work with splitButtonItems prop of the menu toggle. If I remove the splitButtonItems prop then it is working fine.
I also added splitButtonItems to others examples to test things out and it breaks them too.

@thatblindgeye
Copy link
Contributor

thatblindgeye commented Apr 28, 2025

Looks like it's because we're applying the innerref inside MenuToggle to that wrapper div instead of the toggle button:

if (splitButtonItems) {
return (
<div ref={innerRef as React.Ref<HTMLDivElement>} className={css(commonStyles, styles.modifiers.splitButton)}>

Since it's a plain div without any tabindex focus gets lost when trying to focus it, and we end up back at the top of the page when you Tab again. This PR is what added the ref to that div #8024 . @kmcfaul do you recall if we need to have the ref on this wrapper div? Moving it to the button toggle for the splitButtonItems return seems more accurate in this case, but can't remember if there was a specific reason.

An alternative would be possibly having to supply some custom focus logic in the example code, which consumers would then have to also implement.

@kmcfaul
Copy link
Contributor

kmcfaul commented May 14, 2025

Yeah I think this may have been added to the wrong place, it seems like having it on the button would make more sense. I'm a little concerned whether this would count as a breaking change if people are referencing the split actions through the ref, but I think this is more of a bug fix. If we didn't want to change the ref location, we maybe could have the component change how it handles focus if splitActionItems is present and send focus back to the toggle button (like via querySelector getting the last button or have another ref applied to the toggle button).

@kmcfaul
Copy link
Contributor

kmcfaul commented May 20, 2025

After discussing with the team, we should keep the ref on the div as is, and update Dropdown's logic to handle sending focus back to the toggle button via a querySelector (see the filter demos) for its default behavior.

@Mash707 Mash707 force-pushed the dropdown-add-split-action-example branch from 6adca58 to 4834e6d Compare May 29, 2025 15:28
@github-actions
Copy link

This PR has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@github-actions
Copy link

This PR has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@github-actions github-actions bot added the Stale label Oct 10, 2025
@nicolethoen nicolethoen removed the Stale label Dec 11, 2025
Copy link
Contributor

@thatblindgeye thatblindgeye left a comment

Choose a reason for hiding this comment

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

From what I recall this is looking good, just couple things below


### Split button

Description of split button
Copy link
Contributor

Choose a reason for hiding this comment

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

@edonehoo would you mind taking a stab at quick verbiage here? Would be worth mentioning that the focus must be handled manually when shifting focus back to the toggle element after selecting an item (if the dropdown menu closes upon selection)

Comment on lines 17 to 22
if (toggleRef.current) {
const toggleButton = toggleRef.current.querySelector('button[aria-expanded]');
if (toggleButton) {
(toggleButton as HTMLElement).focus();
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: we could remove a layer of nesting here by early returning is !toggleRef.current, or having toggleButton = toggleRef?.current?...

@Mash707 Mash707 force-pushed the dropdown-add-split-action-example branch from c4000d4 to 2d737dc Compare December 11, 2025 18:01

```

### Split button
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
### Split button
### Split toggle with checkbox

to align with the language used in the menu toggle docs


### Split button

Description of split button
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Description of split button
To combine a checkbox or other control with a dropdown menu, use a split button.
A `<MenuToggle>` can be rendered as a split button via `splitButtonItems`. Elements to be displayed before the dropdown toggle button (like the `<MenuToggleCheckbox>`) must be included in the `splitButtonItems`.
If the dropdown menu closes upon selection, you will need to manually shift focus back to the toggle element after a user selects an item from the menu.

wdyt about this?

Copy link
Contributor

Choose a reason for hiding this comment

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

🚢 it

@Mash707 if this looks good to you can you make this quick update?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done 🚀🚀.

@coderabbitai
Copy link

coderabbitai bot commented Dec 11, 2025

Walkthrough

Adds a new split-button Dropdown example and corresponding docs: a React component DropdownSplitButtonText demonstrating a dropdown with a split toggle that includes a checkbox control, plus documentation describing usage and manual focus restoration after selection.

Changes

Cohort / File(s) Summary
Documentation
packages/react-core/src/components/Dropdown/examples/Dropdown.md
Imported useRef, added "Split toggle with checkbox" section describing combining a control with a dropdown via splitButtonItems, and referenced the DropdownWithSplit.tsx example.
New Component Implementation
packages/react-core/src/components/Dropdown/examples/DropdownWithSplit.tsx
Added DropdownSplitButtonText export: a split-button dropdown example that manages isOpen, holds a menu toggle ref, restores focus to the toggle after selection, and includes a mix of action/link/disabled items (with a tooltip on aria-disabled item).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

  • Review focus restoration logic and the MenuToggleElement ref usage.
  • Confirm splitButtonItems configuration and Dropdown API usage.
  • Ensure the aria-disabled + tooltip pattern is implemented accessibly.

Poem

🐰 I hopped in with a split-button cheer,
A checkbox tucked close, the menu near.
When items are chosen, I nudge focus back,
A tidy little hop along the UI track. 🥕

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding a split button action example to the Dropdown component documentation.
Linked Issues check ✅ Passed The PR successfully ports the split button action Dropdown example from deprecated docs to new docs, fulfilling issue #10197 requirements.
Out of Scope Changes check ✅ Passed All changes are scoped to adding the split button example documentation and component. The modifications to Dropdown.md and creation of DropdownWithSplit.tsx are directly aligned with the stated objective.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aa7712c and 0d8177e.

📒 Files selected for processing (2)
  • packages/react-core/src/components/Dropdown/examples/Dropdown.md (2 hunks)
  • packages/react-core/src/components/Dropdown/examples/DropdownWithSplit.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/react-core/src/components/Dropdown/examples/DropdownWithSplit.tsx
  • packages/react-core/src/components/Dropdown/examples/Dropdown.md
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build
  • GitHub Check: Build, test & deploy

Comment @coderabbitai help to get the list of available commands and usage tips.

### Split toggle with checkbox

To combine a checkbox or other control with a dropdown menu, use a split button.

Copy link
Contributor

@edonehoo edonehoo Dec 15, 2025

Choose a reason for hiding this comment

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

Suggested change
A `<MenuToggle>` can be rendered as a split button via `splitButtonItems`. Elements to be displayed before the dropdown toggle button (like the `<MenuToggleCheckbox>`) must be included in the `splitButtonItems`.
If the dropdown menu closes upon selection, you will need to manually shift focus back to the toggle element after a user selects an item from the menu.

can you add these 2 lines too?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My bad. I totally missed it in the previous comment. Have added it now 🚀.

Copy link

@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 UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8928745 and aa7712c.

📒 Files selected for processing (2)
  • packages/react-core/src/components/Dropdown/examples/Dropdown.md (1 hunks)
  • packages/react-core/src/components/Dropdown/examples/DropdownWithSplit.tsx (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build, test & deploy
  • GitHub Check: Build
🔇 Additional comments (3)
packages/react-core/src/components/Dropdown/examples/Dropdown.md (1)

67-77: LGTM! Documentation clearly explains the pattern.

The documentation appropriately describes the split button pattern and the manual focus restoration requirement. The verbiage aligns with the team's consensus from the PR discussion.

packages/react-core/src/components/Dropdown/examples/DropdownWithSplit.tsx (2)

16-28: Focus restoration pattern correctly implements the team's consensus approach.

The onFocus function uses querySelector to find and focus the toggle button, which aligns with the team's decision documented in the PR objectives. This addresses the known issue where shouldFocusToggleOnSelect doesn't work with splitButtonItems.

The early return on line 17-19 addresses the previous review feedback to avoid nesting.


34-96: Well-structured example demonstrating split button pattern.

The component correctly implements:

  • Dual ref handling (lines 40-48) to support both the Dropdown's callback ref and the local useRef needed for focus restoration
  • Required accessibility labels on MenuToggle (line 52) and MenuToggleCheckbox (line 50) that satisfied the a11y tests per the PR comments
  • The onOpenChange handler (line 37) to sync external state changes, which was identified as missing in early PR feedback
  • A variety of dropdown item states (action, link, disabled, aria-disabled with tooltip, separated items) that provide a comprehensive example

Copy link
Contributor

@edonehoo edonehoo left a comment

Choose a reason for hiding this comment

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

looks good!

@thatblindgeye thatblindgeye merged commit 8c91c15 into patternfly:main Dec 17, 2025
14 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 - split button action example

6 participants