feat(ui): migrate organization profile members panel to mosaic#9109
feat(ui): migrate organization profile members panel to mosaic#9109kylemac wants to merge 1 commit into
Conversation
🦋 Changeset detectedLatest commit: d09b2ef 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.
|
📝 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
Warning Tools execution failed with the following error: Failed to run tools: 13 INTERNAL: Received RST_STREAM with code 2 (Internal server error) 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
| export function OrganizationProfileMembersPanel(): ReactElement | null { | ||
| const controller = useOrganizationProfileMembersPanelController(); | ||
| if (controller.status !== 'ready') { | ||
| return null; |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Document the exported members panel.
OrganizationProfileMembersPanel is exported and exposed as OrganizationProfile.MembersPanel, but has no JSDoc describing its loading/null behavior or rendered content. Add the public API documentation and have Docs review the generated reference entry.
As per coding guidelines, public TypeScript APIs must be documented with JSDoc. As per path instructions, exported APIs under packages/** are customer-facing reference documentation.
🤖 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/organization-profile-members-panel.tsx`
around lines 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.
Sources: Coding guidelines, Path instructions
| export interface OrganizationProfileMembersPanelViewProps { | ||
| snapshot: Snapshot<OrganizationProfileMembersPanelContext>; | ||
| send: (event: OrganizationProfileMembersPanelEvent) => void; | ||
| rows: MemberRow[]; | ||
| canManage: boolean; | ||
| page: number; | ||
| pageCount: number; | ||
| isLoading: boolean; | ||
| onPageChange: (page: number) => void; |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Document the exported view contract.
OrganizationProfileMembersPanelViewProps and OrganizationProfileMembersPanelView are exported but lack JSDoc. Document the public props, return value, and usage example so generated reference documentation matches the implementation.
As per coding guidelines, public TypeScript APIs must be documented with JSDoc. As per path instructions, exported APIs under packages/** are customer-facing reference documentation.
Also applies to: 84-93
🤖 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/organization-profile-members-panel.view.tsx`
around lines 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.
Sources: Coding guidelines, Path instructions
| } | ||
|
|
||
| /** Small pill used for the "You" / "Banned" row markers. */ | ||
| function Badge({ children, intent = 'neutral' }: { children: ReactNode; intent?: 'neutral' | 'destructive' }) { |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Add explicit return types to local components.
Badge, HeaderCell, and Cell return JSX but rely on inference. Annotate them with ReactElement and import that type.
Proposed fix
-import type { ReactNode } from 'react';
+import type { ReactElement, ReactNode } from 'react';
-function Badge({ children, intent = 'neutral' }: { children: ReactNode; intent?: 'neutral' | 'destructive' }) {
+function Badge({ children, intent = 'neutral' }: { children: ReactNode; intent?: 'neutral' | 'destructive' }): ReactElement {
...
-function HeaderCell({ children, align = 'start' }: { children?: ReactNode; align?: 'start' | 'end' }) {
+function HeaderCell({ children, align = 'start' }: { children?: ReactNode; align?: 'start' | 'end' }): ReactElement {
...
-function Cell({ children, align = 'start' }: { children?: ReactNode; align?: 'start' | 'end' }) {
+function Cell({ children, align = 'start' }: { children?: ReactNode; align?: 'start' | 'end' }): ReactElement {As per coding guidelines, TypeScript functions should always have explicit return types.
Also applies to: 48-48, 67-67
🤖 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/organization-profile-members-panel.view.tsx`
at 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.
Source: Coding guidelines
| } | ||
|
|
||
| export function OrganizationProfileView({ general, apiKeys }: OrganizationProfileViewProps) { | ||
| export function OrganizationProfileView({ general, members, apiKeys }: OrganizationProfileViewProps) { |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Document and type the exported profile view.
OrganizationProfileView is exported and its slot contract now includes members, but the function has neither JSDoc nor an explicit return type. Document general, members, apiKeys, and the return value, then annotate the return as ReactElement.
As per coding guidelines, public TypeScript APIs require JSDoc and explicit return types. As per path instructions, exported APIs under packages/** feed customer-facing reference documentation.
🤖 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/organization-profile-view.tsx` at 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.
Sources: Coding guidelines, Path instructions
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
New Features
Documentation
Tests