Repository navigation
feat: ButtonDropdown async loading and manual filtering - #5105
Open
NathanZlion wants to merge 17 commits into
Open
NathanZlion wants to merge 17 commits into
NathanZlion wants to merge 17 commits into
Conversation
- 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
…n-dropdown-async-filtering # Conflicts: # src/button-dropdown/utils/use-button-dropdown.ts
…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.
…t utils The root and group status footers now carry distinct markers, so findErrorRecoveryButton, findStatusIndicator, and findFooterRegion never return an expanded group's status when the root status was requested, and vice versa. Also documents noMatch for manual filtering and when the open event is deduplicated.
…n-dropdown-async-filtering
Narrow getExpandableItemsAsyncLoadingState to item groups, move test-utils-only classes to test-classes/styles.scss, and reduce the async-loading and manual-filtering dev pages to a single component selected through a scenario URL param.
Clarify behavior when status is null or undefined in documentation. Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
- Render mobile group loading, error and empty status outside the group's role="menu" so the Retry link is not inside the menu. The menu still references the status with aria-describedby. - Document that expandable groups need an id for async loading and warn when a group without an id is expanded. - Keep the dropdown open when Enter or Space is pressed while an expanded group's items are still loading.
The root list showed the `empty` content whenever it had no items, including while `statusType` was `pending`. The API documents `empty` as shown only when the status is `finished` or not set, so gate it on the normalized status.
NathanZlion
requested review from
a team
and removed request for
a team and
avinashbot
October 5, 2026 14:00
…n-dropdown-async-filtering
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #5105 +/- ##
==========================================
+ Coverage 97.70% 97.72% +0.01%
==========================================
Files 989 992 +3
Lines 31806 31943 +137
Branches 11748 11837 +89
==========================================
+ Hits 31077 31215 +138
+ Misses 722 682 -40
- Partials 7 46 +39 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
NathanZlion
marked this pull request as ready for review
October 5, 2026 14:57
Contributor
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Finished-status rows create invalid ARIA menu ownership on desktop and mobile.
Review effort: Balanced
Findings: 3
Open (3)
What changed in this PR
Adds asynchronous loading, expandable-group loading, and manual filtering to ButtonDropdown.
Changes:
- Adds loading APIs, status footers, retry behavior, and i18n.
- Supports manually filtered items and async expandable groups.
- Adds unit tests, test utilities, snapshots, and demo pages.
| File | Description |
|---|---|
src/test-utils/dom/button-dropdown/index.ts |
Adds scoped status and recovery selectors. |
src/i18n/messages/all.en.json |
Adds default retry and error labels. |
src/i18n/messages-types.ts |
Types the new translations. |
src/button-dropdown/utils/use-load-items.ts |
Implements loading-event behavior. |
src/button-dropdown/utils/use-highlighted-menu.ts |
Tracks pending group highlights. |
src/button-dropdown/utils/use-button-dropdown.ts |
Integrates filtering, loading, retry, and group expansion. |
src/button-dropdown/test-classes/styles.scss |
Adds test-only status markers. |
src/button-dropdown/status-footer.tsx |
Wraps shared status-footer interactions. |
src/button-dropdown/items-list.tsx |
Passes async state into groups. |
src/button-dropdown/internal.tsx |
Integrates the feature into rendering and behavior. |
src/button-dropdown/internal-interfaces.ts |
Extends internal async-loading props. |
src/button-dropdown/interfaces.ts |
Defines the new public API. |
src/button-dropdown/index.tsx |
Forwards the public props. |
src/button-dropdown/category-elements/use-expandable-group-status.ts |
Derives per-group status UI. |
src/button-dropdown/category-elements/mobile-expandable-category-element.tsx |
Renders mobile group statuses. |
src/button-dropdown/category-elements/expandable-category-element.tsx |
Renders desktop group statuses. |
src/button-dropdown/__tests__/use-load-items.test.tsx |
Tests loading-event semantics. |
src/button-dropdown/__tests__/button-dropdown-async-loading.test.tsx |
Tests desktop async behavior. |
src/button-dropdown/__tests__/button-dropdown-async-loading-mobile.test.tsx |
Tests mobile async groups. |
src/__tests__/snapshot-tests/__snapshots__/test-utils-selectors.test.tsx.snap |
Updates selector snapshots. |
src/__tests__/snapshot-tests/__snapshots__/documenter.test.ts.snap |
Updates generated API snapshots. |
pages/button-dropdown/manual-filtering.page.tsx |
Adds manual-filtering scenarios. |
pages/button-dropdown/button-dropdown.async.example.page.tsx |
Adds a full async example. |
pages/button-dropdown/async-loading.page.tsx |
Adds configurable async-loading scenarios. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| ) : null} | ||
| {groupDropdownStatus.content && !groupDropdownStatus.isSticky ? ( | ||
| // Non-sticky status (finished text) follows the items, like in the main dropdown. | ||
| <li role="presentation"> |
| ) : null} | ||
| {groupDropdownStatus.content && !groupDropdownStatus.isSticky ? ( | ||
| // Finished text has no interactive content, so it follows the items inside the menu, like on desktop. | ||
| <li role="presentation"> |
| {dropdownStatus.content && !dropdownStatus.isSticky ? ( | ||
| // Non-sticky status (finished text) scrolls together with the items, like the | ||
| // list bottom in Select, instead of covering the last item. | ||
| <li role="presentation"> |
This branch was successfully deployed
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.