Skip to content

feat(ui): migrate organization profile members panel to mosaic#9109

Merged
alexcarpenter merged 2 commits into
mainfrom
carp/mosaic-members-panel
Jul 10, 2026
Merged

feat(ui): migrate organization profile members panel to mosaic#9109
alexcarpenter merged 2 commits into
mainfrom
carp/mosaic-members-panel

Conversation

@kylemac

@kylemac kylemac commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Stress-test PR — this migration was produced by the mosaic Claude Code skill to evaluate the skill's effectiveness. Based on carp/mosaic-skills (#9106) so the diff shows only the members-panel work. Likely to be closed after review.

What this does

Migrates the OrganizationProfile members panel into Mosaic using the skill's machine → controller → view workflow, wires it into the Members tab of the Mosaic OrganizationProfile, and documents it in swingset.

Members-list section (packages/ui/src/mosaic/sections/members-list.*)

  • .machine.ts — pure flow rules: search input-value vs. committed query (SEARCH_CHANGE/SEARCH_SUBMIT) + a removing state 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's query, gates on org:sys_memberships:read/:manage, derives plain MemberRow[], injects the per-row remove effect (destroy() + fire-and-forget revalidate()).
  • .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 is ready.

Panel + AIO wiring

  • New organization-profile-members panel (+ view) composes the section.
  • AIO organization-profile.tsx/view take a members prop, replacing the "Members content" placeholder.

Swingset docs

MembersList (Section) and OrganizationProfileMembers (Panel) story + mdx (archetype C), AIO page updated, registered in registry.ts + DocsViewer.

Verification

  • @clerk/ui type-check: 0 errors · swingset type-check: 0 errors
  • Mosaic suite: 302 passed (incl. 27 new machine/controller/view tests)
  • Empty changeset — mosaic isn't reachable through any published @clerk/ui entry 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):

  • Role editing (RoleSelect + membership.update) — needs a Mosaic Select; role renders read-only.
  • Role-set-migration warning (hasRoleSetMigration) — needs a Mosaic Alert + useFetchRoles.
  • localizeCustomRole — shows roleName instead of the localized custom role.
  • Member avatar (UserPreview image) — needs a Mosaic Avatar.

Deliberate changes: ThreeDotsMenu → inline Remove button; awaited → fire-and-forget revalidate; 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
    • Added an Organization Profile Members panel with a members table (names, roles, identifiers, joined dates) plus “You” and “Banned” badges.
    • Included search with submit-to-apply behavior, pagination, loading/empty states, and permission-gated member removal with “Removing…” progress and error feedback.
    • Wired the Members panel into the Organization Profile UI and navigation.
  • Documentation
    • Added a new Members panel documentation entry and Storybook example.
  • Tests
    • Added UI, controller, and state-machine test coverage for rendering, search, pagination, permissions, and removal flows.

@changeset-bot

changeset-bot Bot commented Jul 8, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7594e05

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 0 packages

When 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

@vercel

vercel Bot commented Jul 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
clerk-js-sandbox Ready Ready Preview, Comment Jul 10, 2026 2:44pm
swingset Ready Ready Preview, Comment Jul 10, 2026 2:44pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Repository UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 6398a9d2-4f23-4ada-bc75-edd862b31dbe

📥 Commits

Reviewing files that changed from the base of the PR and between d09b2ef and 7594e05.

📒 Files selected for processing (3)
  • packages/ui/src/mosaic/organization/organization-profile-members-panel.tsx
  • packages/ui/src/mosaic/organization/organization-profile-members-panel.view.tsx
  • packages/ui/src/mosaic/organization/organization-profile-view.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/ui/src/mosaic/organization/organization-profile-members-panel.tsx
  • packages/ui/src/mosaic/organization/organization-profile-view.tsx
  • packages/ui/src/mosaic/organization/organization-profile-members-panel.view.tsx

📝 Walkthrough

Walkthrough

Adds 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.

Changes

Organization members panel

Layer / File(s) Summary
Membership state and controller
packages/ui/src/mosaic/organization/organization-profile-members-panel.machine.ts, packages/ui/src/mosaic/organization/organization-profile-members-panel.controller.tsx, packages/ui/src/mosaic/organization/__tests__/*controller*, packages/ui/src/mosaic/organization/__tests__/*machine*
Adds typed search and removal state handling, permission-gated membership loading, member row mapping, removal effects, pagination, and controller/machine coverage.
Members view and profile integration
packages/ui/src/mosaic/organization/organization-profile-members-panel.view.tsx, packages/ui/src/mosaic/organization/organization-profile-members-panel.tsx, packages/ui/src/mosaic/organization/organization-profile-view.tsx, packages/ui/src/mosaic/organization/organization-profile.tsx, packages/ui/src/mosaic/organization/__tests__/*view*
Renders the members table, search form, badges, removal controls, loading and error states, pagination, and connects the panel to the organization profile.
Story and documentation wiring
packages/swingset/src/stories/*members-panel*, packages/swingset/src/stories/organization-profile.stories.tsx, packages/swingset/src/lib/registry.ts, packages/swingset/src/components/DocsViewer.tsx, .changeset/wild-members-gather.md
Adds demo data and stories, registers the story and MDX page, composes the panel in the profile story, and adds a changeset.

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
Loading

Poem

I’m a rabbit with members in rows,
Search hops quickly wherever it goes.
Remove with a click, pagination in flight,
Badges and stories make the panel bright.
Binky, binky—the profile feels right!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: migrating the organization profile members panel to Mosaic.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Comment @coderabbitai help to get the list of available commands.

@pkg-pr-new

pkg-pr-new Bot commented Jul 10, 2026

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@9109

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@9109

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@9109

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@9109

@clerk/electron

npm i https://pkg.pr.new/@clerk/electron@9109

@clerk/electron-passkeys

npm i https://pkg.pr.new/@clerk/electron-passkeys@9109

@clerk/eslint-plugin

npm i https://pkg.pr.new/@clerk/eslint-plugin@9109

@clerk/expo

npm i https://pkg.pr.new/@clerk/expo@9109

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@9109

@clerk/express

npm i https://pkg.pr.new/@clerk/express@9109

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@9109

@clerk/hono

npm i https://pkg.pr.new/@clerk/hono@9109

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@9109

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@9109

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@9109

@clerk/react

npm i https://pkg.pr.new/@clerk/react@9109

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@9109

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@9109

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@9109

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@9109

@clerk/ui

npm i https://pkg.pr.new/@clerk/ui@9109

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@9109

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@9109

commit: 7594e05

@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

API Changes Report

Generated by Break Check on 2026-07-10T14:44:55.017Z

Summary

Metric Count
Packages analyzed 19
Packages with changes 0
🔴 Breaking changes 0
🟡 Non-breaking changes 0
🟢 Additions 0

No API Changes Detected

All packages have stable APIs with no detected changes.


Report generated by Break Check

Last ran on 7594e05.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 win

Use the required Swingset story function signature.

Default is exported but has neither a props: Record<string, unknown> parameter nor an explicit return type. Align it with the standard knobsAsProps story 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 win

Test 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' })]) with pendingMembershipId: '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 drops REMOVE_MEMBER events dispatched while in the removing state, 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

📥 Commits

Reviewing files that changed from the base of the PR and between 145e4d3 and d09b2ef.

📒 Files selected for processing (15)
  • .changeset/wild-members-gather.md
  • packages/swingset/src/components/DocsViewer.tsx
  • packages/swingset/src/lib/registry.ts
  • packages/swingset/src/stories/organization-profile-members-panel.mdx
  • packages/swingset/src/stories/organization-profile-members-panel.stories.tsx
  • packages/swingset/src/stories/organization-profile.stories.tsx
  • packages/ui/src/mosaic/organization/__tests__/organization-profile-members-panel.controller.test.tsx
  • packages/ui/src/mosaic/organization/__tests__/organization-profile-members-panel.machine.test.ts
  • packages/ui/src/mosaic/organization/__tests__/organization-profile-members-panel.view.test.tsx
  • packages/ui/src/mosaic/organization/organization-profile-members-panel.controller.tsx
  • packages/ui/src/mosaic/organization/organization-profile-members-panel.machine.ts
  • packages/ui/src/mosaic/organization/organization-profile-members-panel.tsx
  • packages/ui/src/mosaic/organization/organization-profile-members-panel.view.tsx
  • packages/ui/src/mosaic/organization/organization-profile-view.tsx
  • packages/ui/src/mosaic/organization/organization-profile.tsx

Comment thread packages/ui/src/mosaic/organization/organization-profile-members-panel.view.tsx Outdated
Comment thread packages/ui/src/mosaic/organization/organization-profile-view.tsx Outdated
@alexcarpenter alexcarpenter merged commit 7b581aa into main Jul 10, 2026
53 checks passed
@alexcarpenter alexcarpenter deleted the carp/mosaic-members-panel branch July 10, 2026 14:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants