@nextop-os/ui-system 0.0.16 → 0.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/AGENTS.md +106 -0
  2. package/README.md +15 -10
  3. package/agent/install-skill.mjs +65 -5
  4. package/agent/nextop-ui-system/SKILL.md +145 -69
  5. package/agent/nextop-ui-system/references/extract-base-component.md +87 -0
  6. package/agent/nextop-ui-system/references/maintain-inventory.md +45 -0
  7. package/agent/nextop-ui-system/references/promote-business-component.md +238 -0
  8. package/agent/nextop-ui-system/references/use-existing-component.md +37 -0
  9. package/agent/nextop-ui-system/scripts/create-business-preview.mjs +658 -0
  10. package/dist/chunk-GE5YVRTV.js +859 -0
  11. package/dist/chunk-GE5YVRTV.js.map +1 -0
  12. package/dist/chunk-KJQ366TA.js +70 -0
  13. package/dist/chunk-KJQ366TA.js.map +1 -0
  14. package/dist/chunk-LVHEV755.js +2553 -0
  15. package/dist/chunk-LVHEV755.js.map +1 -0
  16. package/dist/components/index.d.ts +162 -11
  17. package/dist/components/index.js +62 -2
  18. package/dist/date-format.d.ts +6 -0
  19. package/dist/date-format.js +11 -0
  20. package/dist/date-format.js.map +1 -0
  21. package/dist/dev-vite.js +12 -5
  22. package/dist/dev-vite.js.map +1 -1
  23. package/dist/icons/index.d.ts +90 -46
  24. package/dist/icons/index.js +93 -11
  25. package/dist/index.d.ts +3 -2
  26. package/dist/index.js +161 -11
  27. package/dist/metadata/components.json +1331 -263
  28. package/dist/metadata/components.schema.json +4 -0
  29. package/dist/metadata/index.d.ts +3 -1
  30. package/dist/metadata/index.js +1331 -263
  31. package/dist/metadata/index.js.map +1 -1
  32. package/dist/styles/base.css +85 -0
  33. package/dist/styles/index.css +1 -0
  34. package/dist/styles/semantic.css +8 -0
  35. package/dist/styles/theme.css +94 -1
  36. package/package.json +11 -2
  37. package/ui-system.md +640 -0
  38. package/dist/chunk-5COFORA5.js +0 -1159
  39. package/dist/chunk-5COFORA5.js.map +0 -1
  40. package/dist/chunk-TT7B6HKG.js +0 -205
  41. package/dist/chunk-TT7B6HKG.js.map +0 -1
package/AGENTS.md ADDED
@@ -0,0 +1,106 @@
1
+ # AGENTS.md
2
+
3
+ ## Scope
4
+
5
+ This file applies to `packages/ui/system/*`.
6
+
7
+ `packages/ui/system` is the source package for `@nextop-os/ui-system`, the
8
+ shared Nextop UI component library. It owns shared CSS tokens, theme styles,
9
+ icon exports, presentation primitives, reusable host-agnostic business display
10
+ components, component metadata, storyboard inventory, and the bundled
11
+ `nextop-ui-system` agent skill.
12
+
13
+ Before changing components, icons, metadata, styles, storyboard examples, or
14
+ the bundled skill, read `ui-system.md`.
15
+
16
+ UI-system design compliance is a release gate for this package, not a follow-up
17
+ task. If a promoted component does not yet follow the shared token model,
18
+ surface language, primitive vocabulary, and storyboard evidence standard, do
19
+ not report it as complete.
20
+
21
+ ## Public API
22
+
23
+ Stable public imports are:
24
+
25
+ - `@nextop-os/ui-system`
26
+ - `@nextop-os/ui-system/components`
27
+ - `@nextop-os/ui-system/metadata`
28
+ - `@nextop-os/ui-system/icons`
29
+ - `@nextop-os/ui-system/styles.css`
30
+ - `@nextop-os/ui-system/utils`
31
+
32
+ Rules:
33
+
34
+ - prefer adding exports to an existing public barrel before introducing a new
35
+ public subpath
36
+ - do not expose `src/*` layout as public API
37
+ - do not encourage per-file deep imports such as
38
+ `@nextop-os/ui-system/components/button`
39
+ - if package exports change intentionally, update both the package exports and
40
+ the UI-boundary check script
41
+
42
+ ## Component Library Rules
43
+
44
+ - keep `base` components low-level, generic, and
45
+ frontend-foundation-focused
46
+ - allow `business` components only when they are reusable business display
47
+ components that remain host-agnostic and side-effect-free
48
+ - business components may expose domain display props such as workspace, file,
49
+ task, agent, status, permission, and callbacks, but must not own daemon,
50
+ Electron, router, store, query, filesystem, persistence, or workflow calls
51
+ - before promoting a business component, scan source usage, build a
52
+ code-evidence state matrix, and define the public props boundary from that
53
+ evidence; after that, promote it directly into `packages/ui/system` and add
54
+ storyboard coverage for the accepted states
55
+ - business components should compose `base` primitives instead of recreating
56
+ buttons, fields, dialogs, cards, icons, or overlays
57
+ - promoted components and their storyboard examples must use UI-system semantic
58
+ tokens and approved shared CSS variables; do not leave raw `hex`,
59
+ `rgb(...)`, `rgba(...)`, ad hoc gradients, or app-local palette values in the
60
+ final UI-system implementation unless they already come from approved shared
61
+ tokens
62
+ - storyboard coverage must show the component's real promoted surface and
63
+ states; do not rely on surrounding docs chrome or wrapper panels to mask
64
+ component-level visual drift
65
+ - UI storyboard foundation content is JSON-driven. When changing documented
66
+ token, color, typography, spacing, radius, motion, or overview display data,
67
+ edit `apps/ui-storyboard/src/foundation/*.json` directly instead of
68
+ hardcoding those values in `apps/ui-storyboard/src/App.tsx`
69
+ - migrated consumers must end on the same UI-system visual implementation for
70
+ the promoted surface; temporary bridges are allowed only for wiring, not as a
71
+ separate long-lived token or styling system
72
+ - treat this package as the shared shadcn and Radix host package
73
+ - when a primitive exists in the shadcn registry, acquire it through shadcn CLI
74
+ targeted at this package instead of handwriting the component body
75
+ - keep `components.json` and package aliases usable enough that CLI download
76
+ remains the default path for shared primitives
77
+ - after CLI acquisition, limit edits to narrow package-specific adaptation such
78
+ as icon routing, import aliases, stable exports, and boundary-check fixes
79
+ - keep CSS variables as the source of truth for token values
80
+ - prefer semantic token naming over raw palette leakage in public APIs
81
+ - keep helper exports minimal and tied to primitive support, not general
82
+ convenience reuse
83
+ - build primitives for a calm workbench shell, not for marketing-card theatrics
84
+ - every public component, icon, utility, or style entry must have metadata with
85
+ a stable readable `id` and `layer`
86
+ - use the single `nextop-ui-system` skill for component reuse, extraction,
87
+ base/business classification, metadata, and storyboard work
88
+
89
+ ## Validation
90
+
91
+ - Run `pnpm typecheck`
92
+ - Run `pnpm check:ui-boundaries`
93
+ - If component metadata changed, run `node tools/scripts/check-ui-metadata.mjs`
94
+ - If storyboard inventory changed, run
95
+ `pnpm --filter @nextop-os/ui-storyboard typecheck`
96
+ - If a change affects desktop integration, also run
97
+ `pnpm --filter @nextop-os/desktop build`
98
+ - In the handoff, explicitly state whether tokens, primitives, storyboard
99
+ surface, and migrated consumer all comply with the UI-system standard; if any
100
+ of those are still divergent, the work is not complete
101
+
102
+ ## Related Docs
103
+
104
+ - `ui-system.md`
105
+ - `docs/conventions/desktop-visual-language.md`
106
+ - `docs/conventions/local-git-hooks.md`
package/README.md CHANGED
@@ -38,9 +38,9 @@ export default defineConfig({
38
38
  ```
39
39
 
40
40
  When the dev server is reachable, the plugin mirrors the allowed UI-system
41
- source files into `.nextop-ui-system-dev/` and aliases the stable package
42
- entrypoints to that cache. When the dev server is unavailable, resolution falls
43
- back to the installed package in `node_modules`.
41
+ source and skill-support files into `.nextop-ui-system-dev/` and aliases the
42
+ stable package entrypoints to that cache. When the dev server is unavailable,
43
+ resolution falls back to the installed package in `node_modules`.
44
44
 
45
45
  Add the generated cache to the external app's `.gitignore`:
46
46
 
@@ -65,15 +65,18 @@ import { uiSystemMetadata } from "@nextop-os/ui-system/metadata";
65
65
  ```
66
66
 
67
67
  When promoting business UI into this package, use the bundled
68
- `agent/nextop-ui-system/SKILL.md` skill when it is available. The durable rules
69
- are:
68
+ `agent/nextop-ui-system/SKILL.md` skill when it is available. In the source
69
+ checkout, also read `AGENTS.md`, `ui-system.md`, and
70
+ `docs/conventions/desktop-visual-language.md`. The durable rules are:
70
71
 
71
72
  1. prefer existing metadata entries before creating a component
72
73
  2. classify the component as `base` or `business`
73
74
  3. keep business components host-agnostic and side-effect-free
74
- 4. compose business components from base primitives
75
- 5. add metadata, stable exports, and storyboard examples for public UI
76
- 6. run metadata and boundary validation before shipping
75
+ 4. before promoting a business component, scan source usage and define the
76
+ public props boundary from code evidence
77
+ 5. compose business components from base primitives
78
+ 6. add metadata, stable exports, and storyboard examples for public UI
79
+ 7. run metadata and boundary validation before shipping
77
80
 
78
81
  External repositories can install the bundled skill into their local Codex
79
82
  skill directory with one command:
@@ -88,5 +91,7 @@ This copies the package skill into:
88
91
  .codex/skills/nextop-ui-system/SKILL.md
89
92
  ```
90
93
 
91
- The installer does not overwrite a locally modified skill unless `--force` is
92
- provided.
94
+ When `.nextop-ui-system-dev/` is present, the installer prefers the synced
95
+ source checkout so the installed skill and bundled UI-system rules stay aligned
96
+ with the current local UI-system source. The installer does not overwrite a
97
+ locally modified skill unless `--force` is provided.
@@ -14,8 +14,9 @@ import { dirname, join, relative, resolve } from "node:path";
14
14
  import { fileURLToPath } from "node:url";
15
15
 
16
16
  const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)));
17
- const sourceDirectory = join(packageRoot, "agent", "nextop-ui-system");
18
17
  const skillName = "nextop-ui-system";
18
+ const devCacheDirectoryName = ".nextop-ui-system-dev";
19
+ const companionFiles = ["AGENTS.md", "ui-system.md"];
19
20
 
20
21
  const options = parseArgs(process.argv.slice(2));
21
22
 
@@ -26,8 +27,15 @@ if (options.help) {
26
27
 
27
28
  const targetRoot = resolve(options.cwd, ".codex", "skills");
28
29
  const targetDirectory = join(targetRoot, skillName);
30
+ const sourceRoot = await resolveSourceRoot(options.cwd);
31
+ const sourceDirectory = join(sourceRoot, "agent", skillName);
29
32
 
30
33
  await assertReadableDirectory(sourceDirectory);
34
+ await Promise.all(
35
+ companionFiles.map((fileName) =>
36
+ assertReadableFile(join(sourceRoot, fileName))
37
+ )
38
+ );
31
39
  await mkdir(targetRoot, { recursive: true });
32
40
 
33
41
  if (await pathExists(targetDirectory)) {
@@ -38,7 +46,7 @@ if (await pathExists(targetDirectory)) {
38
46
  }
39
47
 
40
48
  if (!options.force) {
41
- if (await directoriesMatch(sourceDirectory, targetDirectory)) {
49
+ if (await directoriesMatch(sourceRoot, sourceDirectory, targetDirectory)) {
42
50
  console.log(
43
51
  `nextop-ui-system skill already configured at ${targetDirectory}`
44
52
  );
@@ -59,6 +67,15 @@ await cp(sourceDirectory, targetDirectory, {
59
67
  force: true,
60
68
  recursive: true
61
69
  });
70
+ await Promise.all(
71
+ companionFiles.map((fileName) =>
72
+ cp(join(sourceRoot, fileName), join(targetDirectory, fileName), {
73
+ errorOnExist: false,
74
+ force: true,
75
+ recursive: false
76
+ })
77
+ )
78
+ );
62
79
 
63
80
  console.log(`Installed nextop-ui-system skill to ${targetDirectory}`);
64
81
  console.log(
@@ -121,6 +138,15 @@ async function assertReadableDirectory(path) {
121
138
  }
122
139
  }
123
140
 
141
+ async function assertReadableFile(path) {
142
+ await access(path, constants.R_OK);
143
+ const pathStats = await stat(path);
144
+
145
+ if (!pathStats.isFile()) {
146
+ throw new Error(`Expected file: ${path}`);
147
+ }
148
+ }
149
+
124
150
  async function pathExists(path) {
125
151
  try {
126
152
  await access(path, constants.F_OK);
@@ -130,8 +156,24 @@ async function pathExists(path) {
130
156
  }
131
157
  }
132
158
 
133
- async function directoriesMatch(leftDirectory, rightDirectory) {
134
- const leftEntries = await listFiles(leftDirectory, leftDirectory);
159
+ async function resolveSourceRoot(cwd) {
160
+ const devCacheRoot = resolve(cwd, devCacheDirectoryName);
161
+ const devCacheSkillDirectory = join(devCacheRoot, "agent", skillName);
162
+
163
+ if (
164
+ (await pathExists(devCacheSkillDirectory)) &&
165
+ (await pathExists(join(devCacheRoot, "AGENTS.md"))) &&
166
+ (await pathExists(join(devCacheRoot, "ui-system.md")))
167
+ ) {
168
+ return devCacheRoot;
169
+ }
170
+
171
+ return packageRoot;
172
+ }
173
+
174
+ async function directoriesMatch(sourceRoot, sourceDirectory, rightDirectory) {
175
+ const sourceEntries = await listBundleFiles(sourceRoot, sourceDirectory);
176
+ const leftEntries = sourceEntries.map((entry) => entry.targetRelativePath);
135
177
  const rightEntries = await listFiles(rightDirectory, rightDirectory);
136
178
 
137
179
  if (leftEntries.length !== rightEntries.length) {
@@ -143,7 +185,7 @@ async function directoriesMatch(leftDirectory, rightDirectory) {
143
185
  return false;
144
186
  }
145
187
 
146
- const leftFile = join(leftDirectory, leftEntries[index]);
188
+ const leftFile = sourceEntries[index].sourceAbsolutePath;
147
189
  const rightFile = join(rightDirectory, rightEntries[index]);
148
190
 
149
191
  const [leftContent, rightContent] = await Promise.all([
@@ -159,6 +201,24 @@ async function directoriesMatch(leftDirectory, rightDirectory) {
159
201
  return true;
160
202
  }
161
203
 
204
+ async function listBundleFiles(sourceRoot, sourceDirectory) {
205
+ const skillFiles = await listFiles(sourceDirectory, sourceDirectory);
206
+ const companionEntries = companionFiles.map((fileName) => ({
207
+ sourceAbsolutePath: join(sourceRoot, fileName),
208
+ targetRelativePath: fileName
209
+ }));
210
+
211
+ return skillFiles
212
+ .map((relativePath) => ({
213
+ sourceAbsolutePath: join(sourceDirectory, relativePath),
214
+ targetRelativePath: relativePath
215
+ }))
216
+ .concat(companionEntries)
217
+ .sort((left, right) =>
218
+ left.targetRelativePath.localeCompare(right.targetRelativePath)
219
+ );
220
+ }
221
+
162
222
  async function listFiles(rootDirectory, directory) {
163
223
  const entries = await readdir(directory, { withFileTypes: true });
164
224
  const files = await Promise.all(
@@ -1,20 +1,45 @@
1
1
  ---
2
2
  name: nextop-ui-system
3
- description: Use when working with @nextop-os/ui-system components, replacing local UI with shared components, querying component ids or metadata, promoting business UI into shared base or business components, or maintaining UI-system storyboard inventory.
3
+ description: Use when working with @nextop-os/ui-system components, replacing local UI with shared components, querying component ids or metadata, promoting UI into shared base or business components, or maintaining UI-system storyboard inventory.
4
4
  ---
5
5
 
6
6
  # Nextop UI System
7
7
 
8
- Use this skill as the single entrypoint for `@nextop-os/ui-system` use,
9
- promotion, metadata, and storyboard work.
8
+ Use this skill as the single entrypoint for `@nextop-os/ui-system` component
9
+ reuse, extraction, promotion, metadata, and storyboard work.
10
+
11
+ ## Non-Negotiable Standard
12
+
13
+ Any UI promoted into `@nextop-os/ui-system` must fully follow the UI-system
14
+ design standard before it can be reported as complete.
15
+
16
+ Treat these as hard requirements, not cleanup suggestions:
17
+
18
+ - use UI-system semantic tokens and existing shared CSS variables; do not leave
19
+ raw `hex`, `rgb(...)`, `rgba(...)`, ad hoc gradients, or app-local palette
20
+ values in promoted components or their storyboard examples unless the source
21
+ of truth already exposes them as approved tokens
22
+ - compose existing UI-system `base` primitives such as `Card`, `Button`,
23
+ `Tooltip`, `Dialog`, and related vocabulary before creating custom panel,
24
+ button, field, or overlay treatments
25
+ - make storyboard examples render the real component surface and states; do not
26
+ rely on surrounding docs chrome to hide component-level visual drift or to
27
+ fake the final panel/surface language
28
+ - when a consumer is migrated, its final rendered result must also follow the
29
+ same UI-system visual standard; a temporary bridge may help wiring, but it is
30
+ not acceptable as the final visual implementation if it keeps a second token
31
+ system or divergent component styling
32
+
33
+ If these conditions are not met, report the promotion as incomplete or blocked,
34
+ not complete.
10
35
 
11
36
  ## Source Of Truth
12
37
 
13
38
  Read these before editing:
14
39
 
15
40
  1. nearest `AGENTS.md` for the target code
16
- 2. `packages/ui/AGENTS.md`
17
- 3. `docs/conventions/ui-system.md`
41
+ 2. local `AGENTS.md` bundled with this skill
42
+ 3. local `ui-system.md` bundled with this skill
18
43
  4. component metadata from the first available source:
19
44
  - `GET http://127.0.0.1:4100/components`
20
45
  - `packages/ui/system/src/metadata/components.json`
@@ -33,76 +58,120 @@ Never deep import `@nextop-os/ui-system/src/*` or per-file component paths.
33
58
 
34
59
  ## Route The Task
35
60
 
36
- ### Use Existing Component
37
-
38
- Use when replacing local UI or answering what components exist.
39
-
40
- 1. Check metadata first by `id`, `name`, `export`, `layer`, and `useCases`.
41
- 2. Prefer existing components before creating or extracting new ones.
42
- 3. Read the source and props type for the selected export.
43
- 4. Keep host state, data loading, routing, daemon calls, i18n keys, and business
44
- transforms in the caller.
45
- 5. Replace only the visual surface with stable UI-system imports.
46
-
47
- ### Extract Base Component
48
-
49
- Use when the target is a low-level visual primitive.
50
-
51
- Proceed only if the public API has no domain noun and props describe
52
- presentation, interaction, accessibility, variants, refs, slots, class names, or
53
- children.
54
-
55
- 1. If the primitive exists in shadcn, acquire it through shadcn CLI targeted at
56
- `packages/ui/system`.
57
- 2. Adapt only package aliases, icons, tokens, exports, and boundary issues.
58
- 3. Add stable exports, metadata with `layer: "base"`, and storyboard coverage.
59
- 4. Replace duplicated local UI with the shared component.
61
+ Read only the reference file that matches the task.
60
62
 
61
- ### Extract Business Component
63
+ - Using or querying existing components:
64
+ `references/use-existing-component.md`
65
+ - Extracting a low-level base primitive:
66
+ `references/extract-base-component.md`
67
+ - Promoting reusable business UI into a shared component:
68
+ `references/promote-business-component.md`
69
+ - Maintaining ids, metadata, exports, or storyboard inventory:
70
+ `references/maintain-inventory.md`
62
71
 
63
- Use when business-side UI should become a reusable display component.
72
+ ## Global Boundaries
64
73
 
65
- Proceed only if the component can render from props with no host side effects.
66
- Business components may expose domain display props such as workspace, file,
67
- task, agent, run, status, permission, labels, and callbacks.
68
-
69
- Before editing, state:
70
-
71
- - component `id` and `layer`
72
- - source usage being replaced
73
- - intended reuse surfaces
74
- - public props and callbacks
75
- - host-owned state and side effects that remain outside the component
76
- - export path, metadata entry, storyboard states, and validation commands
77
-
78
- Keep these outside the component:
74
+ Keep these outside `@nextop-os/ui-system` components:
79
75
 
80
76
  - daemon, Electron, filesystem, router, or host adapter calls
81
77
  - data fetching, cache mutation, persistence, polling, and global store
82
78
  ownership
83
- - workflow orchestration such as onboarding, workspace registration, or
84
- navigation
85
-
86
- Implement the business component by composing `base` primitives. Add metadata
87
- with `layer: "business"` and storyboard examples for normal, empty, disabled,
88
- loading, and error-like states when those states exist in the public contract.
89
-
90
- ### Maintain Inventory
91
-
92
- Use when changing component ids, metadata, exports, or storyboard.
93
-
94
- 1. Keep each public entry's `id` stable, readable, globally unique, and
95
- kebab-case.
96
- 2. Keep `layer` as `base` or `business`.
97
- 3. Ensure `source` points under `packages/ui/system/src`.
98
- 4. Ensure `from` is a stable public entrypoint.
99
- 5. Keep storyboard grouped by `Foundation`, `Base Components`, and
100
- `Business Components`; visible component stories should support copying the
101
- component id.
102
-
103
- ## Validation
104
-
105
- Run the smallest relevant checks, then report exact commands and results:
79
+ - workflow orchestration such as onboarding, workspace registration, install or
80
+ uninstall flows, confirmation dialogs, queueing, or navigation
81
+ - i18n key lookup and business-specific copy derivation unless supplied by
82
+ props, children, or labels
83
+
84
+ For any promoted public component, add stable exports, metadata, and storyboard
85
+ coverage that match the chosen reference workflow.
86
+
87
+ For promoted base components, storyboard coverage is not satisfied by metadata
88
+ alone. The promotion flow must also add or update a real renderable example in
89
+ `apps/ui-storyboard` so the component is visible in navigation and can be
90
+ visually reviewed in shared docs immediately after promotion.
91
+
92
+ For business component promotion, derive the promoted component directly from
93
+ the state matrix, proposed props boundary, and candidate source UI, then add
94
+ storyboard coverage for the accepted states in the same promotion pass. Treat
95
+ that evidence and boundary decision as the implementation blueprint for
96
+ `packages/ui/system`, and use review only to verify the finished implementation.
97
+
98
+ ## Design Foundation Verification
99
+
100
+ Every promoted component must comply with
101
+ `ui-system.md`, especially the shared tokens,
102
+ theme variables, spacing, radius, typography, surface language, interactive
103
+ states, and existing `base` primitive vocabulary.
104
+
105
+ Explicitly check and report all of these before completion:
106
+
107
+ - color and surface styling come from UI-system semantic tokens rather than raw
108
+ palette values
109
+ - panels, rows, controls, and overlays compose existing base primitives where
110
+ applicable instead of recreating them locally
111
+ - storyboard shows the component's real promoted surface rather than only a
112
+ documentation wrapper
113
+ - migrated consumers no longer depend on a separate visual token system for the
114
+ promoted surface
115
+
116
+ Run the Nextop promotion review gate before reporting completion. The gate is
117
+ adapted from frontend design review practice but constrained to Nextop's dense
118
+ workbench product language:
119
+
120
+ - Frictionless: the migrated consumer preserves the original task path, keeps a
121
+ clear action hierarchy, and does not bury primary or recovery actions.
122
+ - Quality craft: visual parity evidence is captured for selected states, shared
123
+ tokens and primitives are used, light/dark and interactive states work, and no
124
+ unapproved raw palette, spacing, radius, typography, or motion drift remains.
125
+ - Trustworthy: empty, loading, disabled, error-like, permission-limited, and
126
+ AI-generated-content states keep clear labels, actionable recovery, and
127
+ host-owned policy or provenance outside the shared component.
128
+
129
+ After promoting a base or business component, start an independent subagent to
130
+ review design-foundation compliance before reporting completion. Provide the
131
+ subagent with the promoted files, source usage, selected states, storyboard and
132
+ metadata entries, and the UI-system guidelines. If subagents are unavailable,
133
+ state that design-foundation verification is blocked and do not claim full
134
+ compliance.
135
+
136
+ Report the gate result with:
137
+
138
+ - context: source usage, promoted component id/layer, user task, selected states
139
+ - status: pass, needs work, or blocked
140
+ - pillar assessment: Frictionless, Quality craft, Trustworthy
141
+ - issues grouped as blocking, major, and minor
142
+ - validation commands and exact results
143
+ - remaining risks, uncovered states, or approved visual deltas
144
+
145
+ ## API Composition Review
146
+
147
+ When converting source states into public props, review the API shape before
148
+ writing the promoted component:
149
+
150
+ - avoid boolean prop proliferation for rendering modes; mode axes such as
151
+ `isFoo`, `showBar`, or `withBaz` must come from code evidence and usually
152
+ become a finite variant, discriminated union, explicit component variant,
153
+ slot, or composed child
154
+ - keep standard UI booleans such as `disabled`, `loading`, `selected`, `open`,
155
+ `required`, and `invalid` only when they represent real component state and
156
+ cannot create impossible combinations
157
+ - prefer `children` or named slots for caller-owned visual regions; use render
158
+ props only when the shared component must pass data back to the caller
159
+ - use compound components and context only for genuinely complex reusable
160
+ structures where consumers need to compose subparts without prop drilling
161
+ - if shared state is needed, define a narrow context value as `state`,
162
+ `actions`, and `meta`; providers may inject state but must not own daemon,
163
+ Electron, router, store, query, persistence, or workflow side effects
164
+ - for new React components in this React 19 codebase, prefer the React 19 API
165
+ shape such as `ref` as a prop; do not churn shadcn or Radix-acquired code only
166
+ to normalize style when behavior and public API are already sound
167
+
168
+ Report the API composition decision with the state matrix: which differences
169
+ became props, variants, slots, children, explicit variants, provider state, or
170
+ stayed host-owned.
171
+
172
+ ## Validation Commands
173
+
174
+ Run the smallest relevant checks from the selected reference. Common checks are:
106
175
 
107
176
  ```bash
108
177
  node tools/scripts/check-ui-metadata.mjs
@@ -111,4 +180,11 @@ pnpm --filter @nextop-os/ui-storyboard typecheck
111
180
  ```
112
181
 
113
182
  If runtime component code changed, also run the relevant package typecheck or
114
- build for the consumer that was migrated.
183
+ consumer build.
184
+
185
+ When a base component is promoted, verify both of these conditions before
186
+ reporting completion:
187
+
188
+ - the component metadata opts into storyboard visibility when appropriate
189
+ - `apps/ui-storyboard` contains a concrete rendered example for the promoted
190
+ component states, not just inventory wiring
@@ -0,0 +1,87 @@
1
+ # Extract Base Component
2
+
3
+ Use this reference when the target is a low-level visual primitive.
4
+
5
+ ## Base Criteria
6
+
7
+ Proceed only if the public API has no domain noun and props describe generic UI
8
+ concerns:
9
+
10
+ - presentation and variants
11
+ - interaction and accessibility
12
+ - refs, slots, class names, and children
13
+ - controlled or uncontrolled primitive state
14
+
15
+ If the component represents a workspace, file, task, agent, run, project,
16
+ account, or other business concept, use `promote-business-component.md`
17
+ instead.
18
+
19
+ ## Workflow
20
+
21
+ 1. Check metadata and existing exports first.
22
+ 2. Read the bundled `ui-system.md` before implementation and
23
+ treat it as a hard gate for the extraction. The component must follow the
24
+ shared token, theme variable, spacing, radius, typography, surface,
25
+ interactive-state, accessibility, and reduced-motion rules from
26
+ `@nextop-os/ui-system`; do not preserve or introduce caller-local styling
27
+ when it conflicts with those guidelines.
28
+ 3. If the primitive exists in the shadcn registry, acquire it through shadcn CLI
29
+ targeted at `packages/ui/system`.
30
+ 4. Decide the primitive API before editing:
31
+ - use finite variants or discriminated unions for mutually exclusive visual
32
+ modes
33
+ - keep standard UI booleans such as `disabled`, `loading`, `selected`,
34
+ `open`, `required`, and `invalid` only when they represent real states
35
+ - prefer `children`, slots, refs, and class names for composition instead
36
+ of broad render props
37
+ - use compound components or context only when consumers need to assemble
38
+ reusable subparts that share primitive state
39
+ - follow the React 19 baseline for new hand-authored components, but do not
40
+ rewrite shadcn or Radix internals only for API-style churn
41
+ 5. Adapt only package aliases, icon routing, tokens, stable exports, metadata,
42
+ storyboard examples, and boundary-check issues.
43
+ 6. Keep helper exports minimal and directly tied to primitive support.
44
+ 7. Add metadata with `layer: "base"`.
45
+ 8. Add storyboard coverage for the public states and variants exposed by the
46
+ primitive.
47
+ - This is mandatory for base-component promotion.
48
+ - Do not treat `storyboard: true` in metadata as sufficient by itself.
49
+ - Add or update a real renderable example in `apps/ui-storyboard` so the
50
+ component appears in navigation and can be visually reviewed immediately.
51
+ 9. Replace duplicated local UI only after the shared primitive exists.
52
+ 10. Run the promotion review gate from
53
+ `ui-system.md`: verify Frictionless task
54
+ preservation, Quality Craft visual/token/state parity, and Trustworthy
55
+ status/error/accessibility behavior for the migrated consumer.
56
+ 11. Start an independent design-foundation review subagent after promotion. The
57
+ review must check the promoted files against
58
+ `ui-system.md`, existing tokens, primitives,
59
+ API shape, storyboard coverage, and metadata. Resolve any reported design
60
+ drift before completion.
61
+
62
+ ## Validation
63
+
64
+ Run the relevant checks:
65
+
66
+ ```bash
67
+ node tools/scripts/check-ui-metadata.mjs
68
+ pnpm check:ui-boundaries
69
+ pnpm --filter @nextop-os/ui-storyboard typecheck
70
+ pnpm --filter @nextop-os/ui-system typecheck
71
+ ```
72
+
73
+ If a consumer was migrated, also run that consumer's typecheck or build.
74
+
75
+ Before reporting completion, confirm storyboard delivery at two levels:
76
+
77
+ - inventory: the component is discoverable from storyboard navigation
78
+ - rendering: the component has a concrete example that renders its public
79
+ states or variants inside `apps/ui-storyboard`
80
+
81
+ Do not report full design-foundation compliance unless the subagent review ran
82
+ and found no unresolved drift. If subagents are unavailable, report the
83
+ verification as blocked.
84
+
85
+ Report the promotion review result with the component id, selected states,
86
+ Frictionless / Quality Craft / Trustworthy pillar status, blocking/major/minor
87
+ issues, validation commands, and remaining risks or approved visual deltas.
@@ -0,0 +1,45 @@
1
+ # Maintain Inventory
2
+
3
+ Use this reference when changing component ids, metadata, exports, or storyboard
4
+ inventory without promoting a new component.
5
+
6
+ ## Metadata Rules
7
+
8
+ Every public UI-system entry must have metadata with:
9
+
10
+ - stable readable `id`
11
+ - globally unique kebab-case id
12
+ - `layer` as `base` or `business`
13
+ - `source` under `packages/ui/system/src`
14
+ - stable public `from` entrypoint
15
+
16
+ Do not expose `src/*` layout as public API and do not encourage per-file deep
17
+ imports.
18
+
19
+ ## Storyboard Rules
20
+
21
+ Keep storyboard grouped by:
22
+
23
+ - `Foundation`
24
+ - `Base Components`
25
+ - `Business Components`
26
+
27
+ Visible component stories should support copying the component id.
28
+
29
+ When a base component is newly promoted into `@nextop-os/ui-system`, updating
30
+ inventory alone is not enough. The same change must also add or refresh a real
31
+ renderable example in `apps/ui-storyboard` so the promoted component is
32
+ immediately reviewable from the shared storyboard.
33
+
34
+ When changing metadata or storyboard inventory, keep ids stable unless the
35
+ rename is intentional and callers or docs are updated together.
36
+
37
+ ## Validation
38
+
39
+ Run the relevant checks:
40
+
41
+ ```bash
42
+ node tools/scripts/check-ui-metadata.mjs
43
+ pnpm check:ui-boundaries
44
+ pnpm --filter @nextop-os/ui-storyboard typecheck
45
+ ```