22name : mosaic
33description : >-
44 Work on Mosaic UI: styling a component with StyleX (`stylex.create`, `--cl-*`
5- tokens, `themeProps`), or building a flow — authoring a state machine
6- (`setup`, states/guards/`invoke`, wiring to React with `useMachine`/`useActor`/
7- `useSelector`), writing the controller (Clerk adapter) or view (rendering) layer,
8- testing any of those layers, or migrating a legacy / pre-Mosaic component into the
9- machine / controller / view split. Use when building, styling, debugging, testing, or
10- migrating anything Mosaic. `references/mosaic-architecture.md` (repo root) holds the
11- design-system contract; this skill is the how-to layer.
5+ tokens, `themeProps`), or building a flow — writing the model (the Clerk
6+ adapter), the controller (local state, in React state or a state machine:
7+ `setup`, states/guards/`invoke`, wired to React with `useMachine`/`useActor`/
8+ `useSelector`), or the view (rendering), testing any of those layers, or
9+ migrating a legacy / pre-Mosaic component into the model / controller / view
10+ split. Use when building, styling, debugging, testing, or migrating anything
11+ Mosaic. `references/mosaic-architecture.md` (repo root) holds the design-system
12+ contract; this skill is the how-to layer.
1213---
1314
1415# Mosaic UI
@@ -19,42 +20,60 @@ Two things live under Mosaic, and this skill covers the how-to for both:
1920 the styles, ` themeProps ` emits the part's public identity (the ` .cl-<slot> `
2021 class plus ` data-<axis> ` attrs), and ` mergeStyleProps ` fuses the two with the
2122 consumer's ` className ` /` style ` .
22- - ** Flows** follow a ** machine → controller → view** split that keeps Clerk
23- resource logic out of visual components and makes behavior testable without a
24- running Clerk app:
23+ - ** Flows** follow a ** model → controller → view** split — _ where the data comes
24+ from_ → _ what the user is doing to it_ → _ what that looks like_ . What crosses
25+ each boundary is plain data: no Clerk resource reaches the controller, no
26+ machine snapshot reaches the view.
2527
2628``` text
27- machine Pure flow rules: states, events, guards, async invokes, errors.
28- No React hooks. No Clerk hooks. No Clerk resource objects.
29+ model Clerk adapter: reads Clerk hooks and resources, resolves the
30+ environment, gates permissions, and answers with plain data plus
31+ plain callbacks under an explicit `status`. The only layer that may
32+ import Clerk hooks or call Clerk resource methods.
2933
30- controller Clerk/data adapter: reads Clerk hooks/resources, injects async
31- effects into machine context, gates permissions, derives view props.
32- The only layer that may import Clerk hooks or call resource methods.
34+ controller Local state: what is open, what is in flight, what the view may do
35+ next — held in React state or a state machine, whichever the
36+ interaction's complexity calls for. Wraps the model's callbacks so
37+ an action can report pending, hold the surface still while it runs,
38+ and close on success. No Clerk imports.
3339
34- view Rendering only: receives a snapshot plus explicit props , renders UI,
35- sends events . No Clerk imports. No data-fetching. No mutations .
40+ view Rendering: takes plain props and callbacks , renders UI, calls them
41+ back . No Clerk imports. No data-fetching. No machine snapshot .
3642```
3743
44+ A machine is ** not a fourth layer** , and not a requirement. It is one of the two
45+ ways a controller can hold its state, and picking one is a complexity call:
46+ ` useState ` for a boolean that never touches async, a machine once the
47+ interaction has an async lifecycle or two values that must change together, and
48+ sometimes both in one controller. Either way the controller returns plain props,
49+ so the view cannot tell and neither can its tests. Criteria and worked
50+ before/afters: ` packages/ui/src/mosaic/machine/ADOPTION.md ` .
51+
3852` references/mosaic-architecture.md ` (repo root, read by all agents) is the
3953canonical contract for the whole design system — the ` --cl-* ` tokens, the
4054` .cl-<slot> ` + ` data-<axis> ` styling API, the CSS build, and the "Flow and data
4155architecture" section that defines the split. Read it for the _ what_ ; this skill
4256is the _ how-to_ .
4357
58+ ` packages/ui/src/mosaic/user-button/ ` is the fullest worked example of the split
59+ in the repo — model, controller, view, wrapper, types, messages, and a test per
60+ layer. Copy from it.
61+
4462## Which reference to read
4563
4664| You are… | Read |
4765| ---------------------------------------------------------------------- | ------------------------------------------------------ |
4866| Building on / authoring a headless primitive (` @clerk/headless ` ) | ` references/headless.md ` |
4967| Styling a component (tokens, ` stylex.create ` , ` themeProps ` , CSS build) | ` references/stylex.md ` |
5068| Building an enter/exit transition, or any motion that reads as wrong | ` references/motion.md ` |
69+ | Writing the model (the Clerk adapter, ` status ` , permissions) | ` references/models.md ` |
70+ | Writing the controller (local state, pending, action wrapping) | ` references/controllers.md ` |
5171| Authoring or debugging a state machine, or wiring one to React | ` references/machines.md ` → in-tree ` machine/README.md ` |
52- | Writing the controller (Clerk adapter, permissions, revalidate) | ` references/controllers.md ` |
53- | Writing the view (rendering a snapshot, sending events) | ` references/views.md ` |
54- | Testing a machine, controller, or view | ` references/testing.md ` |
72+ | Writing the view (rendering plain props) | ` references/views.md ` |
73+ | Testing a model, controller, or view | ` references/testing.md ` |
5574| Migrating a legacy component into Mosaic (the end-to-end workflow) | ` references/migration.md ` |
5675| Running the parity audit that guards a migration | ` references/parity-audit.md ` |
5776
5877The migration workflow (` migration.md ` ) ties the flow references together: it
59- treats the legacy component as the spec and drives you through the machine ,
78+ treats the legacy component as the spec and drives you through the model ,
6079controller, and view layers, then verifies parity with ` parity-audit.md ` .
0 commit comments