feat(core, react): sync combobox with uds and limit role selection - #476
Conversation
- port four combobox features from universal-components: retainQueryOnSelect, debounceMs + loading, maxSelections + maxSelectionsMessage, keyboard/blur fixes - move debounce ownership from the service hook into the combobox, deleting use-debounced-value and its registry entries - cap role selection at 10 in the assign-roles and invitation-create modals, disabling unselected options and surfacing a limit message - thread isSearchingRoles from the member-management and member-detail hooks so the role picker shows a spinner while a search is in flight - add max_selection_message and roles_max_selection_message across en-US/fr/ja
|
Warning Review limit reached
Next review available in: 37 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (19)
📝 WalkthroughWalkthroughThe PR adds a ten-role selection limit, localized limit messages, loading states for role searches, query retention after selection, and direct role-search queries. It removes the shared debounced-value hook and updates related types, wiring, registry entries, and tests. ChangesOrganization role selection
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
packages/react/src/components/auth0/my-organization/__tests__/organization-member-detail.test.tsx (1)
837-842: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse typed Vitest mocks instead of assertions.
Lines 837 and 840 coerce API methods with
as ReturnType<typeof vi.fn>. Usevi.mocked(...)if the repository Vitest version supports it. This preserves the mocked method type without unchecked assertions.As per coding guidelines: “Avoid type assertions (
as) unless there is no other option.”Proposed fix
- (apiService.organization.roles.list as ReturnType<typeof vi.fn>).mockResolvedValue({ + vi.mocked(apiService.organization.roles.list).mockResolvedValue({ data: manyRoles, }); - (apiService.organization.members.roles.list as ReturnType<typeof vi.fn>).mockResolvedValue({ + vi.mocked(apiService.organization.members.roles.list).mockResolvedValue({ data: [], });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/react/src/components/auth0/my-organization/__tests__/organization-member-detail.test.tsx` around lines 837 - 842, Replace the ReturnType<typeof vi.fn> assertions on apiService.organization.roles.list and apiService.organization.members.roles.list with vi.mocked(...) and configure the resulting typed mocks with mockResolvedValue, preserving the existing response data.Source: Coding guidelines
packages/react/src/components/ui/combobox.tsx (1)
18-35: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDocument the expanded public API.
Add JSDoc for
ComboboxPropsandCombobox. Document debounce behavior, query retention, loading behavior, and selection-limit behavior. Add@module,@param, and@returnstags where applicable.As per coding guidelines: “Document public APIs with JSDoc; use
@module,@internal,@param, and@returnstags where applicable.”🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/react/src/components/ui/combobox.tsx` around lines 18 - 35, Add JSDoc to the public ComboboxProps interface and Combobox component, using `@module` for the module and `@param/`@returns where applicable. Describe debounceMs behavior, retainQueryOnSelect query retention, loading/loadingMessage behavior, and maxSelections/maxSelectionsMessage selection limits, while documenting any internal-only symbols with `@internal`.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/core/src/i18n/translations/fr.json`:
- Line 1177: Update the max_selection_message value in the French translations
to a natural French translation of the selection-limit message, preserving the
existing key and meaning.
In `@packages/core/src/i18n/translations/ja.json`:
- Line 1240: Translate the English values for max_selection_message at both
referenced entries in the Japanese locale file into natural Japanese, preserving
the existing JSON keys and valid syntax.
In `@packages/react/src/components/ui/combobox.tsx`:
- Around line 654-658: Replace the hardcoded fallback in the Combobox loading
state with a translated loading-message key, using useTranslator for the
user-facing text. Update every role modal that passes loading to also provide
the localized loadingMessage, preserving the existing custom-message behavior
when supplied.
---
Nitpick comments:
In
`@packages/react/src/components/auth0/my-organization/__tests__/organization-member-detail.test.tsx`:
- Around line 837-842: Replace the ReturnType<typeof vi.fn> assertions on
apiService.organization.roles.list and
apiService.organization.members.roles.list with vi.mocked(...) and configure the
resulting typed mocks with mockResolvedValue, preserving the existing response
data.
In `@packages/react/src/components/ui/combobox.tsx`:
- Around line 18-35: Add JSDoc to the public ComboboxProps interface and
Combobox component, using `@module` for the module and `@param/`@returns where
applicable. Describe debounceMs behavior, retainQueryOnSelect query retention,
loading/loadingMessage behavior, and maxSelections/maxSelectionsMessage
selection limits, while documenting any internal-only symbols with `@internal`.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 46faf136-f334-4aa0-8626-90f845948d80
📒 Files selected for processing (25)
packages/core/src/i18n/custom-messages/my-organization/member-management/invitation-tab-types.tspackages/core/src/i18n/custom-messages/my-organization/member-management/member-management-types.tspackages/core/src/i18n/translations/en-US.jsonpackages/core/src/i18n/translations/fr.jsonpackages/core/src/i18n/translations/ja.jsonpackages/react/registry.jsonpackages/react/src/components/auth0/my-organization/__tests__/organization-member-detail.test.tsxpackages/react/src/components/auth0/my-organization/organization-member-detail.tsxpackages/react/src/components/auth0/my-organization/organization-member-management.tsxpackages/react/src/components/auth0/my-organization/shared/member-management/members/organization-member-roles/__tests__/organization-member-assign-roles-modal.test.tsxpackages/react/src/components/auth0/my-organization/shared/member-management/members/organization-member-roles/organization-member-assign-roles-modal.tsxpackages/react/src/components/auth0/my-organization/shared/member-management/organization-member-detail/organization-member-roles-tab.tsxpackages/react/src/components/auth0/my-organization/shared/member-management/shared/invitation-create/__tests__/organization-invitation-create-modal.test.tsxpackages/react/src/components/auth0/my-organization/shared/member-management/shared/invitation-create/organization-invitation-create-modal.tsxpackages/react/src/components/ui/combobox.tsxpackages/react/src/hooks/my-organization/__tests__/use-member-management-service.test.tspackages/react/src/hooks/my-organization/shared/services/use-member-management-service.tspackages/react/src/hooks/my-organization/use-member-detail.tspackages/react/src/hooks/my-organization/use-organization-member-management.tspackages/react/src/hooks/shared/__tests__/use-debounced-value.test.tspackages/react/src/hooks/shared/use-debounced-value.tspackages/react/src/tests/utils/__mocks__/my-organization/member-management/member.mocks.tspackages/react/src/types/my-organization/member-management/organization-invitation-table-types.tspackages/react/src/types/my-organization/member-management/organization-member-detail-types.tspackages/react/src/types/my-organization/member-management/organization-member-management-types.ts
💤 Files with no reviewable changes (3)
- packages/react/src/hooks/shared/tests/use-debounced-value.test.ts
- packages/react/registry.json
- packages/react/src/hooks/shared/use-debounced-value.ts
Summary
Limits role selection to 10 in the assign-roles and invitation-create modals, and
re-syncs the vendored Combobox with the four features added upstream in
universal-components.
Why
The role pickers let admins select any number of roles, but the API rejects requests
over 10 — the failure only surfaced after submit. Separately, the vendored Combobox had
drifted from universal-components, so downstream consumers were missing the debounce,
loading state, and keyboard fixes that had already shipped upstream. Role search also
had no in-flight indicator: keystrokes debounced at the hook level left a visible gap
where the list looked stale with no feedback.
What
Comboboxgains six props:retainQueryOnSelect,debounceMs(default 300),loading,loadingMessage,maxSelections,maxSelectionsMessage. All optional anddefaulted, so existing call sites are unaffected.
maxSelections, unselected options renderdisabled+aria-disabled="true",arrow navigation skips them, and
Enteris guarded so keyboard input cannot bypass thelimit. Already-selected options stay interactive so deselecting always works.
MAX_ROLES_PER_REQUEST(10) inOrganizationMemberAssignRolesModalandOrganizationInvitationCreateModal. Onecomponent backs both the member-table and member-detail entry points, so the limit
holds in both contexts.
isSearchingRolesis a new optional prop on both modals, threaded fromuseMemberManagementService/useMemberDetail. It maps torolesSearchQuery.isFetchingrather thanisLoading, so with React Query'skeepPreviousDataa refetch still shows the spinner instead of silently serving staleoptions.
useDebouncedValueand its registryentries are removed; the service hook now keys its query on the raw search term and the
Combobox coalesces keystrokes. This avoids the double-debounce that stacking the two
would have produced.
member.detail.roles.assign_modal.max_selection_messageandinvitation.create.roles_max_selection_message— with matching optional entries in thecustom-messages types.
fr/jacarry English placeholders pending translation, matchingthe 12 and 18 keys already in that state in those files.
frgets one key, not two: ithas no
invitation.createblock at all yet.Packages
packages/corepackages/reactexamplesReferences
Testing
How can this be verified? Note anything intentionally not covered by tests and why.
Assign roles.
unselected role greys out; already-selected ones stay clickable.
on a disabled row: nothing is added.
spinner row shows for the whole in-flight window including the debounce delay.
Checklist
Contributing
Summary by CodeRabbit
New Features
Bug Fixes
Tests