feat(ui): migrate organization profile members panel to mosaic#9109
Conversation
🦋 Changeset detectedLatest commit: 7594e05 The changes in this PR will be included in the next version bump. This PR includes changesets to release 0 packagesWhen changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository YAML (base), Repository UI (inherited) Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (3)
📝 WalkthroughWalkthroughAdds an organization profile members panel with permission-aware membership data, search, removal, pagination, loading and error states, profile integration, Storybook/MDX documentation, registry wiring, and focused tests. ChangesOrganization members panel
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant OrganizationProfile
participant OrganizationProfileMembersPanel
participant MembershipResource
OrganizationProfile->>OrganizationProfileMembersPanel: render members slot
OrganizationProfileMembersPanel->>MembershipResource: load organization memberships
MembershipResource-->>OrganizationProfileMembersPanel: return rows and pagination
OrganizationProfileMembersPanel->>MembershipResource: destroy selected membership
MembershipResource-->>OrganizationProfileMembersPanel: return removal result
OrganizationProfileMembersPanel-->>OrganizationProfile: render updated panel state
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
Comment |
3e125e7 to
d09b2ef
Compare
@clerk/astro
@clerk/backend
@clerk/chrome-extension
@clerk/clerk-js
@clerk/electron
@clerk/electron-passkeys
@clerk/eslint-plugin
@clerk/expo
@clerk/expo-passkeys
@clerk/express
@clerk/fastify
@clerk/hono
@clerk/localizations
@clerk/nextjs
@clerk/nuxt
@clerk/react
@clerk/react-router
@clerk/shared
@clerk/tanstack-react-start
@clerk/testing
@clerk/ui
@clerk/upgrade
@clerk/vue
commit: |
API Changes Report
Summary
No API Changes DetectedAll packages have stable APIs with no detected changes. Report generated by Break Check Last ran on |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (2)
packages/swingset/src/stories/organization-profile-members-panel.stories.tsx (1)
46-46: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse the required Swingset story function signature.
Defaultis exported but has neither aprops: Record<string, unknown>parameter nor an explicit return type. Align it with the standardknobsAsPropsstory pattern and declare the return type.As per coding guidelines, story functions must accept
Record<string, unknown>props and TypeScript functions should declare explicit return types.🤖 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/swingset/src/stories/organization-profile-members-panel.stories.tsx` at line 46, Update the exported Default story function to accept a props parameter typed as Record<string, unknown>, following the repository’s knobsAsProps story pattern, and add an explicit return type consistent with the rendered story component.Source: Coding guidelines
packages/ui/src/mosaic/organization/__tests__/organization-profile-members-panel.view.test.tsx (1)
120-127: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winTest only covers a single row; doesn't verify other rows' disabled state during removal.
This test renders only one row (
rows: [row({ id: 'mem_1' })]) withpendingMembershipId: 'mem_1', so it confirms the pending row is disabled/relabeled but doesn't assert whether other rows' remove buttons remain enabled or disabled while a removal is in flight. Given the machine (organization-profile-members-panel.machine.ts) silently dropsREMOVE_MEMBERevents dispatched while in theremovingstate, a test with multiple rows — one pending, one not — asserting the non-pending row's button state would close this gap.🤖 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/ui/src/mosaic/organization/__tests__/organization-profile-members-panel.view.test.tsx` around lines 120 - 127, Extend the test "disables and relabels the row currently being removed" to render at least two rows: the pending row with id "mem_1" and a different non-pending row. Keep asserting the pending row's "Removing…" button is disabled, and additionally assert the non-pending row's remove button remains enabled while removal is in progress.
🤖 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/ui/src/mosaic/organization/organization-profile-members-panel.tsx`:
- Around line 6-9: Document the exported OrganizationProfileMembersPanel
function with JSDoc describing that it returns null while the controller is not
ready and what content it renders when ready; then have Docs review the
generated public reference entry for OrganizationProfile.MembersPanel.
In
`@packages/ui/src/mosaic/organization/organization-profile-members-panel.view.tsx`:
- Around line 15-23: Document the exported
OrganizationProfileMembersPanelViewProps interface and
OrganizationProfileMembersPanelView component with JSDoc, covering each public
prop, the component’s return value, and a concise usage example; place the
documentation directly above the corresponding declarations.
- Line 27: Update the local components Badge, HeaderCell, and Cell to explicitly
declare ReactElement as their return type, and import ReactElement as a type
from React. Preserve their existing props and JSX implementations.
In `@packages/ui/src/mosaic/organization/organization-profile-view.tsx`:
- Line 15: The exported OrganizationProfileView function lacks required API
documentation and an explicit return type. Add JSDoc describing the general,
members, and apiKeys parameters and the rendered result, then annotate
OrganizationProfileView’s return type as ReactElement.
---
Nitpick comments:
In
`@packages/swingset/src/stories/organization-profile-members-panel.stories.tsx`:
- Line 46: Update the exported Default story function to accept a props
parameter typed as Record<string, unknown>, following the repository’s
knobsAsProps story pattern, and add an explicit return type consistent with the
rendered story component.
In
`@packages/ui/src/mosaic/organization/__tests__/organization-profile-members-panel.view.test.tsx`:
- Around line 120-127: Extend the test "disables and relabels the row currently
being removed" to render at least two rows: the pending row with id "mem_1" and
a different non-pending row. Keep asserting the pending row's "Removing…" button
is disabled, and additionally assert the non-pending row's remove button remains
enabled while removal is in progress.
🪄 Autofix (Beta)
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: Repository YAML (base), Repository UI (inherited)
Review profile: CHILL
Plan: Pro Plus
Run ID: a4f6ede3-627f-40f0-9d5b-102ab510836a
📒 Files selected for processing (15)
.changeset/wild-members-gather.mdpackages/swingset/src/components/DocsViewer.tsxpackages/swingset/src/lib/registry.tspackages/swingset/src/stories/organization-profile-members-panel.mdxpackages/swingset/src/stories/organization-profile-members-panel.stories.tsxpackages/swingset/src/stories/organization-profile.stories.tsxpackages/ui/src/mosaic/organization/__tests__/organization-profile-members-panel.controller.test.tsxpackages/ui/src/mosaic/organization/__tests__/organization-profile-members-panel.machine.test.tspackages/ui/src/mosaic/organization/__tests__/organization-profile-members-panel.view.test.tsxpackages/ui/src/mosaic/organization/organization-profile-members-panel.controller.tsxpackages/ui/src/mosaic/organization/organization-profile-members-panel.machine.tspackages/ui/src/mosaic/organization/organization-profile-members-panel.tsxpackages/ui/src/mosaic/organization/organization-profile-members-panel.view.tsxpackages/ui/src/mosaic/organization/organization-profile-view.tsxpackages/ui/src/mosaic/organization/organization-profile.tsx
What this does
Migrates the OrganizationProfile members panel into Mosaic using the skill's
machine → controller → viewworkflow, wires it into the Members tab of the MosaicOrganizationProfile, and documents it in swingset.Members-list section (
packages/ui/src/mosaic/sections/members-list.*).machine.ts— pure flow rules: search input-value vs. committedquery(SEARCH_CHANGE/SEARCH_SUBMIT) + aremovingstate with an injected async remove invoke and error handling. No React, no Clerk..controller.tsx— the only Clerk layer: fetches memberships keyed off the machine'squery, gates onorg:sys_memberships:read/:manage, derives plainMemberRow[], injects the per-row remove effect (destroy()+ fire-and-forgetrevalidate())..view.tsx— Clerk-free rendering: search form, members table, gated Remove button, Prev/Next pagination, loading/empty/error states. Built only from existing Mosaic components..tsx— thin wrapper; renders nothing until the controller isready.Panel + AIO wiring
organization-profile-memberspanel (+ view) composes the section.organization-profile.tsx/view take amembersprop, replacing the"Members content"placeholder.Swingset docs
MembersList(Section) andOrganizationProfileMembers(Panel) story + mdx (archetype C), AIO page updated, registered inregistry.ts+DocsViewer.Verification
@clerk/uitype-check: 0 errors · swingset type-check: 0 errors@clerk/uientry point, so no user-facing impact.Parity audit (deferred items to track)
Read + remove + search + paginate are fully migrated. Consciously deferred (each needs a Mosaic primitive that doesn't exist yet):
RoleSelect+membership.update) — needs a Mosaic Select; role renders read-only.hasRoleSetMigration) — needs a Mosaic Alert +useFetchRoles.localizeCustomRole— showsroleNameinstead of the localized custom role.UserPreviewimage) — needs a Mosaic Avatar.Deliberate changes:
ThreeDotsMenu→ inline Remove button; awaited → fire-and-forgetrevalidate; full numbered pagination → Prev/Next. Consistent with existing mosaic sections (hardcoded English strings,error.message). Invitations/Requests sub-tabs and the seat-usage footer were out of scope for this pass.Summary by CodeRabbit