Skip to content

feat(ui): add Mosaic Item component - #9234

Open
alexcarpenter wants to merge 12 commits into
mainfrom
carp/mosaic-item
Open

feat(ui): add Mosaic Item component#9234
alexcarpenter wants to merge 12 commits into
mainfrom
carp/mosaic-item

Conversation

@alexcarpenter

@alexcarpenter alexcarpenter commented Jul 23, 2026

Copy link
Copy Markdown
Member

Description

Adds a new Item component to Mosaic, styled with StyleX following the Button migration (themeProps + stylex.props + mergeStyleProps; public contract is the .cl-item* classes plus data-* axes). It's a row for lists of accounts, organizations, and settings (org switcher, account switcher, settings rows), composed via dot syntax.

Parts

  • Item.Root — the row; renders a <div> or a custom element via render
  • Item.Media — fixed-width leading/trailing slot that centers an icon, image, or avatar
  • Item.Content, Item.Title, Item.Description, Item.Actions
  • Item.Header, Item.HeaderTitle, Item.HeaderActions — a header row above a group
  • Item.Group (role="list"), Item.Separator

Behavior

  • variant (entity default | action) sets the row's vertical density (entity 8px, action 10px) and, on interactive rows, promotes the title color: action titles start faded and darken to neutral on hover. Reflected as data-variant.
  • Polymorphism uses the repo's render prop (via useRender), not shadcn's asChild. A plain Item.Root is a static <div>; passing render makes the row a link or button and opts it into cursor + hover affordances, reflected as data-interactive.
  • The action hover treatment is scoped with StyleX's when API and a marker set only on interactive action rows, so no other row's title is affected.

Docs

Swingset docs added (item.stories.tsx + item.mdx) and wired into registry.ts / DocsViewer.tsx.

Checklist

  • pnpm test runs as expected.
  • pnpm build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

@changeset-bot

changeset-bot Bot commented Jul 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 85c95c0

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 23, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
swingset Ready Ready Preview, Comment Jul 29, 2026 6:23pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
clerk-js-sandbox Skipped Skipped Jul 29, 2026 6:23pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a composable Mosaic Item component with typed subcomponents, StyleX styling, polymorphic rendering, ref forwarding, and tests. Exports it through Mosaic barrels, adds Storybook stories and MDX documentation, registers the stories and docs in Swingset, updates Mosaic TypeScript paths and styling documentation, adjusts avatar and color tokens, and includes a changeset entry.

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

Possibly related PRs

  • clerk/javascript#9221: Extends the same Swingset documentation and story registry mappings for another Mosaic component.
  • clerk/javascript#9230: Modifies the shared Mosaic Avatar stylesheet used by the new Item stories.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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
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.
Title check ✅ Passed The title clearly and concisely describes the main change: adding the Mosaic Item component.
Description check ✅ Passed The description is broadly aligned with the PR and discusses the new Mosaic Item component and docs integration.

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.

❤️ Share

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

@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/ui/src/mosaic/components/item/index.ts (1)

1-2: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Avoid introducing the Item re-export barrel.

The new directory index.ts adds an unnecessary re-export boundary and the public entry consumes it. Export directly from item.tsx instead to avoid a future circular-dependency edge.

  • packages/ui/src/mosaic/components/item/index.ts#L1-L2: remove the local re-export barrel.
  • packages/ui/src/mosaic/styles/index.ts#L10-L11: re-export from ../components/item/item directly.

As per coding guidelines, “Avoid barrel files (index.ts re-exports) as they can cause circular dependencies.”

🤖 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/components/item/index.ts` around lines 1 - 2, Remove
the Item re-export barrel from packages/ui/src/mosaic/components/item/index.ts
lines 1-2. Update packages/ui/src/mosaic/styles/index.ts lines 10-11 to
re-export Item, ItemMediaProps, and ItemProps directly from
../components/item/item, preserving the existing public exports.

Source: Coding guidelines

packages/swingset/src/stories/item.stories.tsx (1)

17-49: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add explicit return types to the story components.

Annotate BuildingIcon, ArrowIcon, and the exported stories with the project’s JSX element return type instead of relying on inference.

As per coding guidelines, “Always define explicit return types for functions, especially public APIs.”

Also applies to: 51-153

🤖 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/item.stories.tsx` around lines 17 - 49,
Annotate BuildingIcon, ArrowIcon, and every exported story component in this
file with the project’s established JSX element return type. Apply the same
explicit return-type convention consistently across the story definitions,
including the stories referenced in the additional range, without changing their
rendering behavior.

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 @.changeset/mosaic-item.md:
- Around line 1-2: Add a non-empty changeset for the new public `Item` export
from `@clerk/ui`, specifying the appropriate package bump and a concise release
note describing the API addition. Replace the current empty frontmatter in
`.changeset/mosaic-item.md` while preserving valid changeset formatting.

In `@packages/swingset/src/stories/item.mdx`:
- Around line 37-53: Add the required public Button import and provide a
BuildingIcon import or local definition in the Item usage example so the snippet
is self-contained and compiles when copied; preserve the existing Item.Group
structure and usage.

In `@packages/ui/src/mosaic/components/item/item.tsx`:
- Around line 149-151: Remove the role="list" assignment from Item.Group in
packages/ui/src/mosaic/components/item/item.tsx (lines 149-151), since it cannot
guarantee listitem children; update the corresponding semantic-role assertion in
packages/ui/src/mosaic/components/item/item.test.tsx (lines 91-101), and remove
or revise the role="list" documentation claim in
packages/swingset/src/stories/item.mdx (line 67).
- Around line 16-168: Integrate the Item surface with the customization contract
by defining stable element descriptors for Root and each slot component: Media,
Content, Title, Description, Actions, Footer, Group, and Separator. Pass the
appropriate descriptor through each renderElement call and wrap the exported
primitive components with the repository’s makeCustomizable HOC so appearance
elements overrides can target every Item element.

---

Nitpick comments:
In `@packages/swingset/src/stories/item.stories.tsx`:
- Around line 17-49: Annotate BuildingIcon, ArrowIcon, and every exported story
component in this file with the project’s established JSX element return type.
Apply the same explicit return-type convention consistently across the story
definitions, including the stories referenced in the additional range, without
changing their rendering behavior.

In `@packages/ui/src/mosaic/components/item/index.ts`:
- Around line 1-2: Remove the Item re-export barrel from
packages/ui/src/mosaic/components/item/index.ts lines 1-2. Update
packages/ui/src/mosaic/styles/index.ts lines 10-11 to re-export Item,
ItemMediaProps, and ItemProps directly from ../components/item/item, preserving
the existing public exports.
🪄 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), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 41e7b2f0-ab0b-49bc-bdbf-bed0f2e18d58

📥 Commits

Reviewing files that changed from the base of the PR and between 17d1db1 and d37de13.

📒 Files selected for processing (10)
  • .changeset/mosaic-item.md
  • packages/swingset/src/components/DocsViewer.tsx
  • packages/swingset/src/lib/registry.ts
  • packages/swingset/src/stories/item.mdx
  • packages/swingset/src/stories/item.stories.tsx
  • packages/ui/src/mosaic/components/item/index.ts
  • packages/ui/src/mosaic/components/item/item.styles.ts
  • packages/ui/src/mosaic/components/item/item.test.tsx
  • packages/ui/src/mosaic/components/item/item.tsx
  • packages/ui/src/mosaic/styles/index.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • clerk/clerk_go (manual)
  • clerk/dashboard (manual)
  • clerk/accounts (manual)
  • clerk/backoffice (manual)
  • clerk/clerk (manual)
  • clerk/clerk-docs (manual)
  • clerk/cloudflare-workers (manual)
  • clerk/clerk-ios (auto-detected)
  • clerk/cli (auto-detected)
  • clerk/clerk-android (auto-detected)

Comment thread .changeset/mosaic-item.md
Comment on lines +1 to +2
---
---

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.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Add a release entry for the new public UI API.

This PR exports Item from @clerk/ui; an empty changeset risks shipping no version containing the component. Add the appropriate @clerk/ui bump and release note.

Based on learnings, empty changesets are acceptable for documentation-only or internal-only work, not a published public API addition.

🤖 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 @.changeset/mosaic-item.md around lines 1 - 2, Add a non-empty changeset for
the new public `Item` export from `@clerk/ui`, specifying the appropriate
package bump and a concise release note describing the API addition. Replace the
current empty frontmatter in `.changeset/mosaic-item.md` while preserving valid
changeset formatting.

Sources: Coding guidelines, Learnings

Comment on lines +37 to +53
```tsx
import { Item } from '@clerk/ui/mosaic/components/item';

<Item.Group>
<Item render={({ children, ...props }) => <a {...props} href='/org'>{children}</a>}>
<Item.Media variant='icon'>
<BuildingIcon />
</Item.Media>
<Item.Content>
<Item.Title>Test Organization</Item.Title>
<Item.Description>Member</Item.Description>
</Item.Content>
<Item.Actions>
<Button variant='outline'>Manage</Button>
</Item.Actions>
</Item>
</Item.Group>;

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Make the usage example self-contained.

Button and BuildingIcon are used but never imported or defined, so this snippet does not compile when copied. Add the public Button import and an icon import/definition, or remove those usages.

🤖 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/item.mdx` around lines 37 - 53, Add the
required public Button import and provide a BuildingIcon import or local
definition in the Item usage example so the snippet is self-contained and
compiles when copied; preserve the existing Item.Group structure and usage.

Source: Coding guidelines

Comment on lines +16 to +168
const Root = React.forwardRef<HTMLDivElement, ItemProps>(function MosaicItem(
{ variant = 'default', size = 'default', render, className, style, ...rest },
ref,
) {
// A custom render (link/button row) opts into hover + cursor affordances.
const interactive = Boolean(render);
return renderElement({
defaultTagName: 'div',
render,
props: {
ref,
...mergeProps(
themeProps('item', { variant, size, interactive }),
stylex.props(
slots.item.base,
variant === 'outline' && slots.item.variantOutline,
variant === 'muted' && slots.item.variantMuted,
variant === 'default' && slots.item.variantDefault,
size === 'sm' ? slots.item.sizeSm : slots.item.sizeMd,
interactive && slots.item.interactive,
),
className,
style,
),
...rest,
},
});
});

export type ItemMediaProps = ComponentProps<'div'> & {
variant?: 'default' | 'icon' | 'image';
};

const Media = React.forwardRef<HTMLDivElement, ItemMediaProps>(function MosaicItemMedia(
{ variant = 'default', render, className, style, ...rest },
ref,
) {
return renderElement({
defaultTagName: 'div',
render,
props: {
ref,
...mergeProps(
themeProps('item-media', { variant }),
stylex.props(
slots.media.base,
variant === 'icon' && slots.media.icon,
variant === 'image' && slots.media.image,
),
className,
style,
),
...rest,
},
});
});

const Content = React.forwardRef<HTMLDivElement, ComponentProps<'div'>>(function MosaicItemContent(
{ render, className, style, ...rest },
ref,
) {
return renderElement({
defaultTagName: 'div',
render,
props: {
ref,
...mergeProps(themeProps('item-content'), stylex.props(slots.content.base), className, style),
...rest,
},
});
});

const Title = React.forwardRef<HTMLDivElement, ComponentProps<'div'>>(function MosaicItemTitle(
{ render, className, style, ...rest },
ref,
) {
return renderElement({
defaultTagName: 'div',
render,
props: { ref, ...mergeProps(themeProps('item-title'), stylex.props(slots.title.base), className, style), ...rest },
});
});

const Description = React.forwardRef<HTMLParagraphElement, ComponentProps<'p'>>(function MosaicItemDescription(
{ render, className, style, ...rest },
ref,
) {
return renderElement({
defaultTagName: 'p',
render,
props: {
ref,
...mergeProps(themeProps('item-description'), stylex.props(slots.description.base), className, style),
...rest,
},
});
});

const Actions = React.forwardRef<HTMLDivElement, ComponentProps<'div'>>(function MosaicItemActions(
{ render, className, style, ...rest },
ref,
) {
return renderElement({
defaultTagName: 'div',
render,
props: {
ref,
...mergeProps(themeProps('item-actions'), stylex.props(slots.actions.base), className, style),
...rest,
},
});
});

const Footer = React.forwardRef<HTMLDivElement, ComponentProps<'div'>>(function MosaicItemFooter(
{ render, className, style, ...rest },
ref,
) {
return renderElement({
defaultTagName: 'div',
render,
props: { ref, ...mergeProps(themeProps('item-footer'), stylex.props(slots.band.base), className, style), ...rest },
});
});

const Group = React.forwardRef<HTMLDivElement, ComponentProps<'div'>>(function MosaicItemGroup(
{ render, className, style, ...rest },
ref,
) {
return renderElement({
defaultTagName: 'div',
render,
props: {
ref,
role: 'list',
...mergeProps(themeProps('item-group'), stylex.props(slots.group.base), className, style),
...rest,
},
});
});

const Separator = React.forwardRef<HTMLHRElement, ComponentProps<'hr'>>(function MosaicItemSeparator(
{ render, className, style, ...rest },
ref,
) {
return renderElement({
defaultTagName: 'hr',
render,
props: {
ref,
...mergeProps(themeProps('item-separator'), stylex.props(slots.separator.base), className, style),
...rest,
},
});

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.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Wire Item slots into the UI customization contract.

The new themable Item surface only emits themeProps/StyleX classes; no slot receives an elementDescriptor or is wrapped through the customizable primitive path. Appearance elements overrides therefore cannot target this public component consistently.

Add stable descriptors for the root and slots, then apply the repository’s elementDescriptor/makeCustomizable integration.

As per coding guidelines, “Use element descriptors for all themable elements” and “Wrap primitive components with makeCustomizable HOC.”

🤖 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/components/item/item.tsx` around lines 16 - 168,
Integrate the Item surface with the customization contract by defining stable
element descriptors for Root and each slot component: Media, Content, Title,
Description, Actions, Footer, Group, and Separator. Pass the appropriate
descriptor through each renderElement call and wrap the exported primitive
components with the repository’s makeCustomizable HOC so appearance elements
overrides can target every Item element.

Source: Coding guidelines

Comment on lines +149 to +151
role: 'list',
...mergeProps(themeProps('item-group'), stylex.props(slots.group.base), className, style),
...rest,

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Do not expose a list role without list-item children.

Item.Group declares an ARIA list, but its direct Item and Item.Separator children are div/hr or arbitrary render targets, not listitems. Either remove the list role or redesign the group API to enforce semantic list items.

  • packages/ui/src/mosaic/components/item/item.tsx#L149-L151: remove role: 'list' unless the component can guarantee listitem children.
  • packages/ui/src/mosaic/components/item/item.test.tsx#L91-L101: update the test to reflect the corrected semantic contract.
  • packages/swingset/src/stories/item.mdx#L67-L67: remove or revise the role="list" documentation claim.

As per coding guidelines, “Use proper HTML elements for semantic HTML in React components.”

📍 Affects 3 files
  • packages/ui/src/mosaic/components/item/item.tsx#L149-L151 (this comment)
  • packages/ui/src/mosaic/components/item/item.test.tsx#L91-L101
  • packages/swingset/src/stories/item.mdx#L67-L67
🤖 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/components/item/item.tsx` around lines 149 - 151,
Remove the role="list" assignment from Item.Group in
packages/ui/src/mosaic/components/item/item.tsx (lines 149-151), since it cannot
guarantee listitem children; update the corresponding semantic-role assertion in
packages/ui/src/mosaic/components/item/item.test.tsx (lines 91-101), and remove
or revise the role="list" documentation claim in
packages/swingset/src/stories/item.mdx (line 67).

Source: Coding guidelines

@pkg-pr-new

pkg-pr-new Bot commented Jul 23, 2026

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

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

@clerk/backend

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

@clerk/chrome-extension

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

@clerk/clerk-js

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

@clerk/electron

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

@clerk/electron-passkeys

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

@clerk/eslint-plugin

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

@clerk/expo

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

@clerk/expo-google-signin

npm i https://pkg.pr.new/@clerk/expo-google-signin@9234

@clerk/expo-passkeys

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

@clerk/express

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

@clerk/fastify

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

@clerk/hono

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

@clerk/localizations

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

@clerk/nextjs

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

@clerk/nuxt

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

@clerk/react

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

@clerk/react-router

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

@clerk/shared

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

@clerk/tanstack-react-start

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

@clerk/testing

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

@clerk/ui

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

@clerk/upgrade

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

@clerk/vue

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

commit: 85c95c0

@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

API Changes Report

Generated by Break Check on 2026-07-29T18:24:14.730Z

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 85c95c0.

@alexcarpenter alexcarpenter changed the title feat(ui): add Mosaic Item component with StyleX styling feat(ui): add Mosaic Item component Jul 24, 2026

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

🤖 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/components/item/item.styles.ts`:
- Around line 77-87: Update the description style in the stylex.create
definition to enable the required legacy WebKit box layout alongside
WebkitLineClamp, preserving the existing two-line clamp and other styling.

In `@packages/ui/src/mosaic/components/item/item.tsx`:
- Around line 8-11: The Item public API is incomplete: add typed variant and
size props, map them to the component’s styling axes, implement the Item.Footer
slot, and assign it on the exported Item component. Update the associated tests
and documentation to cover these APIs, using the existing Item styling and slot
patterns.
🪄 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), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: b43b47ad-829e-418f-807a-8b03e013113d

📥 Commits

Reviewing files that changed from the base of the PR and between d37de13 and 45d7685.

📒 Files selected for processing (11)
  • .changeset/mosaic-item.md
  • packages/swingset/src/components/DocsViewer.tsx
  • packages/swingset/src/lib/registry.ts
  • packages/swingset/src/stories/item.mdx
  • packages/swingset/src/stories/item.stories.tsx
  • packages/ui/src/mosaic/components/item/index.ts
  • packages/ui/src/mosaic/components/item/item.styles.ts
  • packages/ui/src/mosaic/components/item/item.test.tsx
  • packages/ui/src/mosaic/components/item/item.tsx
  • packages/ui/src/mosaic/styles/index.ts
  • packages/ui/tsconfig.mosaic.json
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • clerk/clerk_go (manual)
  • clerk/dashboard (manual)
  • clerk/accounts (manual)
  • clerk/backoffice (manual)
  • clerk/clerk (manual)
  • clerk/clerk-docs (manual)
  • clerk/cloudflare-workers (manual)
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/ui/src/mosaic/components/item/index.ts
  • packages/ui/src/mosaic/styles/index.ts
  • .changeset/mosaic-item.md
  • packages/swingset/src/components/DocsViewer.tsx

Comment thread packages/ui/src/mosaic/components/item/item.styles.ts
Comment thread packages/ui/src/mosaic/components/item/item.tsx Outdated

@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 (1)
references/mosaic-architecture.md (1)

124-126: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a migration guide for the styling-contract transition.

The documentation introduces new .cl-*/data-* selectors alongside the legacy data-cl-* contract, but provides no before/after migration example. Add a short migration section explaining which selectors apply to legacy and StyleX-authored components.

As per coding guidelines, Markdown files must include migration guides for breaking changes.

🤖 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 `@references/mosaic-architecture.md` around lines 124 - 126, Add a concise
migration section near “Appearance & cascade” documenting the transition from
legacy data-cl-* selectors to the new .cl-* and data-* contract. Include a
before/after example and clearly state which selectors apply to Emotion
slot-recipe components versus StyleX-authored components, including that StyleX
uses className/style and does not read appearance.elements.

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 `@references/mosaic-architecture.md`:
- Line 9: Update the styling contract statements in the overview and API
sections to scope `.cl-<slot>` classes and `data-<axis>` attributes to
StyleX-authored parts only. Explicitly distinguish legacy slot-recipe
components, which retain the `data-cl-slot` and `data-cl-*` contract, and remove
any wording that implies every Mosaic part emits the StyleX class contract.

---

Nitpick comments:
In `@references/mosaic-architecture.md`:
- Around line 124-126: Add a concise migration section near “Appearance &
cascade” documenting the transition from legacy data-cl-* selectors to the new
.cl-* and data-* contract. Include a before/after example and clearly state
which selectors apply to Emotion slot-recipe components versus StyleX-authored
components, including that StyleX uses className/style and does not read
appearance.elements.
🪄 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), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: bb2d4296-cad5-49f0-b9e0-a57c3da0ef98

📥 Commits

Reviewing files that changed from the base of the PR and between 45d7685 and 497a792.

📒 Files selected for processing (1)
  • references/mosaic-architecture.md
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • clerk/clerk_go (manual)
  • clerk/dashboard (manual)
  • clerk/accounts (manual)
  • clerk/backoffice (manual)
  • clerk/clerk (manual)
  • clerk/clerk-docs (manual)
  • clerk/cloudflare-workers (manual)

Comment thread references/mosaic-architecture.md
The Mosaic StyleX build resolved @clerk/headless types against its published
dist .d.ts re-export barrels, which rolldown-plugin-dts can't follow when
inlining a bundled dependency. Since @clerk/headless is private and must be
inlined, map it to source in tsconfig.mosaic.json (the monorepo default, same
pattern already used for @/core/*), so Mosaic components can import headless
types directly.
Add a Mosaic `Item` component for lists of accounts, organizations, and
settings rows. Composed via dot syntax (`Item.Media`, `Item.Content`,
`Item.Title`, `Item.Description`, `Item.Actions`, `Item.Footer`,
`Item.Group`, `Item.Separator`) with `default`/`outline`/`muted` variants and
`default`/`sm` sizes. Per-slot StyleX styles compile into the shared sheet, and
a `render` prop allows an item to render as a link or button. Includes swingset
docs and stories.
- 8px padding on the row; media slot fits its child (no fixed-width variants)
- drop Item variant/size props and the Footer part
- examples use an avatar in the media slot; interactive trailing slot is 28px
The public contract is now the `.cl-<slot>` class plus `data-<axis>` attrs
emitted by `themeProps`/`mergeStyleProps`, not `data-cl-slot`. Mark the
slot-recipe engine and its `data-cl-*`/`appearance.elements` cascade as the
legacy authoring path still used by un-migrated components.

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

♻️ Duplicate comments (1)
packages/ui/src/mosaic/components/item/item.tsx (1)

16-36: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Item slots still bypass the customization contract.

Root continues to emit only themeProps/StyleX classes; no elementDescriptor is applied and it isn't wrapped through makeCustomizable, so appearance elements overrides can't consistently target this public component. This was raised previously and remains unaddressed in this revision.

As per coding guidelines, "Use element descriptors for all themable elements..." and "Wrap primitive components with makeCustomizable HOC...".

🤖 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/components/item/item.tsx` around lines 16 - 36, Update
the public Root component to use the element descriptor for its themable item
element and wrap the primitive with makeCustomizable, while preserving the
existing useRender behavior and style props. Ensure appearance elements
overrides can target MosaicItem consistently.

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/swingset/src/stories/item.stories.tsx`:
- Around line 163-169: Add an accessible name to the icon-only Button wrapping
EllipsisIcon by applying a descriptive aria-label, while preserving its existing
size, shape, and variant props.

In `@packages/ui/src/mosaic/components/item/item.tsx`:
- Around line 9-14: Update ItemProps to expose the documented variant option
alongside size and render, using the component’s existing variant values and
styling flow. Extend the exported Item object to include the implemented
Item.Footer component so both the type API and runtime exports match the
documented contract.

---

Duplicate comments:
In `@packages/ui/src/mosaic/components/item/item.tsx`:
- Around line 16-36: Update the public Root component to use the element
descriptor for its themable item element and wrap the primitive with
makeCustomizable, while preserving the existing useRender behavior and style
props. Ensure appearance elements overrides can target MosaicItem consistently.
🪄 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), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: e200c761-96cd-4bee-9267-b9c7adca058f

📥 Commits

Reviewing files that changed from the base of the PR and between d8c39c4 and d93a7fa.

📒 Files selected for processing (7)
  • packages/swingset/src/stories/item.mdx
  • packages/swingset/src/stories/item.stories.tsx
  • packages/ui/src/mosaic/components/avatar/avatar.styles.ts
  • packages/ui/src/mosaic/components/item/item.styles.ts
  • packages/ui/src/mosaic/components/item/item.test.tsx
  • packages/ui/src/mosaic/components/item/item.tsx
  • packages/ui/src/mosaic/tokens.stylex.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • clerk/clerk_go (manual)
  • clerk/dashboard (manual)
  • clerk/accounts (manual)
  • clerk/backoffice (manual)
  • clerk/clerk (manual)
  • clerk/clerk-docs (manual)
  • clerk/cloudflare-workers (manual)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/swingset/src/stories/item.mdx
  • packages/ui/src/mosaic/components/item/item.test.tsx

Comment thread packages/swingset/src/stories/item.stories.tsx Outdated
Comment thread packages/ui/src/mosaic/components/item/item.tsx
Add a shared truncationStyles set to typography.styles.ts and compose
singleLine on Item.Title and Item.Description so long labels ellipsis
instead of wrapping.
Replace the Item size prop with a variant-driven density: entity (8px)
and action (10px). Add JSDoc to every Item part and fix the Header parts'
display names.
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