@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.
- package/AGENTS.md +106 -0
- package/README.md +15 -10
- package/agent/install-skill.mjs +65 -5
- package/agent/nextop-ui-system/SKILL.md +145 -69
- package/agent/nextop-ui-system/references/extract-base-component.md +87 -0
- package/agent/nextop-ui-system/references/maintain-inventory.md +45 -0
- package/agent/nextop-ui-system/references/promote-business-component.md +238 -0
- package/agent/nextop-ui-system/references/use-existing-component.md +37 -0
- package/agent/nextop-ui-system/scripts/create-business-preview.mjs +658 -0
- package/dist/chunk-GE5YVRTV.js +859 -0
- package/dist/chunk-GE5YVRTV.js.map +1 -0
- package/dist/chunk-KJQ366TA.js +70 -0
- package/dist/chunk-KJQ366TA.js.map +1 -0
- package/dist/chunk-LVHEV755.js +2553 -0
- package/dist/chunk-LVHEV755.js.map +1 -0
- package/dist/components/index.d.ts +162 -11
- package/dist/components/index.js +62 -2
- package/dist/date-format.d.ts +6 -0
- package/dist/date-format.js +11 -0
- package/dist/date-format.js.map +1 -0
- package/dist/dev-vite.js +12 -5
- package/dist/dev-vite.js.map +1 -1
- package/dist/icons/index.d.ts +90 -46
- package/dist/icons/index.js +93 -11
- package/dist/index.d.ts +3 -2
- package/dist/index.js +161 -11
- package/dist/metadata/components.json +1331 -263
- package/dist/metadata/components.schema.json +4 -0
- package/dist/metadata/index.d.ts +3 -1
- package/dist/metadata/index.js +1331 -263
- package/dist/metadata/index.js.map +1 -1
- package/dist/styles/base.css +85 -0
- package/dist/styles/index.css +1 -0
- package/dist/styles/semantic.css +8 -0
- package/dist/styles/theme.css +94 -1
- package/package.json +11 -2
- package/ui-system.md +640 -0
- package/dist/chunk-5COFORA5.js +0 -1159
- package/dist/chunk-5COFORA5.js.map +0 -1
- package/dist/chunk-TT7B6HKG.js +0 -205
- 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
|
|
42
|
-
entrypoints to that cache. When the dev server is unavailable,
|
|
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.
|
|
69
|
-
|
|
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.
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
92
|
-
|
|
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.
|
package/agent/install-skill.mjs
CHANGED
|
@@ -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
|
|
134
|
-
const
|
|
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 =
|
|
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
|
|
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`
|
|
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. `
|
|
17
|
-
3. `
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
72
|
+
## Global Boundaries
|
|
64
73
|
|
|
65
|
-
|
|
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
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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
|
-
|
|
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
|
+
```
|