Skip to content

feat(ui): Add experimental mosaic components export#9045

Open
alexcarpenter wants to merge 14 commits into
mainfrom
feat/mosaic-experimental-export
Open

feat(ui): Add experimental mosaic components export#9045
alexcarpenter wants to merge 14 commits into
mainfrom
feat/mosaic-experimental-export

Conversation

@alexcarpenter

@alexcarpenter alexcarpenter commented Jun 30, 2026

Copy link
Copy Markdown
Member

Description

New @clerk/ui/experimental/mosaic entry.

Exports:

  • MosaicProvider — styling/appearance + emotion cache.
  • OrganizationProfile (compound: .GeneralPanel/.LeaveSection/.DeleteSection) — client-only, consumer needs 'use client' (property access on client ref can't cross RSC boundary).
  • flat parts OrganizationProfile{GeneralPanel,LeaveSection,DeleteSection} — each own client ref, drop straight into RSC, no consumer 'use client'.

Entry carries 'use client' (hooks/context/emotion). Components gate on Clerk loaded → render null til ready, so no server markup; UI after hydration.

Preview: https://swingset-git-feat-mosaic-experimental-export.clerkstage.dev/

Summary by CodeRabbit

  • New Features

    • Added a new Organization profile experience with separate General, Leave, and Delete sections.
    • Introduced an experimental Mosaic entrypoint for easier access to organization profile components.
    • Improved sidebar labeling to show clearer usage examples for components and hooks.
  • Bug Fixes

    • Updated styling setup for more consistent Mosaic rendering and fewer CSS conflicts.
    • Refined layer/group ordering so organization-related content appears in the expected place.

@changeset-bot

changeset-bot Bot commented Jun 30, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: c1e7c00

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

This PR includes changesets to release 3 packages
Name Type
@clerk/ui Patch
@clerk/chrome-extension Patch
@clerk/swingset Patch

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 Jun 30, 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 1, 2026 5:47pm
swingset Ready Ready Preview, Comment Jul 1, 2026 5:47pm

Request Review

@coderabbitai

coderabbitai Bot commented Jun 30, 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: 7dc2eb69-de29-4606-8f30-3dd5c7589b6c

📥 Commits

Reviewing files that changed from the base of the PR and between 2fb9cbd and c1e7c00.

📒 Files selected for processing (28)
  • packages/swingset/src/stories/organization-profile-delete-section.stories.tsx
  • packages/swingset/src/stories/organization-profile-general-panel.stories.tsx
  • packages/swingset/src/stories/organization-profile-leave-section.stories.tsx
  • packages/swingset/src/stories/organization-profile.stories.tsx
  • packages/ui/src/experimental/__tests__/mosaic.test.tsx
  • packages/ui/src/experimental/mosaic.ts
  • packages/ui/src/mosaic/organization/__tests__/organization-profile-delete-section.controller.test.tsx
  • packages/ui/src/mosaic/organization/__tests__/organization-profile-delete-section.machine.test.ts
  • packages/ui/src/mosaic/organization/__tests__/organization-profile-delete-section.view.test.tsx
  • packages/ui/src/mosaic/organization/__tests__/organization-profile-leave-section.controller.test.tsx
  • packages/ui/src/mosaic/organization/__tests__/organization-profile-leave-section.machine.test.ts
  • packages/ui/src/mosaic/organization/__tests__/organization-profile-leave-section.view.test.tsx
  • packages/ui/src/mosaic/organization/__tests__/organization-profile.controller.test.tsx
  • packages/ui/src/mosaic/organization/__tests__/organization-profile.test.tsx
  • packages/ui/src/mosaic/organization/organization-profile-delete-section.controller.tsx
  • packages/ui/src/mosaic/organization/organization-profile-delete-section.machine.ts
  • packages/ui/src/mosaic/organization/organization-profile-delete-section.tsx
  • packages/ui/src/mosaic/organization/organization-profile-delete-section.view.tsx
  • packages/ui/src/mosaic/organization/organization-profile-general-panel-view.tsx
  • packages/ui/src/mosaic/organization/organization-profile-general-panel.tsx
  • packages/ui/src/mosaic/organization/organization-profile-leave-section.controller.tsx
  • packages/ui/src/mosaic/organization/organization-profile-leave-section.machine.ts
  • packages/ui/src/mosaic/organization/organization-profile-leave-section.tsx
  • packages/ui/src/mosaic/organization/organization-profile-leave-section.view.tsx
  • packages/ui/src/mosaic/organization/organization-profile-view.tsx
  • packages/ui/src/mosaic/organization/organization-profile.controller.tsx
  • packages/ui/src/mosaic/organization/organization-profile.tsx
  • references/mosaic-architecture.md
💤 Files with no reviewable changes (17)
  • packages/ui/src/mosaic/organization/tests/organization-profile-leave-section.machine.test.ts
  • packages/ui/src/mosaic/organization/organization-profile-delete-section.tsx
  • packages/ui/src/mosaic/organization/organization-profile-leave-section.tsx
  • packages/ui/src/mosaic/organization/organization-profile.controller.tsx
  • packages/ui/src/mosaic/organization/tests/organization-profile.controller.test.tsx
  • packages/ui/src/mosaic/organization/tests/organization-profile-delete-section.machine.test.ts
  • packages/ui/src/mosaic/organization/tests/organization-profile-delete-section.view.test.tsx
  • packages/ui/src/mosaic/organization/organization-profile-leave-section.view.tsx
  • packages/ui/src/mosaic/organization/organization-profile-delete-section.view.tsx
  • packages/ui/src/mosaic/organization/organization-profile-general-panel-view.tsx
  • packages/ui/src/mosaic/organization/tests/organization-profile-leave-section.view.test.tsx
  • packages/ui/src/mosaic/organization/organization-profile-leave-section.machine.ts
  • packages/ui/src/mosaic/organization/organization-profile-leave-section.controller.tsx
  • packages/ui/src/mosaic/organization/organization-profile-delete-section.machine.ts
  • packages/ui/src/mosaic/organization/tests/organization-profile-delete-section.controller.test.tsx
  • packages/ui/src/mosaic/organization/tests/organization-profile-leave-section.controller.test.tsx
  • packages/ui/src/mosaic/organization/organization-profile-delete-section.controller.tsx
✅ Files skipped from review due to trivial changes (4)
  • packages/ui/src/experimental/tests/mosaic.test.tsx
  • packages/ui/src/mosaic/organization/tests/organization-profile.test.tsx
  • packages/swingset/src/stories/organization-profile-general-panel.stories.tsx
  • references/mosaic-architecture.md
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/swingset/src/stories/organization-profile-delete-section.stories.tsx
  • packages/ui/src/experimental/mosaic.ts
  • packages/swingset/src/stories/organization-profile-leave-section.stories.tsx

📝 Walkthrough

Walkthrough

The Mosaic organization-profile flow is restructured: delete/leave organization machines, controllers, and views are renamed and relocated under organization-profile-*-section, wired with navigation-after-action behavior. A compound OrganizationProfile export is introduced alongside new Mosaic environment/router hooks, an Emotion insertion-point/CSS-reset update in MosaicProvider, a new experimental/mosaic public entrypoint, and updated swingset storybook/registry/docs.

Changes

Organization Profile section/controller restructure

Layer / File(s) Summary
Delete section machine, controller, view and component
packages/ui/src/mosaic/organization/organization-profile-delete-section.{machine,controller,tsx,view}.tsx, packages/ui/src/mosaic/organization/__tests__/organization-profile-delete-section.*, packages/ui/src/mosaic/machine/__tests__/delete-organization-machine.ts
Renames DeleteOrgContext/DeleteOrgEvent/deleteOrgMachine to OrganizationProfileDeleteSection*, adds post-delete navigation via Mosaic router/environment, introduces the new section component, and updates view/tests.
Leave section machine, controller, view and component
packages/ui/src/mosaic/organization/organization-profile-leave-section.{machine,controller,tsx,view}.tsx, packages/ui/src/mosaic/organization/__tests__/organization-profile-leave-section.*
Renames leave-organization types/machine to OrganizationProfileLeaveSection*, replaces membership-destroy with self-leave via user.leaveOrganization, adds revalidation/navigation, introduces the section component, and updates tests.
Compound OrganizationProfile export, controller, hooks
packages/ui/src/mosaic/organization/organization-profile.{controller,tsx}, packages/ui/src/mosaic/organization/organization-profile-general-panel*.tsx, packages/ui/src/mosaic/aio/organization-profile.tsx, packages/ui/src/mosaic/hooks/useMosaic{Environment,Router}.ts, packages/ui/src/mosaic/organization/__tests__/organization-profile*.test.tsx
Introduces a controller-gated OrganizationProfileRoot and compound OrganizationProfile namespace exposing GeneralPanel/LeaveSection/DeleteSection, adds a general panel component, adds environment/router hooks, and adds equivalence tests.

Estimated code review effort: 4 (Complex) | ~60 minutes

MosaicProvider insertion point and CSS reset

Layer / File(s) Summary
Insertion point creation and reset CSS injection
packages/ui/src/mosaic/MosaicProvider.tsx, packages/ui/src/mosaic/__tests__/MosaicProvider.test.tsx
Replaces the lookup-only insertion-point helper with ensureInsertionPoint (creates the node when missing), adds a zero-specificity [data-cl-slot] CSS reset injected as an inline style, and adds tests for reset content and insertion-point creation/reuse.

Public experimental/mosaic export surface

Layer / File(s) Summary
experimental/mosaic entrypoint and build wiring
packages/ui/src/experimental/mosaic.ts, packages/ui/src/experimental/__tests__/mosaic.test.tsx, packages/ui/package.json, packages/ui/tsdown.config.mts, .changeset/open-heads-brush.md, packages/ui/src/mosaic/slot-recipe.ts
Adds the experimental/mosaic.ts re-export module, wires it into package.json exports and the tsdown build, adds an equivalence test, adds a patch changeset, and reorders slot-recipe.ts imports.

Swingset storybook/registry/docs restructuring

Layer / File(s) Summary
Registry, layer ordering, docs and story files
packages/swingset/src/lib/registry.ts, packages/swingset/src/components/{Composition,DocsViewer,app-sidebar}.tsx, packages/swingset/src/stories/organization-profile*, references/mosaic-architecture.md
Updates LAYER_ORDER/docModules for the Organization group, changes sidebar usage-text rendering for hooks, rewires the story registry to new organization-profile sub-story modules, adds new story/MDX files, and updates architecture docs.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant View as OrganizationProfileDeleteSectionView
  participant Controller as useOrganizationProfileDeleteSectionController
  participant Machine as organizationProfileDeleteSectionMachine
  participant Router as useMosaicRouter

  View->>Controller: send CONFIRM
  Controller->>Machine: destroyOrganization()
  Machine-->>Controller: resolved
  Controller->>Router: navigate(afterLeaveUrl)
Loading
sequenceDiagram
  participant View as OrganizationProfileLeaveSectionView
  participant Controller as useOrganizationProfileLeaveSectionController
  participant User as user.leaveOrganization
  participant Router as useMosaicRouter

  View->>Controller: send CONFIRM
  Controller->>User: leaveOrganization(orgId)
  User-->>Controller: resolved
  Controller->>Controller: userMemberships.revalidate()
  Controller->>Router: navigate(afterLeaveUrl)
Loading

Possibly related PRs

  • clerk/javascript#8838: Initial refactor of the mosaic/sections leave/delete-organization flow into block/section/aio layers, a precursor to this organization-profile-section rewrite.
  • clerk/javascript#9017: Removes the old mosaic/sections leave/delete controllers and replaces them with mosaic/organization/organization-profile-*-section modules, overlapping the same rename.
  • clerk/javascript#9041: Replaces the legacy gated mosaic/sections/{delete,leave}-organization controllers/views with the organization-profile-{delete,leave}-section equivalents, matching the same delete/leave gating logic.

Suggested reviewers: wobsoriano

Poem

A rabbit hops through mosaic tiles anew,
Delete and leave, now section-named too. 🐇
A style tag blooms where insertion points grow,
Compound profiles bundled in one tidy row.
Through swingset stories the carrots align —
Hop, ship, and let this refactor shine! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.71% 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 and concisely summarizes the main change: adding an experimental Mosaic components export in ui.
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 Jun 30, 2026

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

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

@clerk/backend

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

@clerk/chrome-extension

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

@clerk/clerk-js

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

@clerk/electron

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

@clerk/electron-passkeys

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

@clerk/eslint-plugin

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

@clerk/expo

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

@clerk/expo-passkeys

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

@clerk/express

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

@clerk/fastify

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

@clerk/hono

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

@clerk/localizations

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

@clerk/nextjs

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

@clerk/nuxt

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

@clerk/react

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

@clerk/react-router

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

@clerk/shared

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

@clerk/tanstack-react-start

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

@clerk/testing

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

@clerk/ui

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

@clerk/upgrade

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

@clerk/vue

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

commit: c1e7c00

@alexcarpenter

Copy link
Copy Markdown
Member Author

!snapshot

@alexcarpenter

Copy link
Copy Markdown
Member Author

!snapshot

@github-actions

This comment has been minimized.

@alexcarpenter

Copy link
Copy Markdown
Member Author

!snapshot

@github-actions

This comment has been minimized.

@alexcarpenter

Copy link
Copy Markdown
Member Author

!snapshot

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@alexcarpenter

Copy link
Copy Markdown
Member Author

!snapshot

@github-actions

This comment has been minimized.

@alexcarpenter

Copy link
Copy Markdown
Member Author

!snapshot

@github-actions

Copy link
Copy Markdown
Contributor

Hey @alexcarpenter - the snapshot version command generated the following package versions:

Package Version
@clerk/astro 3.4.11-snapshot.v20260630204952
@clerk/backend 3.9.1-snapshot.v20260630204952
@clerk/chrome-extension 3.1.47-snapshot.v20260630204952
@clerk/clerk-js 6.23.1-snapshot.v20260630204952
@clerk/electron 0.0.8-snapshot.v20260630204952
@clerk/electron-passkeys 0.0.4-snapshot.v20260630204952
@clerk/eslint-plugin 0.2.1-snapshot.v20260630204952
@clerk/expo 3.6.5-snapshot.v20260630204952
@clerk/expo-passkeys 1.1.13-snapshot.v20260630204952
@clerk/express 2.1.35-snapshot.v20260630204952
@clerk/fastify 3.1.45-snapshot.v20260630204952
@clerk/headless 0.0.7-snapshot.v20260630204952
@clerk/hono 0.1.45-snapshot.v20260630204952
@clerk/localizations 4.12.1-snapshot.v20260630204952
@clerk/msw 0.0.43-snapshot.v20260630204952
@clerk/nextjs 7.5.12-snapshot.v20260630204952
@clerk/nuxt 2.6.11-snapshot.v20260630204952
@clerk/react 6.11.4-snapshot.v20260630204952
@clerk/react-router 3.5.4-snapshot.v20260630204952
@clerk/shared 4.23.1-snapshot.v20260630204952
@clerk/swingset 0.0.13-snapshot.v20260630204952
@clerk/tanstack-react-start 1.4.12-snapshot.v20260630204952
@clerk/testing 2.2.2-snapshot.v20260630204952
@clerk/ui 1.24.1-snapshot.v20260630204952
@clerk/upgrade 2.0.5-snapshot.v20260630204952
@clerk/vue 2.4.11-snapshot.v20260630204952

Tip: Use the snippet copy button below to quickly install the required packages.
@clerk/astro

npm i @clerk/astro@3.4.11-snapshot.v20260630204952 --save-exact

@clerk/backend

npm i @clerk/backend@3.9.1-snapshot.v20260630204952 --save-exact

@clerk/chrome-extension

npm i @clerk/chrome-extension@3.1.47-snapshot.v20260630204952 --save-exact

@clerk/clerk-js

npm i @clerk/clerk-js@6.23.1-snapshot.v20260630204952 --save-exact

@clerk/electron

npm i @clerk/electron@0.0.8-snapshot.v20260630204952 --save-exact

@clerk/electron-passkeys

npm i @clerk/electron-passkeys@0.0.4-snapshot.v20260630204952 --save-exact

@clerk/eslint-plugin

npm i @clerk/eslint-plugin@0.2.1-snapshot.v20260630204952 --save-exact

@clerk/expo

npm i @clerk/expo@3.6.5-snapshot.v20260630204952 --save-exact

@clerk/expo-passkeys

npm i @clerk/expo-passkeys@1.1.13-snapshot.v20260630204952 --save-exact

@clerk/express

npm i @clerk/express@2.1.35-snapshot.v20260630204952 --save-exact

@clerk/fastify

npm i @clerk/fastify@3.1.45-snapshot.v20260630204952 --save-exact

@clerk/headless

npm i @clerk/headless@0.0.7-snapshot.v20260630204952 --save-exact

@clerk/hono

npm i @clerk/hono@0.1.45-snapshot.v20260630204952 --save-exact

@clerk/localizations

npm i @clerk/localizations@4.12.1-snapshot.v20260630204952 --save-exact

@clerk/msw

npm i @clerk/msw@0.0.43-snapshot.v20260630204952 --save-exact

@clerk/nextjs

npm i @clerk/nextjs@7.5.12-snapshot.v20260630204952 --save-exact

@clerk/nuxt

npm i @clerk/nuxt@2.6.11-snapshot.v20260630204952 --save-exact

@clerk/react

npm i @clerk/react@6.11.4-snapshot.v20260630204952 --save-exact

@clerk/react-router

npm i @clerk/react-router@3.5.4-snapshot.v20260630204952 --save-exact

@clerk/shared

npm i @clerk/shared@4.23.1-snapshot.v20260630204952 --save-exact

@clerk/swingset

npm i @clerk/swingset@0.0.13-snapshot.v20260630204952 --save-exact

@clerk/tanstack-react-start

npm i @clerk/tanstack-react-start@1.4.12-snapshot.v20260630204952 --save-exact

@clerk/testing

npm i @clerk/testing@2.2.2-snapshot.v20260630204952 --save-exact

@clerk/ui

npm i @clerk/ui@1.24.1-snapshot.v20260630204952 --save-exact

@clerk/upgrade

npm i @clerk/upgrade@2.0.5-snapshot.v20260630204952 --save-exact

@clerk/vue

npm i @clerk/vue@2.4.11-snapshot.v20260630204952 --save-exact

Comment on lines +6 to +10
import { expandConditions } from './conditions';
import { useMosaicTheme } from './MosaicProvider';
import { resolveSlotClassName, resolveSlotCss } from './resolveSlot';
import { defaultMosaicVariables, resolveVariables } from './variables';
import type { MosaicTheme } from './variables';
import { defaultMosaicVariables, resolveVariables } from './variables';

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

just a sorting change

…imental exports

Rename the experimental Mosaic parts and their files so the source symbols match how they are exported from @clerk/ui/experimental/mosaic:

- DeleteOrganization -> OrganizationProfileDeleteSection
- LeaveOrganization -> OrganizationProfileLeaveSection
- OrganizationProfileGeneral -> OrganizationProfileGeneralPanel
- OrganizationProfile unchanged

The rename cascades through each part's view, controller, and machine symbols and their co-located tests. The experimental entry no longer needs to alias on re-export.

In @clerk/swingset, flatten the AIO/Panels/Sections sidebar groups into a single Organization group, and render each entry by its export name (components as <Name />, hooks as useName()), wrapping long names instead of overflowing.

Public export names from @clerk/ui/experimental/mosaic are unchanged, so there is no user-facing impact.
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

API Changes Report

Generated by Break Check on 2026-07-01T17:48:32.591Z

Summary

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

@clerk/ui

Current version: 1.24.0
Recommended bump: MINOR → 1.25.0

Subpath ./experimental/mosaic

🟢 Additions (1)

Added: ./experimental/mosaic

New subpath export ./experimental/mosaic (15 exported members)


Report generated by Break Check

Last ran on c1e7c00.

@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: 1

🧹 Nitpick comments (5)
packages/ui/src/experimental/mosaic.ts (1)

3-40: 🧹 Nitpick | 🔵 Trivial

Docs team should review this public entrypoint JSDoc.

This module-level doc will surface in generated Clerk Docs, so please confirm the RSC/client-boundary wording and exported surface stay aligned with the intended public API.

As per path instructions, public/reference-facing APIs may appear in generated docs.

🤖 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/experimental/mosaic.ts` around lines 3 - 40, The module JSDoc
in Mosaic’s experimental entrypoint needs a docs review to ensure its client/RSC
boundary explanation and exported API description match the actual public
surface. Update the comment around the top-level exports from mosaic.ts so it
accurately reflects what consumers can import and how OrganizationProfile versus
the flat panel/section exports should be used, keeping the wording aligned with
the intended Clerk Docs output.

Source: Path instructions

packages/ui/src/mosaic/sections/organization-profile-delete-section.tsx (1)

6-18: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding JSDoc for this public flat export.

OrganizationProfileDeleteSection is one of the flat exports intended for direct RSC usage per the PR summary. Since Clerk Docs generates reference pages from JSDoc on public/reference-facing APIs, consider documenting this component (purpose, usage note about requiring MosaicProvider, etc.) so it renders correctly in generated docs.

As per path instructions, "If a PR adds or changes public/reference-facing API surface area, check whether the corresponding JSDoc is present, accurate, and aligned with the implementation" and reference-facing changes "may need Docs-team review."

🤖 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/sections/organization-profile-delete-section.tsx`
around lines 6 - 18, Add JSDoc to the public flat export
OrganizationProfileDeleteSection so Docs can generate a reference page for it.
Document its purpose, the direct RSC usage intent, and the requirement that it
be rendered within MosaicProvider, keeping the description aligned with the
implementation and other reference-facing exports in this area.

Source: Path instructions

packages/ui/src/mosaic/aio/organization-profile.tsx (1)

9-30: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add JSDoc on the OrganizationProfile compound export.

OrganizationProfile is the primary public export of the new experimental/mosaic entrypoint (compound with .GeneralPanel, .LeaveSection, .DeleteSection). Since it's reference-facing, consider adding a JSDoc block (purpose, required MosaicProvider ancestor, 'use client' requirement noted in the PR description, and documenting the attached parts) so generated docs reflect this API accurately.

As per path instructions, "If a PR adds or changes public/reference-facing API surface area, check whether the corresponding JSDoc is present, accurate, and aligned with the implementation."

🤖 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/aio/organization-profile.tsx` around lines 9 - 30, Add
a JSDoc block to the public OrganizationProfile export so the reference docs
capture this compound API accurately. Document that OrganizationProfile is the
primary experimental/mosaic entrypoint, that it requires a MosaicProvider
ancestor and a client-only environment, and list the attached compound parts
(GeneralPanel, LeaveSection, DeleteSection). Place the comment on the
OrganizationProfile binding in organization-profile.tsx so it stays aligned with
the implementation and its Object.assign-based export shape.

Source: Path instructions

packages/ui/src/mosaic/panels/organization-profile-general-panel.tsx (1)

7-14: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding JSDoc for this public flat export.

Same as OrganizationProfileDeleteSectionOrganizationProfileGeneralPanel is one of the flat exports intended for direct RSC usage. Documenting it would help keep generated reference docs accurate for this new public surface.

As per path instructions, reference-facing exports should have JSDoc so generated docs reflect the implementation.

🤖 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/panels/organization-profile-general-panel.tsx` around
lines 7 - 14, Add JSDoc to the public flat export
OrganizationProfileGeneralPanel so generated reference docs include it for
direct RSC usage. Update the function declaration in
OrganizationProfileGeneralPanel to include a concise descriptive comment,
matching the documentation style used by OrganizationProfileDeleteSection and
other reference-facing exports.

Source: Path instructions

packages/ui/src/mosaic/sections/organization-profile-delete-section.controller.tsx (1)

23-42: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate post-action navigation logic vs. leave controller.

The revalidate + fire-and-forget router.navigate(afterLeaveUrl) block (Lines 36-42) is duplicated nearly verbatim in organization-profile-leave-section.controller.tsx. Consider extracting a small shared hook (e.g., useAfterOrgActionNavigate(afterLeaveUrl)) since more sections are being added to this namespace.

♻️ Sketch of a shared helper
// packages/ui/src/mosaic/hooks/useAfterOrgActionNavigate.ts
export function useAfterOrgActionNavigate() {
  const router = useMosaicRouter();
  const afterLeaveUrl = useMosaicEnvironment()?.displayConfig.afterLeaveOrganizationUrl;
  return () => {
    if (afterLeaveUrl) {
      void router.navigate(afterLeaveUrl);
    }
  };
}
🤖 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/sections/organization-profile-delete-section.controller.tsx`
around lines 23 - 42, The post-action navigation/revalidate logic inside
useOrganizationProfileDeleteSectionController is duplicated in the leave
controller, so extract the shared “after org action” behavior into a reusable
hook or helper and call it from both controllers. Keep the existing
destroy/revalidate flow in organizationProfileDeleteSectionMachine’s context,
but move the afterLeaveUrl lookup and fire-and-forget router.navigate behavior
into a shared function such as useAfterOrgActionNavigate so future organization
sections can reuse it.
🤖 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/__tests__/MosaicProvider.test.tsx`:
- Around line 85-94: The MosaicProvider reset test only covers the unlayered CSS
path; extend the existing test around MosaicProvider/styleText to also assert
the layered reset output when cssLayerName is provided and that the nonce value
is forwarded to the generated style tag. Use the existing `MosaicProvider`
render setup and `styleText()` assertions to verify both the wrapped CSS branch
and nonce propagation, alongside the current `:where([data-cl-slot])` reset
checks.

---

Nitpick comments:
In `@packages/ui/src/experimental/mosaic.ts`:
- Around line 3-40: The module JSDoc in Mosaic’s experimental entrypoint needs a
docs review to ensure its client/RSC boundary explanation and exported API
description match the actual public surface. Update the comment around the
top-level exports from mosaic.ts so it accurately reflects what consumers can
import and how OrganizationProfile versus the flat panel/section exports should
be used, keeping the wording aligned with the intended Clerk Docs output.

In `@packages/ui/src/mosaic/aio/organization-profile.tsx`:
- Around line 9-30: Add a JSDoc block to the public OrganizationProfile export
so the reference docs capture this compound API accurately. Document that
OrganizationProfile is the primary experimental/mosaic entrypoint, that it
requires a MosaicProvider ancestor and a client-only environment, and list the
attached compound parts (GeneralPanel, LeaveSection, DeleteSection). Place the
comment on the OrganizationProfile binding in organization-profile.tsx so it
stays aligned with the implementation and its Object.assign-based export shape.

In `@packages/ui/src/mosaic/panels/organization-profile-general-panel.tsx`:
- Around line 7-14: Add JSDoc to the public flat export
OrganizationProfileGeneralPanel so generated reference docs include it for
direct RSC usage. Update the function declaration in
OrganizationProfileGeneralPanel to include a concise descriptive comment,
matching the documentation style used by OrganizationProfileDeleteSection and
other reference-facing exports.

In
`@packages/ui/src/mosaic/sections/organization-profile-delete-section.controller.tsx`:
- Around line 23-42: The post-action navigation/revalidate logic inside
useOrganizationProfileDeleteSectionController is duplicated in the leave
controller, so extract the shared “after org action” behavior into a reusable
hook or helper and call it from both controllers. Keep the existing
destroy/revalidate flow in organizationProfileDeleteSectionMachine’s context,
but move the afterLeaveUrl lookup and fire-and-forget router.navigate behavior
into a shared function such as useAfterOrgActionNavigate so future organization
sections can reuse it.

In `@packages/ui/src/mosaic/sections/organization-profile-delete-section.tsx`:
- Around line 6-18: Add JSDoc to the public flat export
OrganizationProfileDeleteSection so Docs can generate a reference page for it.
Document its purpose, the direct RSC usage intent, and the requirement that it
be rendered within MosaicProvider, keeping the description aligned with the
implementation and other reference-facing exports in this area.
🪄 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: e135a058-7b33-4d86-98fd-ad4eaf44879e

📥 Commits

Reviewing files that changed from the base of the PR and between feac5f3 and 2fb9cbd.

📒 Files selected for processing (51)
  • .changeset/open-heads-brush.md
  • packages/swingset/src/components/Composition.tsx
  • packages/swingset/src/components/DocsViewer.tsx
  • packages/swingset/src/components/app-sidebar.tsx
  • packages/swingset/src/lib/registry.ts
  • packages/swingset/src/stories/delete-organization.stories.tsx
  • packages/swingset/src/stories/leave-organization.stories.tsx
  • packages/swingset/src/stories/organization-profile-delete-section.mdx
  • packages/swingset/src/stories/organization-profile-delete-section.stories.tsx
  • packages/swingset/src/stories/organization-profile-general-panel.mdx
  • packages/swingset/src/stories/organization-profile-general-panel.stories.tsx
  • packages/swingset/src/stories/organization-profile-general.mdx
  • packages/swingset/src/stories/organization-profile-general.stories.tsx
  • packages/swingset/src/stories/organization-profile-leave-section.mdx
  • packages/swingset/src/stories/organization-profile-leave-section.stories.tsx
  • packages/swingset/src/stories/organization-profile.mdx
  • packages/swingset/src/stories/organization-profile.stories.tsx
  • packages/ui/package.json
  • packages/ui/src/experimental/__tests__/mosaic.test.tsx
  • packages/ui/src/experimental/mosaic.ts
  • packages/ui/src/mosaic/MosaicProvider.tsx
  • packages/ui/src/mosaic/__tests__/MosaicProvider.test.tsx
  • packages/ui/src/mosaic/aio/__tests__/organization-profile.controller.test.tsx
  • packages/ui/src/mosaic/aio/__tests__/organization-profile.test.tsx
  • packages/ui/src/mosaic/aio/organization-profile.controller.tsx
  • packages/ui/src/mosaic/aio/organization-profile.tsx
  • packages/ui/src/mosaic/hooks/useMosaicEnvironment.ts
  • packages/ui/src/mosaic/hooks/useMosaicRouter.ts
  • packages/ui/src/mosaic/machine/__tests__/delete-organization-machine.ts
  • packages/ui/src/mosaic/panels/organization-profile-general-panel-view.tsx
  • packages/ui/src/mosaic/panels/organization-profile-general-panel.tsx
  • packages/ui/src/mosaic/panels/organization-profile-general.tsx
  • packages/ui/src/mosaic/sections/__tests__/organization-profile-delete-section.controller.test.tsx
  • packages/ui/src/mosaic/sections/__tests__/organization-profile-delete-section.machine.test.ts
  • packages/ui/src/mosaic/sections/__tests__/organization-profile-delete-section.view.test.tsx
  • packages/ui/src/mosaic/sections/__tests__/organization-profile-leave-section.controller.test.tsx
  • packages/ui/src/mosaic/sections/__tests__/organization-profile-leave-section.machine.test.ts
  • packages/ui/src/mosaic/sections/__tests__/organization-profile-leave-section.view.test.tsx
  • packages/ui/src/mosaic/sections/delete-organization.tsx
  • packages/ui/src/mosaic/sections/leave-organization.controller.tsx
  • packages/ui/src/mosaic/sections/leave-organization.tsx
  • packages/ui/src/mosaic/sections/organization-profile-delete-section.controller.tsx
  • packages/ui/src/mosaic/sections/organization-profile-delete-section.machine.ts
  • packages/ui/src/mosaic/sections/organization-profile-delete-section.tsx
  • packages/ui/src/mosaic/sections/organization-profile-delete-section.view.tsx
  • packages/ui/src/mosaic/sections/organization-profile-leave-section.controller.tsx
  • packages/ui/src/mosaic/sections/organization-profile-leave-section.machine.ts
  • packages/ui/src/mosaic/sections/organization-profile-leave-section.tsx
  • packages/ui/src/mosaic/sections/organization-profile-leave-section.view.tsx
  • packages/ui/src/mosaic/slot-recipe.ts
  • packages/ui/tsdown.config.mts
💤 Files with no reviewable changes (8)
  • packages/ui/src/mosaic/sections/delete-organization.tsx
  • packages/swingset/src/stories/delete-organization.stories.tsx
  • packages/swingset/src/stories/leave-organization.stories.tsx
  • packages/ui/src/mosaic/sections/leave-organization.tsx
  • packages/ui/src/mosaic/panels/organization-profile-general.tsx
  • packages/swingset/src/stories/organization-profile-general.mdx
  • packages/ui/src/mosaic/sections/leave-organization.controller.tsx
  • packages/swingset/src/stories/organization-profile-general.stories.tsx

Comment on lines +85 to +94
it('emits a zero-specificity box-sizing/margin/padding reset scoped to [data-cl-slot]', () => {
render(React.createElement(MosaicProvider, {}, React.createElement('div')));

const css = styleText();
// `:where()` keeps the reset at 0 specificity so component classes always win on insertion-order ties.
expect(css).toContain(':where([data-cl-slot])');
expect(css).toContain('box-sizing:border-box');
expect(css).toContain('margin:0');
expect(css).toContain('padding:0');
});

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Cover the layered reset/nonce branch.

The new reset style also supports cssLayerName and nonce, but this test only exercises the unlayered path. Add one assertion for the wrapped CSS and nonce forwarding.

🧪 Proposed test coverage
   it('emits a zero-specificity box-sizing/margin/padding reset scoped to [data-cl-slot]', () => {
     render(React.createElement(MosaicProvider, {}, React.createElement('div')));
 
     const css = styleText();
     // `:where()` keeps the reset at 0 specificity so component classes always win on insertion-order ties.
     expect(css).toContain(':where([data-cl-slot])');
     expect(css).toContain('box-sizing:border-box');
     expect(css).toContain('margin:0');
     expect(css).toContain('padding:0');
   });
+
+  it('wraps the reset in the requested CSS layer and forwards the nonce', () => {
+    render(React.createElement(MosaicProvider, { cssLayerName: 'clerk.mosaic', nonce: 'test-nonce' }, React.createElement('div')));
+
+    const resetStyle = Array.from(document.querySelectorAll('style')).find(node =>
+      node.textContent?.includes(':where([data-cl-slot])'),
+    );
+    expect(resetStyle?.textContent).toContain('`@layer` clerk.mosaic{');
+    expect(resetStyle?.nonce).toBe('test-nonce');
+  });
 });

As per coding guidelines, “Unit tests are required for all new functionality” and “Include tests for all new features”.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it('emits a zero-specificity box-sizing/margin/padding reset scoped to [data-cl-slot]', () => {
render(React.createElement(MosaicProvider, {}, React.createElement('div')));
const css = styleText();
// `:where()` keeps the reset at 0 specificity so component classes always win on insertion-order ties.
expect(css).toContain(':where([data-cl-slot])');
expect(css).toContain('box-sizing:border-box');
expect(css).toContain('margin:0');
expect(css).toContain('padding:0');
});
it('emits a zero-specificity box-sizing/margin/padding reset scoped to [data-cl-slot]', () => {
render(React.createElement(MosaicProvider, {}, React.createElement('div')));
const css = styleText();
// `:where()` keeps the reset at 0 specificity so component classes always win on insertion-order ties.
expect(css).toContain(':where([data-cl-slot])');
expect(css).toContain('box-sizing:border-box');
expect(css).toContain('margin:0');
expect(css).toContain('padding:0');
});
it('wraps the reset in the requested CSS layer and forwards the nonce', () => {
render(React.createElement(MosaicProvider, { cssLayerName: 'clerk.mosaic', nonce: 'test-nonce' }, React.createElement('div')));
const resetStyle = Array.from(document.querySelectorAll('style')).find(node =>
node.textContent?.includes(':where([data-cl-slot])'),
);
expect(resetStyle?.textContent).toContain('`@layer` clerk.mosaic{');
expect(resetStyle?.nonce).toBe('test-nonce');
});
🤖 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/__tests__/MosaicProvider.test.tsx` around lines 85 -
94, The MosaicProvider reset test only covers the unlayered CSS path; extend the
existing test around MosaicProvider/styleText to also assert the layered reset
output when cssLayerName is provided and that the nonce value is forwarded to
the generated style tag. Use the existing `MosaicProvider` render setup and
`styleText()` assertions to verify both the wrapped CSS branch and nonce
propagation, alongside the current `:where([data-cl-slot])` reset checks.

Source: Coding guidelines

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.

1 participant