@tutti-os/ui-system 0.0.1
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 +146 -0
- package/LICENSE +202 -0
- package/README.md +97 -0
- package/agent/install-skill.mjs +241 -0
- package/agent/nextop-ui-system/SKILL.md +227 -0
- 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 +316 -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-2AUYRRDG.js +3078 -0
- package/dist/chunk-2AUYRRDG.js.map +1 -0
- package/dist/chunk-DGPY4WP3.js +11 -0
- package/dist/chunk-DGPY4WP3.js.map +1 -0
- package/dist/chunk-GX3U3V36.js +70 -0
- package/dist/chunk-GX3U3V36.js.map +1 -0
- package/dist/chunk-UTUVPSKL.js +873 -0
- package/dist/chunk-UTUVPSKL.js.map +1 -0
- package/dist/chunk-XHA7R2WC.js +292 -0
- package/dist/chunk-XHA7R2WC.js.map +1 -0
- package/dist/components/index.d.ts +360 -0
- package/dist/components/index.js +221 -0
- package/dist/components/index.js.map +1 -0
- 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.d.ts +9 -0
- package/dist/dev-vite.js +583 -0
- package/dist/dev-vite.js.map +1 -0
- package/dist/icons/index.d.ts +112 -0
- package/dist/icons/index.js +191 -0
- package/dist/icons/index.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +419 -0
- package/dist/index.js.map +1 -0
- package/dist/metadata/components.json +2819 -0
- package/dist/metadata/components.schema.json +110 -0
- package/dist/metadata/index.d.ts +27 -0
- package/dist/metadata/index.js +2827 -0
- package/dist/metadata/index.js.map +1 -0
- package/dist/styles/base.css +170 -0
- package/dist/styles/index.css +4 -0
- package/dist/styles/semantic.css +50 -0
- package/dist/styles/theme.css +366 -0
- package/dist/utils.d.ts +5 -0
- package/dist/utils.js +7 -0
- package/dist/utils.js.map +1 -0
- package/package.json +118 -0
- package/ui-system.md +671 -0
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nextop-ui-system
|
|
3
|
+
description: Use when working with @tutti-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
|
+
---
|
|
5
|
+
|
|
6
|
+
# Nextop UI System
|
|
7
|
+
|
|
8
|
+
Use this skill as the single entrypoint for `@tutti-os/ui-system` component
|
|
9
|
+
reuse, extraction, promotion, metadata, and storyboard work.
|
|
10
|
+
|
|
11
|
+
## Non-Negotiable Standard
|
|
12
|
+
|
|
13
|
+
Any UI promoted into `@tutti-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
|
+
- use icon components from `@tutti-os/ui-system/icons` for promoted
|
|
26
|
+
components and storyboard examples. Do not inline SVG/data URI assets, import
|
|
27
|
+
app-local icon files, or pull third-party icon packages directly from promoted
|
|
28
|
+
UI. If the source UI depends on an icon that is not in the UI system, promote
|
|
29
|
+
the source-derived icon into `packages/ui/system/src/icons` with metadata
|
|
30
|
+
first, then consume the UI-system icon export.
|
|
31
|
+
- make storyboard examples render the real component surface and states; do not
|
|
32
|
+
rely on surrounding docs chrome to hide component-level visual drift or to
|
|
33
|
+
fake the final panel/surface language
|
|
34
|
+
- when a consumer is migrated, its final rendered result must also follow the
|
|
35
|
+
same UI-system visual standard; a temporary bridge may help wiring, but it is
|
|
36
|
+
not acceptable as the final visual implementation if it keeps a second token
|
|
37
|
+
system or divergent component styling
|
|
38
|
+
|
|
39
|
+
If these conditions are not met, report the promotion as incomplete or blocked,
|
|
40
|
+
not complete.
|
|
41
|
+
|
|
42
|
+
## Source Of Truth
|
|
43
|
+
|
|
44
|
+
Read these before editing:
|
|
45
|
+
|
|
46
|
+
1. nearest `AGENTS.md` for the target code
|
|
47
|
+
2. local `AGENTS.md` bundled with this skill
|
|
48
|
+
3. local `ui-system.md` bundled with this skill
|
|
49
|
+
4. component metadata from the first available source:
|
|
50
|
+
- `GET http://127.0.0.1:4100/components`
|
|
51
|
+
- `packages/ui/system/src/metadata/components.json`
|
|
52
|
+
- `@tutti-os/ui-system/metadata` from the installed package
|
|
53
|
+
|
|
54
|
+
Use stable public imports only:
|
|
55
|
+
|
|
56
|
+
- `@tutti-os/ui-system`
|
|
57
|
+
- `@tutti-os/ui-system/components`
|
|
58
|
+
- `@tutti-os/ui-system/icons`
|
|
59
|
+
- `@tutti-os/ui-system/metadata`
|
|
60
|
+
- `@tutti-os/ui-system/styles.css`
|
|
61
|
+
- `@tutti-os/ui-system/utils`
|
|
62
|
+
|
|
63
|
+
Never deep import `@tutti-os/ui-system/src/*` or per-file component paths.
|
|
64
|
+
|
|
65
|
+
## Route The Task
|
|
66
|
+
|
|
67
|
+
Read only the reference file that matches the task.
|
|
68
|
+
|
|
69
|
+
- Using or querying existing components:
|
|
70
|
+
`references/use-existing-component.md`
|
|
71
|
+
- Extracting a low-level base primitive:
|
|
72
|
+
`references/extract-base-component.md`
|
|
73
|
+
- Promoting reusable business UI into a shared component:
|
|
74
|
+
`references/promote-business-component.md`
|
|
75
|
+
- Maintaining ids, metadata, exports, or storyboard inventory:
|
|
76
|
+
`references/maintain-inventory.md`
|
|
77
|
+
|
|
78
|
+
## Global Boundaries
|
|
79
|
+
|
|
80
|
+
Keep these outside `@tutti-os/ui-system` components:
|
|
81
|
+
|
|
82
|
+
- daemon, Electron, filesystem, router, or host adapter calls
|
|
83
|
+
- data fetching, cache mutation, persistence, polling, and global store
|
|
84
|
+
ownership
|
|
85
|
+
- workflow orchestration such as onboarding, workspace registration, install or
|
|
86
|
+
uninstall flows, confirmation dialogs, queueing, or navigation
|
|
87
|
+
- i18n key lookup and business-specific copy derivation unless supplied by
|
|
88
|
+
props, children, or labels
|
|
89
|
+
|
|
90
|
+
For any promoted public component, add stable exports, metadata, and storyboard
|
|
91
|
+
coverage that match the chosen reference workflow.
|
|
92
|
+
|
|
93
|
+
For promoted base components, storyboard coverage is not satisfied by metadata
|
|
94
|
+
alone. The promotion flow must also add or update a real renderable example in
|
|
95
|
+
`apps/ui-storyboard` so the component is visible in navigation and can be
|
|
96
|
+
visually reviewed in shared docs immediately after promotion.
|
|
97
|
+
|
|
98
|
+
For business component promotion, use a copy-first workflow: move the existing
|
|
99
|
+
business component structure as intact as possible, preserve the real DOM,
|
|
100
|
+
visual hierarchy, state branches, and interaction layout, then progressively
|
|
101
|
+
remove host dependencies and standardize the public API. Do not begin by
|
|
102
|
+
inventing a cleaner abstraction or new visual treatment. The state matrix,
|
|
103
|
+
props boundary, and candidate source UI define what to copy, what to keep
|
|
104
|
+
caller-owned, and what to standardize after parity exists.
|
|
105
|
+
|
|
106
|
+
Treat business component promotion as an iterative migration-review loop, not a
|
|
107
|
+
single extraction pass:
|
|
108
|
+
|
|
109
|
+
1. migrate the source UI copy-first
|
|
110
|
+
2. recreate source-backed states in storyboard
|
|
111
|
+
3. run independent review against the original source and screenshot
|
|
112
|
+
4. migrate again to close review findings
|
|
113
|
+
5. repeat review until source/design parity is acceptable
|
|
114
|
+
|
|
115
|
+
Only after that loop should the API be generalized further. Do not report the
|
|
116
|
+
component as complete after the first migration if review still shows material
|
|
117
|
+
DOM, visual, token, state, icon, or storyboard coverage drift.
|
|
118
|
+
|
|
119
|
+
The promoted UI must follow the original design exactly unless the user
|
|
120
|
+
explicitly approves a visual change. Do not add new decoration, controls,
|
|
121
|
+
icons, layout chrome, copy, motion, states, spacing, or visual hierarchy that
|
|
122
|
+
does not exist in the source UI or provided screenshot. If UI-system token or
|
|
123
|
+
primitive replacement is needed, it must preserve the observed design and
|
|
124
|
+
interaction path rather than becoming a redesign.
|
|
125
|
+
|
|
126
|
+
Copy-first also applies to dependent presentational subcomponents and
|
|
127
|
+
third-party-library wrappers used by the candidate UI. Do not copy only the top
|
|
128
|
+
level JSX and recreate nested behavior from memory. Trace the dependency tree:
|
|
129
|
+
pure display helpers should move with the component; reusable wrappers around
|
|
130
|
+
Radix, floating UI, resizable panels, virtualization, or similar libraries
|
|
131
|
+
should be promoted or reused as `base` primitives first; host-coupled children
|
|
132
|
+
must be split into caller-owned data, labels, callbacks, or slots before the
|
|
133
|
+
business component is considered promoted.
|
|
134
|
+
|
|
135
|
+
## Design Foundation Verification
|
|
136
|
+
|
|
137
|
+
Every promoted component must comply with
|
|
138
|
+
`ui-system.md`, especially the shared tokens,
|
|
139
|
+
theme variables, spacing, radius, typography, surface language, interactive
|
|
140
|
+
states, and existing `base` primitive vocabulary.
|
|
141
|
+
|
|
142
|
+
Explicitly check and report all of these before completion:
|
|
143
|
+
|
|
144
|
+
- color and surface styling come from UI-system semantic tokens rather than raw
|
|
145
|
+
palette values
|
|
146
|
+
- panels, rows, controls, and overlays compose existing base primitives where
|
|
147
|
+
applicable instead of recreating them locally
|
|
148
|
+
- storyboard shows the component's real promoted surface rather than only a
|
|
149
|
+
documentation wrapper
|
|
150
|
+
- migrated consumers no longer depend on a separate visual token system for the
|
|
151
|
+
promoted surface
|
|
152
|
+
|
|
153
|
+
Run the Nextop promotion review gate before reporting completion. The gate is
|
|
154
|
+
adapted from frontend design review practice but constrained to Nextop's dense
|
|
155
|
+
workbench product language:
|
|
156
|
+
|
|
157
|
+
- Frictionless: the migrated consumer preserves the original task path, keeps a
|
|
158
|
+
clear action hierarchy, and does not bury primary or recovery actions.
|
|
159
|
+
- Quality craft: visual parity evidence is captured for selected states, shared
|
|
160
|
+
tokens and primitives are used, light/dark and interactive states work, and no
|
|
161
|
+
unapproved raw palette, spacing, radius, typography, or motion drift remains.
|
|
162
|
+
- Trustworthy: empty, loading, disabled, error-like, permission-limited, and
|
|
163
|
+
AI-generated-content states keep clear labels, actionable recovery, and
|
|
164
|
+
host-owned policy or provenance outside the shared component.
|
|
165
|
+
|
|
166
|
+
After promoting a base or business component, start an independent subagent to
|
|
167
|
+
review design-foundation compliance before reporting completion. Provide the
|
|
168
|
+
subagent with the promoted files, source usage, selected states, storyboard and
|
|
169
|
+
metadata entries, and the UI-system guidelines. If subagents are unavailable,
|
|
170
|
+
state that design-foundation verification is blocked and do not claim full
|
|
171
|
+
compliance.
|
|
172
|
+
|
|
173
|
+
Report the gate result with:
|
|
174
|
+
|
|
175
|
+
- context: source usage, promoted component id/layer, user task, selected states
|
|
176
|
+
- status: pass, needs work, or blocked
|
|
177
|
+
- pillar assessment: Frictionless, Quality craft, Trustworthy
|
|
178
|
+
- issues grouped as blocking, major, and minor
|
|
179
|
+
- validation commands and exact results
|
|
180
|
+
- remaining risks, uncovered states, or approved visual deltas
|
|
181
|
+
|
|
182
|
+
## API Composition Review
|
|
183
|
+
|
|
184
|
+
When converting source states into public props, review the API shape before
|
|
185
|
+
writing the promoted component:
|
|
186
|
+
|
|
187
|
+
- avoid boolean prop proliferation for rendering modes; mode axes such as
|
|
188
|
+
`isFoo`, `showBar`, or `withBaz` must come from code evidence and usually
|
|
189
|
+
become a finite variant, discriminated union, explicit component variant,
|
|
190
|
+
slot, or composed child
|
|
191
|
+
- keep standard UI booleans such as `disabled`, `loading`, `selected`, `open`,
|
|
192
|
+
`required`, and `invalid` only when they represent real component state and
|
|
193
|
+
cannot create impossible combinations
|
|
194
|
+
- prefer `children` or named slots for caller-owned visual regions; use render
|
|
195
|
+
props only when the shared component must pass data back to the caller
|
|
196
|
+
- use compound components and context only for genuinely complex reusable
|
|
197
|
+
structures where consumers need to compose subparts without prop drilling
|
|
198
|
+
- if shared state is needed, define a narrow context value as `state`,
|
|
199
|
+
`actions`, and `meta`; providers may inject state but must not own daemon,
|
|
200
|
+
Electron, router, store, query, persistence, or workflow side effects
|
|
201
|
+
- for new React components in this React 19 codebase, prefer the React 19 API
|
|
202
|
+
shape such as `ref` as a prop; do not churn shadcn or Radix-acquired code only
|
|
203
|
+
to normalize style when behavior and public API are already sound
|
|
204
|
+
|
|
205
|
+
Report the API composition decision with the state matrix: which differences
|
|
206
|
+
became props, variants, slots, children, explicit variants, provider state, or
|
|
207
|
+
stayed host-owned.
|
|
208
|
+
|
|
209
|
+
## Validation Commands
|
|
210
|
+
|
|
211
|
+
Run the smallest relevant checks from the selected reference. Common checks are:
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
node tools/scripts/check-ui-metadata.mjs
|
|
215
|
+
pnpm check:ui-boundaries
|
|
216
|
+
pnpm --filter @tutti-os/ui-storyboard typecheck
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
If runtime component code changed, also run the relevant package typecheck or
|
|
220
|
+
consumer build.
|
|
221
|
+
|
|
222
|
+
When a base component is promoted, verify both of these conditions before
|
|
223
|
+
reporting completion:
|
|
224
|
+
|
|
225
|
+
- the component metadata opts into storyboard visibility when appropriate
|
|
226
|
+
- `apps/ui-storyboard` contains a concrete rendered example for the promoted
|
|
227
|
+
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
|
+
`@tutti-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 @tutti-os/ui-storyboard typecheck
|
|
70
|
+
pnpm --filter @tutti-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 `@tutti-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 @tutti-os/ui-storyboard typecheck
|
|
45
|
+
```
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
# Promote Business Component
|
|
2
|
+
|
|
3
|
+
Use this reference when business-side UI should become a reusable
|
|
4
|
+
host-agnostic display component.
|
|
5
|
+
|
|
6
|
+
## Business Criteria
|
|
7
|
+
|
|
8
|
+
Proceed only if the component can render from props with no host side effects.
|
|
9
|
+
Business components may expose domain display props such as workspace, file,
|
|
10
|
+
task, agent, run, project, account, status, permission, labels, and callbacks.
|
|
11
|
+
|
|
12
|
+
Do not promote UI that owns daemon, Electron, router, store, query, persistence,
|
|
13
|
+
polling, filesystem access, or workflow orchestration.
|
|
14
|
+
|
|
15
|
+
## Agent-Owned Analysis
|
|
16
|
+
|
|
17
|
+
The agent must automatically analyze the candidate from code evidence. Do not
|
|
18
|
+
ask the user to provide the state matrix or props boundary unless the code has
|
|
19
|
+
conflicting evidence or an unclear business meaning.
|
|
20
|
+
|
|
21
|
+
Scan:
|
|
22
|
+
|
|
23
|
+
- source component and nearby helpers
|
|
24
|
+
- dependent presentational subcomponents imported by the source component
|
|
25
|
+
- third-party-library wrappers used by the candidate UI, such as Radix,
|
|
26
|
+
floating UI, resizable panels, drag/drop, virtualization, or editor shells
|
|
27
|
+
- call sites and conditional rendering branches
|
|
28
|
+
- props, types, tests, mocks, fixtures, and sample data
|
|
29
|
+
- relevant i18n keys and resolved labels
|
|
30
|
+
- existing UI-system metadata and components
|
|
31
|
+
|
|
32
|
+
Build a state matrix from that evidence. For each candidate state, record:
|
|
33
|
+
|
|
34
|
+
- state name
|
|
35
|
+
- source file or branch proving the state
|
|
36
|
+
- props or data needed to render it
|
|
37
|
+
- variation axes and whether each axis is visual, structural, behavioral, or
|
|
38
|
+
host-owned
|
|
39
|
+
- host-owned behavior that must stay outside the shared component
|
|
40
|
+
- whether the state belongs in the shared component contract
|
|
41
|
+
|
|
42
|
+
## Agent-Owned Boundary Decision
|
|
43
|
+
|
|
44
|
+
The agent decides the proposed component boundary before implementation:
|
|
45
|
+
|
|
46
|
+
- component `id` and `layer: "business"`
|
|
47
|
+
- source usage being replaced
|
|
48
|
+
- intended reuse surfaces
|
|
49
|
+
- public props and callbacks
|
|
50
|
+
- API shape decision: variants, discriminated unions, slots, children, explicit
|
|
51
|
+
component variants, compound subcomponents, provider state, and host-owned
|
|
52
|
+
caller logic
|
|
53
|
+
- host-owned state and side effects that remain outside
|
|
54
|
+
- states that will appear in storyboard
|
|
55
|
+
- stable export path and metadata entry
|
|
56
|
+
|
|
57
|
+
If the candidate is not reusable or cannot stay host-agnostic, do not promote
|
|
58
|
+
it. Prefer using existing components or keeping the UI local.
|
|
59
|
+
|
|
60
|
+
## API Composition Gate
|
|
61
|
+
|
|
62
|
+
Before writing the promoted component, convert the state matrix into a public
|
|
63
|
+
API deliberately:
|
|
64
|
+
|
|
65
|
+
1. List every visual, structural, and behavioral variation found in source
|
|
66
|
+
evidence.
|
|
67
|
+
2. Keep only standard state booleans such as `disabled`, `loading`, `selected`,
|
|
68
|
+
`open`, `required`, or `invalid` when they represent real states and do not
|
|
69
|
+
create impossible combinations.
|
|
70
|
+
3. Replace mode booleans such as `isFoo`, `showBar`, and `withBaz` with a
|
|
71
|
+
finite variant, discriminated union, explicit component variant, slot, or
|
|
72
|
+
composed child.
|
|
73
|
+
4. Prefer `children` or named slots for caller-owned visual regions. Use render
|
|
74
|
+
props only when the shared component needs to pass data back to the caller.
|
|
75
|
+
5. Use compound components and context only when consumers need to assemble
|
|
76
|
+
subparts while sharing state. A simple row, card, badge, toolbar, or display
|
|
77
|
+
panel should stay as a direct props-driven component.
|
|
78
|
+
6. If shared state is necessary, define a narrow injectable context contract as
|
|
79
|
+
`state`, `actions`, and `meta`. Providers may adapt caller state, but daemon,
|
|
80
|
+
Electron, router, store, query, persistence, filesystem, i18n lookup, and
|
|
81
|
+
workflow orchestration remain outside `@tutti-os/ui-system`.
|
|
82
|
+
7. For new React components, use the repository's React 19 baseline, including
|
|
83
|
+
`ref` as a prop when needed. Do not rewrite shadcn or Radix-acquired
|
|
84
|
+
internals solely to normalize API style.
|
|
85
|
+
|
|
86
|
+
Stop promotion if the only way to represent the source states is a broad bag of
|
|
87
|
+
unrelated boolean props or leaked host state. Narrow the boundary, create
|
|
88
|
+
explicit variants, or keep the UI local.
|
|
89
|
+
|
|
90
|
+
## Implementation Blueprint
|
|
91
|
+
|
|
92
|
+
Use a copy-first promotion workflow. The first implementation should be a
|
|
93
|
+
props-driven copy of the source business UI, not a new abstraction designed from
|
|
94
|
+
memory. Preserve the source DOM hierarchy, visual structure, spacing, state
|
|
95
|
+
branches, slots, and interaction affordances until parity is visible in
|
|
96
|
+
storyboard. Only after parity exists should the API be tightened and generalized.
|
|
97
|
+
|
|
98
|
+
Run promotion as a loop: migrate, review, migrate, review. The first migration
|
|
99
|
+
must make source-backed parity visible; review then measures drift against the
|
|
100
|
+
original code and screenshot; the next migration closes those findings without
|
|
101
|
+
redesigning. Continue until no material DOM, visual, token, state, icon, or
|
|
102
|
+
storyboard coverage drift remains. Do not treat the first extracted abstraction
|
|
103
|
+
as done if review still reports medium or high difference.
|
|
104
|
+
|
|
105
|
+
The promoted UI must follow the original design. Do not introduce new visual
|
|
106
|
+
ideas while promoting: no extra decoration, layout chrome, icons, controls,
|
|
107
|
+
copy, motion, spacing, state branches, or hierarchy that cannot be traced to the
|
|
108
|
+
source UI or the user's screenshot. Token replacement and primitive composition
|
|
109
|
+
are allowed only when they preserve the observed design and interaction path.
|
|
110
|
+
|
|
111
|
+
Icons are part of that source-derived visual contract and must still enter the
|
|
112
|
+
shared package through the UI-system icon layer. When the source UI uses an
|
|
113
|
+
icon, first reuse an existing `@tutti-os/ui-system/icons` export. If no
|
|
114
|
+
matching icon exists, promote the source-derived SVG or mark into
|
|
115
|
+
`packages/ui/system/src/icons`, add metadata, and consume that exported icon
|
|
116
|
+
from the business component or storyboard. Do not leave inline SVG/data URI
|
|
117
|
+
icons, app-local asset imports, or direct third-party icon imports in promoted
|
|
118
|
+
components or storyboard examples.
|
|
119
|
+
|
|
120
|
+
Copy and classify dependent subcomponents during the same migration. If a
|
|
121
|
+
nested helper is pure display, move it with the business component and convert
|
|
122
|
+
host data to props. If it wraps a third-party UI behavior that is reusable
|
|
123
|
+
outside the business domain, promote or reuse it as a `base` primitive first and
|
|
124
|
+
compose it from the business component. If it owns host state, i18n lookup,
|
|
125
|
+
daemon calls, router/filesystem access, persistence, or workflow orchestration,
|
|
126
|
+
leave that behavior in the caller and replace the nested region with data,
|
|
127
|
+
labels, callbacks, or slots. Do not rewrite a new nested component from memory
|
|
128
|
+
while the original source behavior still exists to copy.
|
|
129
|
+
|
|
130
|
+
Implement the promoted component directly from three inputs:
|
|
131
|
+
|
|
132
|
+
- the code-evidence state matrix
|
|
133
|
+
- the proposed public props and callback boundary
|
|
134
|
+
- the existing candidate source UI or visual surface being extracted
|
|
135
|
+
|
|
136
|
+
The promoted component should start as a props-driven version of the candidate
|
|
137
|
+
source with host-owned behavior removed. Preserve the real visual structure,
|
|
138
|
+
component composition, class names, spacing, icons, and state-specific branches
|
|
139
|
+
unless they depend on host-owned behavior. Replace host-owned behavior with
|
|
140
|
+
public props, callbacks, caller-owned slots, or explicit variants. Add
|
|
141
|
+
storyboard examples for every accepted public state in the same change so the
|
|
142
|
+
review can inspect the finished implementation instead of a preflight draft.
|
|
143
|
+
Do not add states, controls, copy, icons, animation, or visual wrappers that the
|
|
144
|
+
source component did not have unless the user explicitly asks for that design
|
|
145
|
+
change.
|
|
146
|
+
|
|
147
|
+
Generalize in this order:
|
|
148
|
+
|
|
149
|
+
1. Copy the existing component structure and nearby presentational helpers.
|
|
150
|
+
2. Trace dependent subcomponents and third-party wrappers; move pure display
|
|
151
|
+
helpers with the component, promote reusable third-party wrappers to `base`
|
|
152
|
+
primitives, and mark host-coupled children as caller-owned slots or data.
|
|
153
|
+
3. Replace host imports, data derivation, i18n lookup, store reads, side effects,
|
|
154
|
+
and daemon/router/filesystem calls with props, labels, callbacks, or slots.
|
|
155
|
+
4. Recreate the original visual states in storyboard before simplifying the API.
|
|
156
|
+
5. Run independent review against the source UI and close material drift before
|
|
157
|
+
simplifying the API.
|
|
158
|
+
6. Standardize the API names and types around data, labels, actions, variants,
|
|
159
|
+
and slots while preserving visual and behavioral parity.
|
|
160
|
+
7. Replace app-local styling with UI-system tokens and base primitives only when
|
|
161
|
+
the replacement does not change the observed UI or interaction path.
|
|
162
|
+
8. Reject or remove any invented UI added during promotion unless it is backed
|
|
163
|
+
by source evidence or an explicit user-approved visual change.
|
|
164
|
+
|
|
165
|
+
Do not skip directly to a polished abstraction. If the first promoted version
|
|
166
|
+
cannot be compared against the source screenshot or source state, the promotion
|
|
167
|
+
is incomplete.
|
|
168
|
+
|
|
169
|
+
If the draft still needs app state, navigation, fetching, persistence, i18n key
|
|
170
|
+
lookup, or host adapters to render, stop and revise the component boundary
|
|
171
|
+
instead of promoting it.
|
|
172
|
+
|
|
173
|
+
## Promotion Chain Demo
|
|
174
|
+
|
|
175
|
+
Example request:
|
|
176
|
+
|
|
177
|
+
```text
|
|
178
|
+
Promote the managed agent settings table into @tutti-os/ui-system.
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Expected chain:
|
|
182
|
+
|
|
183
|
+
1. **Analyze source evidence**
|
|
184
|
+
- Read the source table, settings panel call sites, tests, mocks, and i18n
|
|
185
|
+
labels.
|
|
186
|
+
- Check existing metadata for reusable table, badge, button, dialog, and
|
|
187
|
+
icon primitives.
|
|
188
|
+
2. **Build the state matrix**
|
|
189
|
+
|
|
190
|
+
```text
|
|
191
|
+
normal
|
|
192
|
+
- Evidence: settings table renders installed agents with status and actions.
|
|
193
|
+
- Props/data: rows, status labels, action labels, icon slots, callbacks.
|
|
194
|
+
- Host-owned: install/uninstall orchestration, queue state derivation, i18n.
|
|
195
|
+
- Contract: yes.
|
|
196
|
+
|
|
197
|
+
empty
|
|
198
|
+
- Evidence: settings surface renders no configured agents.
|
|
199
|
+
- Props/data: empty title/body.
|
|
200
|
+
- Host-owned: deciding whether inventory is empty.
|
|
201
|
+
- Contract: yes.
|
|
202
|
+
|
|
203
|
+
disabled
|
|
204
|
+
- Evidence: actions disabled while an operation is pending.
|
|
205
|
+
- Props/data: disabled rows or disabled actions.
|
|
206
|
+
- Host-owned: permission and pending-operation calculation.
|
|
207
|
+
- Contract: yes.
|
|
208
|
+
|
|
209
|
+
error-like
|
|
210
|
+
- Evidence: row can show install failure or unavailable status.
|
|
211
|
+
- Props/data: tone, status label, supporting text.
|
|
212
|
+
- Host-owned: failure classification and retry behavior.
|
|
213
|
+
- Contract: yes.
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
3. **Decide the boundary before implementation**
|
|
217
|
+
- `id`: a stable kebab-case business component id, for example
|
|
218
|
+
`example-business-component`
|
|
219
|
+
- `layer`: `business`
|
|
220
|
+
- Export: a matching PascalCase component name, for example
|
|
221
|
+
`ExampleBusinessComponent`
|
|
222
|
+
- Public props: rows, labels, icon render slots, action callbacks, disabled
|
|
223
|
+
flags, status/tone fields, empty-state copy.
|
|
224
|
+
- API shape: row status as finite tone values, callbacks as host-provided
|
|
225
|
+
actions, empty state copy as labels, and no install/uninstall mode
|
|
226
|
+
booleans. If the table later needs caller-owned row adornments, prefer a
|
|
227
|
+
named slot or composed child over a broad render prop.
|
|
228
|
+
- Host-owned behavior: i18n lookup, daemon calls, install queue,
|
|
229
|
+
confirmation dialogs, persistence, routing, and state derivation.
|
|
230
|
+
4. **Implement the promoted component with copy-first parity**
|
|
231
|
+
- Copy the current candidate source into the final
|
|
232
|
+
`packages/ui/system/src/components/<component-dir>/index.tsx` component.
|
|
233
|
+
- Copy dependent presentational helpers and classify any third-party
|
|
234
|
+
wrappers before changing behavior. Reuse or promote base primitives for
|
|
235
|
+
reusable library wrappers instead of rebuilding them in the business file.
|
|
236
|
+
- Route icons through `@tutti-os/ui-system/icons`: reuse existing exports or
|
|
237
|
+
promote source-derived icons into the package icon layer with metadata
|
|
238
|
+
before using them in the component or storyboard.
|
|
239
|
+
- Keep the real table layout, status cells, action affordances, icon
|
|
240
|
+
placement, empty state, nested display helpers, and disabled/error branches.
|
|
241
|
+
- Replace host behavior with props, labels, callbacks, and caller-owned
|
|
242
|
+
slots: i18n lookup, queue state, confirmation dialog decisions, daemon
|
|
243
|
+
calls, and install orchestration stay outside the component.
|
|
244
|
+
- Only after storyboard parity is visible, simplify the copied API toward
|
|
245
|
+
durable `items`, `labels`, `actions`, explicit variants, and slots.
|
|
246
|
+
- Make only package integration edits: final exported prop types, imports,
|
|
247
|
+
class cleanup, and package-local helpers.
|
|
248
|
+
- Export it from stable barrels.
|
|
249
|
+
- Add metadata with `layer: "business"` and storyboard coverage for the
|
|
250
|
+
accepted states.
|
|
251
|
+
- Replace the original app UI with `@tutti-os/ui-system` imports while
|
|
252
|
+
leaving host-owned behavior in the caller.
|
|
253
|
+
5. **Validate and report**
|
|
254
|
+
- Review the finished implementation through the storyboard states and the
|
|
255
|
+
migrated consumer surface.
|
|
256
|
+
- Start an independent design-foundation review subagent. Give it the
|
|
257
|
+
promoted files, original source usage, selected state matrix, storyboard
|
|
258
|
+
entry, metadata entry, and `ui-system.md`.
|
|
259
|
+
- Include the API shape review in the handoff: accepted booleans, variants,
|
|
260
|
+
slots or children, explicit variants, provider state if any, and
|
|
261
|
+
host-owned behavior kept in the caller.
|
|
262
|
+
- Resolve any subagent-reported design drift before reporting completion.
|
|
263
|
+
- Run the promotion review gate: Frictionless task path and action hierarchy,
|
|
264
|
+
Quality Craft visual parity and token/state coverage, and Trustworthy
|
|
265
|
+
labels, recovery, policy, and provenance behavior.
|
|
266
|
+
- Run metadata, boundary, storyboard, and relevant package checks.
|
|
267
|
+
- Report the state matrix summary, final boundary, promotion review result,
|
|
268
|
+
subagent design-foundation result, validation results, and uncovered
|
|
269
|
+
risks.
|
|
270
|
+
|
|
271
|
+
## Implementation
|
|
272
|
+
|
|
273
|
+
1. Copy the existing business component structure into `packages/ui/system`
|
|
274
|
+
before abstracting it.
|
|
275
|
+
2. Keep all host-owned behavior in the caller by replacing it with props,
|
|
276
|
+
labels, callbacks, or caller-owned slots.
|
|
277
|
+
3. Preserve the source visual and interaction shape until storyboard parity is
|
|
278
|
+
visible.
|
|
279
|
+
4. Standardize the API incrementally. Do not add new mode booleans or
|
|
280
|
+
host-owned state while moving the candidate UI into the shared package.
|
|
281
|
+
5. Add stable exports and metadata with `layer: "business"`.
|
|
282
|
+
6. Add storyboard examples for normal, empty, disabled, loading, and error-like
|
|
283
|
+
states when those states exist in the public contract.
|
|
284
|
+
7. Migrate callers by replacing only the visual surface.
|
|
285
|
+
8. Run the promotion review gate from
|
|
286
|
+
`ui-system.md` against the promoted component
|
|
287
|
+
and migrated consumer.
|
|
288
|
+
9. Start the design-foundation review subagent and resolve any reported drift.
|
|
289
|
+
|
|
290
|
+
## Validation
|
|
291
|
+
|
|
292
|
+
Run the relevant checks:
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
node tools/scripts/check-ui-metadata.mjs
|
|
296
|
+
pnpm check:ui-boundaries
|
|
297
|
+
pnpm --filter @tutti-os/ui-storyboard typecheck
|
|
298
|
+
pnpm --filter @tutti-os/ui-system typecheck
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
If a consumer was migrated, also run that consumer's typecheck or build.
|
|
302
|
+
|
|
303
|
+
Report:
|
|
304
|
+
|
|
305
|
+
- state matrix summary
|
|
306
|
+
- component boundary decision
|
|
307
|
+
- API composition decision and any rejected boolean or state combinations
|
|
308
|
+
- promotion review result with Frictionless / Quality Craft / Trustworthy
|
|
309
|
+
pillar status and blocking/major/minor issues
|
|
310
|
+
- design-foundation subagent result
|
|
311
|
+
- validation commands and results
|
|
312
|
+
- remaining risks or uncovered states
|
|
313
|
+
|
|
314
|
+
Do not report full design-foundation compliance unless the subagent review ran
|
|
315
|
+
and found no unresolved drift. If subagents are unavailable, report the
|
|
316
|
+
verification as blocked.
|