You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat: ButtonDropdown async loading and manual filtering - #5105
Adds async loading and manual filtering to ButtonDropdown. These follow the same model Select and Multiselect already use.
Until now actions were required to be passed upfront synchronously. Changes in this PR enable Asynchronous Loading and Manual Filtering feature for Button Dropdown.
Async loading: the new onLoadItems event fires when the dropdown opens, when the user scrolls to the end, on Retry, and when a group is expanded. asyncLoadingProps sets the status (pending, loading, finished, error) and its texts.
Async groups: expandable groups can load their items when expanded. getExpandableItemsAsyncLoadingState reports each group's own status.
Manual filtering: with filteringType="manual", the component stops filtering on the client and passes the filter text to onLoadItems.
The status footer, live region and Retry are Select's existing shared code. useLoadItems is adapted from Select, with group loading added.
Unit tests cover the main list, groups on desktop and mobile, Retry and focus, keyboard behaviour and manual filtering. There are no new integration tests.
The feature was bug bashed, and an A11Y sanity check has been requested.
❌ Patch coverage is 99.50249% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 97.75%. Comparing base (623c7d3) to head (644a8f6).
- Render DropdownStatus directly (no DropdownFooter border) when
items are empty and status is sticky (loading/error state)
- Apply fix to both main dropdown (internal.tsx) and expandable
group sub-dropdown (expandable-category-element.tsx)
- Remove dead code: fireGroupLoadItems was exported but never called
- Add use-load-items.test.tsx covering handleLoadMore and
handleRecoveryClick branches
- Improve test coverage for DropdownStatus direct-render path
…recovery
- Share the expandable group status logic between the desktop fly-out and the
mobile inline group so both render loading, error, empty, and finished states
- Route group recovery through the root so focus returns to the filter input in
filtering mode; group events never carry the root filtering text
- Pass the real async status to the options list so a short first page loads
the next one, as in Select
- Treat a group status of pending as finished: groups load as a single page
- Test utils: expandedGroupDropdown also resolves inline mobile groups; drop the
duplicate stylesheet import
Reference getExpandableItemsAsyncLoadingState instead of a non-existent prop,
describe when onLoadItems fires, document that the text properties receive the
group id, and use items instead of options throughout.
Status, item presets, filtering type, delay, and expandToViewport are now
AppContext URL params so each state is linkable; fetched results stay local.
Descriptions now match the actual 5 s timeouts.
These IDs collide with menu-item IDs (${menuId}-${item.id}). For example, group g1 and a distinct action g1-recovery get the same DOM ID when Retry appears; g1-status similarly collides with the status. In filtering mode, aria-activedescendant can then resolve to the wrong element. Prefix the status and recovery IDs before menuId to separate them from item IDs.
Extract shared request and pagination logic into a hook
src/button-dropdown/utils/use-load-items.ts:17
The reuse-before-adding convention calls for one shared implementation. This duplicates Select's request tracking, pagination, and retry logic (src/select/utils/use-load-items.ts:16–43), with an additional missing-handler guard here. Extract the common root behavior into an internal hook and compose the group-specific events around it so loading fixes do not need separate implementations.
The reason will be displayed to describe this comment to others. Learn more.
There is technically a race condition here with fetchGroupItems. When a user opens and closes the group multiple times, it will create multiple promises, which all resolve independent form each other, populating the setGroupItems and Status. This way, the 5s delay is not really visible.
Though this might be fine for a test page. You can decide whether you want to fix this.
The reason will be displayed to describe this comment to others. Learn more.
nit: for a follow-up: Can't we remove options completely? It only checks whether it's an empty array. we could have a property "iconCount" or isEmpty instead.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds async loading and manual filtering to ButtonDropdown. These follow the same model Select and Multiselect already use.
Until now actions were required to be passed upfront synchronously. Changes in this PR enable Asynchronous Loading and Manual Filtering feature for Button Dropdown.
onLoadItemsevent fires when the dropdown opens, when the user scrolls to the end, on Retry, and when a group is expanded.asyncLoadingPropssets the status (pending,loading,finished,error) and its texts.getExpandableItemsAsyncLoadingStatereports each group's own status.filteringType="manual", the component stops filtering on the client and passes the filter text toonLoadItems.The status footer, live region and Retry are Select's existing shared code.
useLoadItemsis adapted from Select, with group loading added.API proposal: K9PFTzwiUlNH · Bug bash: KytjqOibVjRy · Release sign-off: 9XKd8i0qDr2l
Related links, issue #, if available: n/a
How has this been tested?
To review, open the dev pages:
scenariotoflat,groups,paginated,per-grouporerror.scenariotoclientorserver.Review checklist
The following items are to be evaluated by the author(s) and the reviewer(s).
Correctness
CONTRIBUTING.md.CONTRIBUTING.md.Security
checkSafeUrlfunction.Testing
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.