@oneie/claude 0.6.0 → 0.7.0
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/w1-recon.md +9 -4
- package/agents/w2-decide.md +51 -28
- package/agents/w3-edit.md +70 -78
- package/agents/w4-verify.md +164 -69
- package/commands/browser.md +98 -35
- package/commands/cc-connect.md +6 -0
- package/commands/chat.md +13 -1
- package/commands/close.md +45 -19
- package/commands/create.md +20 -10
- package/commands/db-sync.md +5 -1
- package/commands/deploy.md +174 -87
- package/commands/do-autonomous.md +31 -20
- package/commands/do-improve.md +4 -4
- package/commands/do-show.md +4 -3
- package/commands/do.md +53 -13
- package/commands/go.md +75 -0
- package/commands/improve.md +4 -2
- package/commands/kill.md +6 -8
- package/commands/notify.md +15 -2
- package/commands/oo-push.md +24 -9
- package/commands/rag.md +6 -0
- package/commands/release.md +46 -25
- package/commands/restart.md +5 -4
- package/commands/see.md +45 -35
- package/commands/skill-create.md +38 -5
- package/commands/sync.md +21 -11
- package/hooks/scripts/auto-continue.sh +70 -0
- package/hooks/scripts/branch-pin.sh +85 -0
- package/hooks/scripts/git-add-guard.sh +16 -5
- package/hooks/scripts/post-edit-check.sh +16 -0
- package/hooks/scripts/session-start.sh +13 -8
- package/hooks/scripts/sync-priority-todo.sh +5 -0
- package/package.json +1 -1
- package/rules/api.md +9 -0
- package/rules/design.md +13 -3
- package/rules/documentation.md +30 -71
- package/rules/engine.md +8 -1
- package/rules/ui.md +5 -1
- package/scripts/__pycache__/do-rank.cpython-313.pyc +0 -0
- package/scripts/browser-check.mjs +44 -103
- package/scripts/cc-events-proof.sh +13 -12
- package/scripts/chrome.mjs +381 -0
- package/scripts/do-analyze.sh +109 -4
- package/scripts/do-auto.sh +350 -43
- package/scripts/do-consumer-sweep.sh +72 -0
- package/scripts/do-derives-check.sh +88 -0
- package/scripts/do-fleet.sh +50 -1
- package/scripts/do-killswitch-audit.py +33 -14
- package/scripts/do-promise-lint.sh +150 -4
- package/scripts/do-promise-settle.sh +131 -9
- package/scripts/do-prove.sh +197 -17
- package/scripts/do-rank.py +606 -20
- package/scripts/do-rubric.py +21 -2
- package/scripts/do-signal.sh +157 -17
- package/scripts/do-smoke.sh +9 -0
- package/scripts/do-substrate-check.sh +49 -0
- package/scripts/do-tasks-wire-check.sh +81 -0
- package/scripts/do-tier.sh +90 -5
- package/scripts/do-ui-gate.sh +332 -0
- package/scripts/do-untracked-gate.sh +231 -0
- package/scripts/do-walk.sh +344 -0
- package/scripts/factory-check.sh +747 -0
- package/scripts/factory-repo.sh +1361 -0
- package/scripts/factory-tasks-check.sh +85 -0
- package/scripts/outcome-pull.ts +279 -0
- package/scripts/promise-manifest.mjs +167 -0
- package/scripts/reconcile-allow.txt +5 -0
- package/scripts/rubric-weights.json +64 -0
- package/scripts/spine-canary.sh +20 -0
- package/scripts/typedb-cluster-status.sh +128 -0
- package/scripts/typedb-env.sh +182 -0
- package/scripts/typedb-flap-recorder.sh +85 -0
- package/scripts/typedb-probes/containment-probe.py +88 -0
- package/scripts/typedb-probes/panic-probe-version.py +92 -0
- package/scripts/typedb-probes/panic-probe.py +77 -0
- package/scripts/typedb-scratch.sh +73 -0
- package/scripts/urls-lint.sh +58 -0
- package/scripts/w4-rubric.ts +96 -12
- package/scripts/wf-check.mjs +75 -0
- package/skills/ai-ui/SKILL.md +1 -1
- package/skills/astro/SKILL.md +177 -132
- package/skills/astro/add-content-collection.md +29 -13
- package/skills/astro/check-build.md +19 -13
- package/skills/astro/create-component.md +36 -9
- package/skills/astro/create-page.md +39 -10
- package/skills/astro/optimize-performance.md +36 -8
- package/skills/cli/SKILL.md +254 -220
- package/skills/dev/SKILL.md +1 -1
- package/skills/directory-autofill/SKILL.md +68 -0
- package/skills/docs/SKILL.md +4 -4
- package/skills/mcp/SKILL.md +186 -156
- package/skills/promise-make/SKILL.md +2 -2
- package/skills/puck/SKILL.md +465 -250
- package/skills/react19/SKILL.md +196 -296
- package/skills/reactflow/SKILL.md +387 -412
- package/skills/sdk/SKILL.md +167 -106
- package/skills/shadcn/SKILL.md +245 -201
- package/skills/signal/SKILL.md +5 -0
- package/skills/sui/SKILL.md +6 -1
- package/skills/tutorial/SKILL.md +15 -0
- package/skills/typedb/SKILL.md +427 -217
- package/skills/typedb/examples/python-patterns.py +11 -4
- package/skills/typedb/examples/query-patterns.tql +8 -3
- package/skills/typedb/examples/schema-patterns.tql +4 -2
- package/skills/typedb/reference/migration-2x-3x.md +19 -1
- package/skills/typedb/reference/python-driver.md +17 -1
- package/skills/voice/SKILL.md +117 -0
- package/skills/writer/SKILL.md +29 -12
- package/templates/template-feature.md +26 -1
- package/templates/template-tests.md +4 -0
- package/templates/template-todo.md +65 -10
package/skills/shadcn/SKILL.md
CHANGED
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: shadcn
|
|
3
|
-
description:
|
|
3
|
+
description: shadcn/ui primitives in `one.ie/web` under the ONE 6-token design system. Covers the `src/components/ui/` inventory, why shadcn's own `-foreground` names survive the `--color-*: initial` palette wipe via the Layout.astro aliases, adding a primitive with the CLI, and Button/Badge/Card/Dialog variants. Use when adding or editing a `src/components/ui/` primitive, when a shadcn component renders transparent or invisible after the wipe, or when picking between a token utility and an alias.
|
|
4
4
|
user-invocable: true
|
|
5
5
|
allowed-tools: Read, Write, Edit, Glob, Grep, Bash
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# shadcn/ui Development
|
|
9
9
|
|
|
10
|
-
Build
|
|
10
|
+
Build UI in `one.ie/web` with shadcn primitives on the ONE 6-token design system.
|
|
11
|
+
|
|
12
|
+
This skill covers the seam that the auto-loaded rules do not: **how shadcn's own
|
|
13
|
+
naming convention (`bg-card`, `text-muted-foreground`, `text-primary-foreground`)
|
|
14
|
+
survives the `--color-*: initial` palette wipe.** For the token list, the allowed
|
|
15
|
+
utilities, and the ban list, read `.claude/rules/design.md` — it auto-loads on the
|
|
16
|
+
same files and is already in context when you edit.
|
|
17
|
+
|
|
18
|
+
Scope: `one.ie/web`. For `template/site` use the `template:shadcn` skill; for
|
|
19
|
+
generic registry/CLI operations outside this repo use the `shadcn` plugin skill.
|
|
11
20
|
|
|
12
21
|
## Works With
|
|
13
22
|
|
|
@@ -15,56 +24,102 @@ Build consistent UI with shadcn/ui components, customized for the Envelope Syste
|
|
|
15
24
|
|------------|------------------------------------------------------------------------------|
|
|
16
25
|
| `/react19` | shadcn components ARE React components — ref-as-prop, Actions, transitions apply. |
|
|
17
26
|
| `/astro` | Placement inside islands + hydration strategy decisions. |
|
|
18
|
-
| `/
|
|
27
|
+
| `/puck` | Every Puck block wraps a real component — brand tokens reach the editor iframe. |
|
|
19
28
|
| `/ai-ui` | AI Elements (reasoning cards, tool-call blocks) compose shadcn primitives. |
|
|
20
29
|
|
|
21
|
-
Auto-loads on
|
|
30
|
+
Auto-loads on these files, via each rule's own `paths:` frontmatter (not
|
|
31
|
+
`settings.json`, which wires hooks only):
|
|
32
|
+
|
|
33
|
+
| Rule | Glob |
|
|
34
|
+
|---|---|
|
|
35
|
+
| `rules/react.md` | `**/*.tsx` |
|
|
36
|
+
| `rules/ui.md` | `one.ie/web/src/components/**/*.tsx` |
|
|
37
|
+
| `rules/design.md` | `one.ie/web/**/*.{tsx,astro,css}` |
|
|
22
38
|
|
|
23
39
|
## When to Use This Skill
|
|
24
40
|
|
|
25
|
-
- Use existing
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
- Build composite components
|
|
41
|
+
- Use existing primitives from `one.ie/web/src/components/ui/`
|
|
42
|
+
- Add a new primitive with the shadcn CLI
|
|
43
|
+
- Customize a variant (`cva` blocks in `button.tsx`, `badge.tsx`)
|
|
44
|
+
- Fix a primitive that renders transparent or invisible after the palette wipe
|
|
45
|
+
- Build composite components on top of the primitives
|
|
30
46
|
|
|
31
47
|
## Available Components
|
|
32
48
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
49
|
+
`one.ie/web/src/components/ui/` holds **57 files**. They are not all shadcn:
|
|
50
|
+
|
|
51
|
+
**shadcn primitives** — generated by the CLI, backed by the unified `radix-ui`
|
|
52
|
+
package (`^1.4.3`, imported as `import { Dialog as DialogPrimitive } from "radix-ui"`
|
|
53
|
+
— **not** the old `@radix-ui/react-*` scoped packages):
|
|
54
|
+
|
|
55
|
+
`accordion` · `alert` · `aspect-ratio` · `avatar` · `badge` · `breadcrumb` ·
|
|
56
|
+
`button` · `button-group` · `card` · `carousel` · `chart` · `checkbox` ·
|
|
57
|
+
`collapsible` · `command` · `dialog` · `dropdown-menu` · `hover-card` ·
|
|
58
|
+
`input` · `input-group` · `kbd` · `label` · `navigation-menu` · `pagination` ·
|
|
59
|
+
`popover` · `progress` · `radio-group` · `scroll-area` · `select` · `separator` ·
|
|
60
|
+
`sheet` · `skeleton` · `slider` · `spinner` · `switch` · `table` · `tabs` ·
|
|
61
|
+
`textarea` · `toggle` · `toggle-group` · `tooltip`
|
|
62
|
+
|
|
63
|
+
**ONE-local, not shadcn** — do not `shadcn add` over these, and do not assume
|
|
64
|
+
upstream props: `Icon.tsx` · `IconBadge.tsx` · `EmptyCard.tsx` · `ImagePicker.tsx` ·
|
|
65
|
+
`Drawer.tsx` · `global-toaster.tsx` · `multi-select.tsx` · `rating.tsx` ·
|
|
66
|
+
`animated-tooltip.tsx` · `bounce-button.tsx` · `magnetic-button.tsx` ·
|
|
67
|
+
`shimmer-button.tsx` · `motion-checkbox.tsx` · `motion-highlight.tsx` ·
|
|
68
|
+
`motion-radio-group.tsx` · `motion-switch.tsx` · `motion-tabs.tsx`
|
|
69
|
+
|
|
70
|
+
`components.json` pins `style: "radix-nova"`, `iconLibrary: "lucide"`,
|
|
71
|
+
`cssVariables: true`, and `css: src/styles/globals.css`.
|
|
72
|
+
|
|
73
|
+
## Color System — how shadcn names survive the wipe
|
|
74
|
+
|
|
75
|
+
`Layout.astro` declares `--color-*: initial` inside `@theme`, which erases
|
|
76
|
+
Tailwind's entire default palette. That is the enforcement layer: `bg-zinc-950`
|
|
77
|
+
emits no CSS at all. It also erases every var a stock shadcn primitive expects.
|
|
78
|
+
|
|
79
|
+
So `Layout.astro` re-declares the ones shadcn needs, aliased onto the 6 tokens.
|
|
80
|
+
This is the mechanism to know — it is why you can write `bg-card` and
|
|
81
|
+
`text-muted-foreground` in a primitive without adding a 7th token:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
--color-popover: var(--color-foreground)
|
|
85
|
+
--color-popover-foreground: var(--color-font)
|
|
86
|
+
--color-card: var(--color-foreground)
|
|
87
|
+
--color-card-foreground: var(--color-font)
|
|
88
|
+
--color-muted: var(--color-foreground)
|
|
89
|
+
--color-muted-foreground: color-mix(font 60%, transparent)
|
|
90
|
+
--color-accent: var(--color-foreground)
|
|
91
|
+
--color-accent-foreground: var(--color-font)
|
|
92
|
+
--color-input: var(--color-background)
|
|
93
|
+
--color-primary-foreground: var(--color-on-primary)
|
|
94
|
+
--color-secondary-foreground: var(--color-on-secondary)
|
|
63
95
|
```
|
|
64
96
|
|
|
97
|
+
Two failure modes this prevents, both of which look like a bug in the component:
|
|
98
|
+
|
|
99
|
+
1. **Transparent popovers.** Without `--color-card` / `--color-popover`, the
|
|
100
|
+
wiped var makes the `background-color` declaration invalid, so the panel
|
|
101
|
+
inherits nothing and floats see-through over the page.
|
|
102
|
+
2. **Invisible glyphs on a brand fill.** Stock Button/Badge/Checkbox read
|
|
103
|
+
`text-primary-foreground`. Wiped, the color declaration is dropped and the
|
|
104
|
+
icon inherits an ancestor's `text-muted-foreground` — near-invisible on a
|
|
105
|
+
solid `bg-primary`. The alias points it at the already-WCAG-correct
|
|
106
|
+
`on-primary` label.
|
|
107
|
+
|
|
108
|
+
**The one collision you must resolve by hand:** shadcn uses `foreground` to mean
|
|
109
|
+
"body text on a card". ONE uses `foreground` as the L2 *surface* token (cards,
|
|
110
|
+
sidebar, panels). They are not the same thing and there is no alias that can make
|
|
111
|
+
them so. Any primitive that ships `text-foreground` for body text **must be edited
|
|
112
|
+
to `text-font`** — otherwise the text paints the same color as its own background.
|
|
113
|
+
`src/components/ui/` currently has zero `text-foreground` occurrences; keep it
|
|
114
|
+
that way after every `shadcn add`.
|
|
115
|
+
|
|
116
|
+
Fine as-is, no edit needed: `text-card-foreground`, `text-popover-foreground`,
|
|
117
|
+
`text-muted-foreground`, `text-accent-foreground`, and the
|
|
118
|
+
`text-{primary,secondary,destructive,sidebar}-foreground` contrast labels.
|
|
119
|
+
|
|
65
120
|
## Core Components
|
|
66
121
|
|
|
67
|
-
### Card
|
|
122
|
+
### Card
|
|
68
123
|
|
|
69
124
|
```tsx
|
|
70
125
|
import {
|
|
@@ -75,32 +130,33 @@ import {
|
|
|
75
130
|
CardTitle,
|
|
76
131
|
} from "@/components/ui/card";
|
|
77
132
|
|
|
78
|
-
|
|
133
|
+
interface Signal {
|
|
134
|
+
id: string;
|
|
135
|
+
receiver: string;
|
|
136
|
+
target: string;
|
|
137
|
+
status: string;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function SignalCard({ signal }: { signal: Signal }) {
|
|
79
141
|
return (
|
|
80
|
-
<Card
|
|
142
|
+
<Card>
|
|
81
143
|
<CardHeader className="pb-2">
|
|
82
144
|
<CardTitle className="flex items-center gap-2 text-sm font-mono">
|
|
83
|
-
<span className="text-
|
|
84
|
-
<span className="text-
|
|
145
|
+
<span className="text-font/60">signal</span>
|
|
146
|
+
<span className="text-primary">{signal.id}</span>
|
|
85
147
|
</CardTitle>
|
|
86
148
|
<CardDescription>
|
|
87
|
-
{
|
|
149
|
+
{signal.receiver} → {signal.target}
|
|
88
150
|
</CardDescription>
|
|
89
151
|
</CardHeader>
|
|
90
152
|
<CardContent className="space-y-2">
|
|
91
153
|
<div className="font-mono text-xs">
|
|
92
|
-
<span className="text-
|
|
93
|
-
<span className="text-
|
|
154
|
+
<span className="text-font/40">receiver: </span>
|
|
155
|
+
<span className="text-tertiary">{signal.receiver}</span>
|
|
94
156
|
</div>
|
|
95
157
|
<div className="font-mono text-xs">
|
|
96
|
-
<span className="text-
|
|
97
|
-
<
|
|
98
|
-
{JSON.stringify(envelope.env.inputs)}
|
|
99
|
-
</span>
|
|
100
|
-
</div>
|
|
101
|
-
<div className="font-mono text-xs">
|
|
102
|
-
<span className="text-slate-500">status: </span>
|
|
103
|
-
<StatusBadge status={envelope.payload.status} />
|
|
158
|
+
<span className="text-font/40">status: </span>
|
|
159
|
+
<StatusBadge status={signal.status} />
|
|
104
160
|
</div>
|
|
105
161
|
</CardContent>
|
|
106
162
|
</Card>
|
|
@@ -108,30 +164,31 @@ export function EnvelopeCard({ envelope }: { envelope: Envelope }) {
|
|
|
108
164
|
}
|
|
109
165
|
```
|
|
110
166
|
|
|
111
|
-
|
|
167
|
+
`Card` already resolves to the `foreground` surface via `--color-card`. Do not
|
|
168
|
+
re-skin it with a background utility.
|
|
169
|
+
|
|
170
|
+
### Tabs
|
|
112
171
|
|
|
113
172
|
```tsx
|
|
114
173
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
|
115
174
|
|
|
116
|
-
|
|
175
|
+
interface Actor { id: string; name: string; status: string }
|
|
176
|
+
|
|
177
|
+
export function ActorTabs({ actors }: { actors: Actor[] }) {
|
|
117
178
|
return (
|
|
118
|
-
<Tabs defaultValue={
|
|
119
|
-
<TabsList
|
|
120
|
-
{
|
|
121
|
-
<TabsTrigger
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
className="data-[state=active]:bg-[#1e293b] data-[state=active]:text-white"
|
|
125
|
-
>
|
|
126
|
-
<StatusDot status={agent.status} />
|
|
127
|
-
<span className="ml-2">{agent.name}</span>
|
|
179
|
+
<Tabs defaultValue={actors[0]?.id} className="w-full">
|
|
180
|
+
<TabsList>
|
|
181
|
+
{actors.map(actor => (
|
|
182
|
+
<TabsTrigger key={actor.id} value={actor.id}>
|
|
183
|
+
<StatusDot status={actor.status} />
|
|
184
|
+
<span className="ml-2">{actor.name}</span>
|
|
128
185
|
</TabsTrigger>
|
|
129
186
|
))}
|
|
130
187
|
</TabsList>
|
|
131
188
|
|
|
132
|
-
{
|
|
133
|
-
<TabsContent key={
|
|
134
|
-
<
|
|
189
|
+
{actors.map(actor => (
|
|
190
|
+
<TabsContent key={actor.id} value={actor.id} className="mt-4">
|
|
191
|
+
<ActorContent actor={actor} />
|
|
135
192
|
</TabsContent>
|
|
136
193
|
))}
|
|
137
194
|
</Tabs>
|
|
@@ -139,26 +196,26 @@ export function AgentTabs({ agents }: { agents: Agent[] }) {
|
|
|
139
196
|
}
|
|
140
197
|
```
|
|
141
198
|
|
|
142
|
-
### Badge
|
|
199
|
+
### Badge
|
|
200
|
+
|
|
201
|
+
Status color comes from the 5 invariants plus the 3 brand tokens — never from a
|
|
202
|
+
Tailwind palette ramp.
|
|
143
203
|
|
|
144
204
|
```tsx
|
|
145
205
|
import { Badge } from "@/components/ui/badge";
|
|
146
206
|
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
idle: "bg-slate-500/20 text-slate-400 border-slate-500/30",
|
|
153
|
-
error: "bg-red-500/20 text-red-400 border-red-500/30",
|
|
154
|
-
rejected: "bg-red-500/20 text-red-400 border-red-500/30",
|
|
207
|
+
const statusClasses = {
|
|
208
|
+
resolved: "bg-success/20 text-success",
|
|
209
|
+
pending: "bg-secondary/20 text-secondary",
|
|
210
|
+
idle: "bg-font/10 text-font/60",
|
|
211
|
+
error: "bg-destructive/20 text-destructive",
|
|
155
212
|
};
|
|
156
213
|
|
|
157
214
|
export function StatusBadge({ status }: { status: string }) {
|
|
158
215
|
return (
|
|
159
216
|
<Badge
|
|
160
217
|
variant="outline"
|
|
161
|
-
className={
|
|
218
|
+
className={statusClasses[status as keyof typeof statusClasses] ?? statusClasses.idle}
|
|
162
219
|
>
|
|
163
220
|
{status}
|
|
164
221
|
</Badge>
|
|
@@ -166,43 +223,41 @@ export function StatusBadge({ status }: { status: string }) {
|
|
|
166
223
|
}
|
|
167
224
|
```
|
|
168
225
|
|
|
169
|
-
### Button
|
|
226
|
+
### Button
|
|
227
|
+
|
|
228
|
+
The repo's `button.tsx` ships **6 variants** — `default` · `outline` ·
|
|
229
|
+
`secondary` · `ghost` · `destructive` · `link` — and **8 sizes** — `default` ·
|
|
230
|
+
`xs` · `sm` · `lg` · `icon` · `icon-xs` · `icon-sm` · `icon-lg`. There is no
|
|
231
|
+
`primary` variant name; `default` already means `bg-primary text-primary-foreground`.
|
|
170
232
|
|
|
171
233
|
```tsx
|
|
172
234
|
import { Button } from "@/components/ui/button";
|
|
235
|
+
import { ChevronRight } from "lucide-react";
|
|
173
236
|
|
|
174
|
-
|
|
175
|
-
<Button
|
|
176
|
-
|
|
177
|
-
</Button>
|
|
178
|
-
|
|
179
|
-
// Secondary action
|
|
180
|
-
<Button variant="outline" className="border-[#1e293b] hover:bg-[#1e293b]">
|
|
181
|
-
Cancel
|
|
182
|
-
</Button>
|
|
183
|
-
|
|
184
|
-
// Destructive
|
|
185
|
-
<Button variant="destructive">
|
|
186
|
-
Reject
|
|
187
|
-
</Button>
|
|
188
|
-
|
|
189
|
-
// Ghost (icon buttons)
|
|
237
|
+
<Button>Send signal</Button> {/* default = brand fill */}
|
|
238
|
+
<Button variant="outline">Cancel</Button>
|
|
239
|
+
<Button variant="secondary">Save draft</Button>
|
|
240
|
+
<Button variant="destructive">Reject</Button>
|
|
190
241
|
<Button variant="ghost" size="icon">
|
|
191
|
-
<ChevronRight
|
|
242
|
+
<ChevronRight />
|
|
192
243
|
</Button>
|
|
193
244
|
```
|
|
194
245
|
|
|
195
|
-
|
|
246
|
+
Do not pass a background class to override the variant — that is how a palette
|
|
247
|
+
class gets reintroduced. Add a variant to the `cva` block instead.
|
|
248
|
+
|
|
249
|
+
### ScrollArea
|
|
196
250
|
|
|
197
251
|
```tsx
|
|
198
252
|
import { ScrollArea } from "@/components/ui/scroll-area";
|
|
253
|
+
import { SignalCard } from "./SignalCard";
|
|
199
254
|
|
|
200
|
-
export function
|
|
255
|
+
export function SignalList({ signals }: { signals: Signal[] }) {
|
|
201
256
|
return (
|
|
202
257
|
<ScrollArea className="h-[400px] pr-4">
|
|
203
258
|
<div className="space-y-3">
|
|
204
|
-
{
|
|
205
|
-
<
|
|
259
|
+
{signals.map(s => (
|
|
260
|
+
<SignalCard key={s.id} signal={s} />
|
|
206
261
|
))}
|
|
207
262
|
</div>
|
|
208
263
|
</ScrollArea>
|
|
@@ -210,7 +265,7 @@ export function EnvelopeList({ envelopes }: { envelopes: Envelope[] }) {
|
|
|
210
265
|
}
|
|
211
266
|
```
|
|
212
267
|
|
|
213
|
-
### Tooltip
|
|
268
|
+
### Tooltip
|
|
214
269
|
|
|
215
270
|
```tsx
|
|
216
271
|
import {
|
|
@@ -220,11 +275,11 @@ import {
|
|
|
220
275
|
TooltipTrigger,
|
|
221
276
|
} from "@/components/ui/tooltip";
|
|
222
277
|
|
|
223
|
-
export function
|
|
278
|
+
export function SignalId({ id, full }: { id: string; full: string }) {
|
|
224
279
|
return (
|
|
225
280
|
<TooltipProvider>
|
|
226
281
|
<Tooltip>
|
|
227
|
-
<TooltipTrigger className="font-mono text-
|
|
282
|
+
<TooltipTrigger className="font-mono text-primary cursor-help">
|
|
228
283
|
{id}
|
|
229
284
|
</TooltipTrigger>
|
|
230
285
|
<TooltipContent>
|
|
@@ -236,7 +291,7 @@ export function EnvelopeId({ id, full }: { id: string; full: string }) {
|
|
|
236
291
|
}
|
|
237
292
|
```
|
|
238
293
|
|
|
239
|
-
### Accordion
|
|
294
|
+
### Accordion
|
|
240
295
|
|
|
241
296
|
```tsx
|
|
242
297
|
import {
|
|
@@ -246,16 +301,14 @@ import {
|
|
|
246
301
|
AccordionTrigger,
|
|
247
302
|
} from "@/components/ui/accordion";
|
|
248
303
|
|
|
249
|
-
export function
|
|
304
|
+
export function ConfigViewer({ code }: { code: string }) {
|
|
250
305
|
return (
|
|
251
|
-
<Accordion type="single" collapsible defaultValue="
|
|
252
|
-
<AccordionItem value="
|
|
253
|
-
<AccordionTrigger className="text-sm">
|
|
254
|
-
Agent Logic
|
|
255
|
-
</AccordionTrigger>
|
|
306
|
+
<Accordion type="single" collapsible defaultValue="config">
|
|
307
|
+
<AccordionItem value="config">
|
|
308
|
+
<AccordionTrigger className="text-sm">Step config</AccordionTrigger>
|
|
256
309
|
<AccordionContent>
|
|
257
|
-
<pre className="p-4 bg-
|
|
258
|
-
<code className="text-
|
|
310
|
+
<pre className="p-4 bg-background rounded font-mono text-xs overflow-x-auto">
|
|
311
|
+
<code className="text-font/80">{code}</code>
|
|
259
312
|
</pre>
|
|
260
313
|
</AccordionContent>
|
|
261
314
|
</AccordionItem>
|
|
@@ -269,21 +322,18 @@ export function LogicViewer({ code }: { code: string }) {
|
|
|
269
322
|
### Status Dot
|
|
270
323
|
|
|
271
324
|
```tsx
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
idle: "bg-slate-500",
|
|
278
|
-
error: "bg-red-500",
|
|
279
|
-
rejected: "bg-red-500",
|
|
325
|
+
const dotClasses = {
|
|
326
|
+
resolved: "bg-success",
|
|
327
|
+
pending: "bg-secondary animate-pulse",
|
|
328
|
+
idle: "bg-font/40",
|
|
329
|
+
error: "bg-destructive",
|
|
280
330
|
};
|
|
281
331
|
|
|
282
332
|
export function StatusDot({ status }: { status: string }) {
|
|
283
333
|
return (
|
|
284
334
|
<span
|
|
285
335
|
className={`inline-block w-2 h-2 rounded-full ${
|
|
286
|
-
|
|
336
|
+
dotClasses[status as keyof typeof dotClasses] ?? dotClasses.idle
|
|
287
337
|
}`}
|
|
288
338
|
/>
|
|
289
339
|
);
|
|
@@ -293,24 +343,20 @@ export function StatusDot({ status }: { status: string }) {
|
|
|
293
343
|
### Panel Header
|
|
294
344
|
|
|
295
345
|
```tsx
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
children,
|
|
300
|
-
}: {
|
|
346
|
+
import { Badge } from "@/components/ui/badge";
|
|
347
|
+
|
|
348
|
+
interface PanelHeaderProps {
|
|
301
349
|
title: string;
|
|
302
350
|
count?: number;
|
|
303
351
|
children?: React.ReactNode;
|
|
304
|
-
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
export function PanelHeader({ title, count, children }: PanelHeaderProps) {
|
|
305
355
|
return (
|
|
306
356
|
<div className="flex items-center justify-between mb-4">
|
|
307
357
|
<div className="flex items-center gap-2">
|
|
308
|
-
<h3 className="text-sm font-medium text-
|
|
309
|
-
{count !== undefined &&
|
|
310
|
-
<Badge variant="secondary" className="bg-[#1e293b]">
|
|
311
|
-
{count}
|
|
312
|
-
</Badge>
|
|
313
|
-
)}
|
|
358
|
+
<h3 className="text-sm font-medium text-font/80">{title}</h3>
|
|
359
|
+
{count !== undefined && <Badge variant="secondary">{count}</Badge>}
|
|
314
360
|
</div>
|
|
315
361
|
{children}
|
|
316
362
|
</div>
|
|
@@ -321,18 +367,19 @@ export function PanelHeader({
|
|
|
321
367
|
### Code Block
|
|
322
368
|
|
|
323
369
|
```tsx
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
}: {
|
|
370
|
+
import { Card, CardContent } from "@/components/ui/card";
|
|
371
|
+
|
|
372
|
+
interface CodeBlockProps {
|
|
328
373
|
code: string;
|
|
329
374
|
language?: string;
|
|
330
|
-
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
export function CodeBlock({ code, language = "typescript" }: CodeBlockProps) {
|
|
331
378
|
return (
|
|
332
|
-
<Card
|
|
379
|
+
<Card data-language={language}>
|
|
333
380
|
<CardContent className="p-0">
|
|
334
381
|
<pre className="p-4 overflow-x-auto">
|
|
335
|
-
<code className="font-mono text-xs text-
|
|
382
|
+
<code className="font-mono text-xs text-font/80 whitespace-pre">
|
|
336
383
|
{code}
|
|
337
384
|
</code>
|
|
338
385
|
</pre>
|
|
@@ -344,31 +391,39 @@ export function CodeBlock({
|
|
|
344
391
|
|
|
345
392
|
## Adding New Components
|
|
346
393
|
|
|
347
|
-
To add a new shadcn component:
|
|
348
|
-
|
|
349
394
|
```bash
|
|
350
|
-
#
|
|
351
|
-
bunx shadcn@latest add [component-name]
|
|
352
|
-
|
|
353
|
-
# Examples
|
|
395
|
+
# from one.ie/web (components.json lives there)
|
|
354
396
|
bunx shadcn@latest add sheet
|
|
355
397
|
bunx shadcn@latest add command
|
|
356
398
|
bunx shadcn@latest add popover
|
|
357
399
|
```
|
|
358
400
|
|
|
401
|
+
**Always run the token pass immediately after.** The CLI writes upstream defaults
|
|
402
|
+
that assume Tailwind's palette exists:
|
|
403
|
+
|
|
404
|
+
```bash
|
|
405
|
+
grep -nE 'text-foreground|#[0-9a-fA-F]{3,8}|(bg|text|border)-(zinc|slate|gray|neutral|red|green|blue|amber)-[0-9]' \
|
|
406
|
+
src/components/ui/<new>.tsx
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
Every hit is a fix: `text-foreground` → `text-font`; a palette class → a token
|
|
410
|
+
utility or an alias from the table above; a hex → a token. The `design-check.sh`
|
|
411
|
+
PostToolUse hook catches these on your next edit of the file, but the CLI writes
|
|
412
|
+
the file without going through the hook — so sweep it yourself.
|
|
413
|
+
|
|
359
414
|
## Customization Patterns
|
|
360
415
|
|
|
361
416
|
### Extending Button
|
|
362
417
|
|
|
363
418
|
```tsx
|
|
364
|
-
// src/components/ui/button.tsx
|
|
419
|
+
// src/components/ui/button.tsx — add to the existing cva variants block
|
|
365
420
|
const buttonVariants = cva(
|
|
366
421
|
"...",
|
|
367
422
|
{
|
|
368
423
|
variants: {
|
|
369
424
|
variant: {
|
|
370
|
-
// ...
|
|
371
|
-
|
|
425
|
+
// ... default | outline | secondary | ghost | destructive | link
|
|
426
|
+
brand: "bg-tertiary text-on-tertiary hover:bg-tertiary/80",
|
|
372
427
|
},
|
|
373
428
|
},
|
|
374
429
|
}
|
|
@@ -378,20 +433,17 @@ const buttonVariants = cva(
|
|
|
378
433
|
### Custom Card Variant
|
|
379
434
|
|
|
380
435
|
```tsx
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
436
|
+
import { Card } from "@/components/ui/card";
|
|
437
|
+
import { cn } from "@/lib/utils";
|
|
438
|
+
|
|
439
|
+
interface NestedCardProps {
|
|
385
440
|
children: React.ReactNode;
|
|
386
441
|
isNested?: boolean;
|
|
387
|
-
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
export function NestedCard({ children, isNested }: NestedCardProps) {
|
|
388
445
|
return (
|
|
389
|
-
<Card
|
|
390
|
-
className={cn(
|
|
391
|
-
"bg-[#0f0f14] border-[#1e293b]",
|
|
392
|
-
isNested && "ml-4 border-l-2 border-l-blue-500/30"
|
|
393
|
-
)}
|
|
394
|
-
>
|
|
446
|
+
<Card className={cn(isNested && "ml-4 border-l-2 border-l-primary")}>
|
|
395
447
|
{children}
|
|
396
448
|
</Card>
|
|
397
449
|
);
|
|
@@ -403,20 +455,24 @@ export function EnvelopeCardVariant({
|
|
|
403
455
|
### Two-Panel Layout
|
|
404
456
|
|
|
405
457
|
```tsx
|
|
406
|
-
|
|
458
|
+
import { ScrollArea } from "@/components/ui/scroll-area";
|
|
459
|
+
|
|
460
|
+
export function WorkspaceLayout({ actors, signals }: { actors: Actor[]; signals: Signal[] }) {
|
|
407
461
|
return (
|
|
408
|
-
<div className="h-screen flex flex-col bg-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
462
|
+
<div className="h-screen flex flex-col bg-background">
|
|
463
|
+
<div
|
|
464
|
+
className="flex-none h-[40%] border-b p-4"
|
|
465
|
+
style={{ borderColor: 'var(--color-border)' }}
|
|
466
|
+
>
|
|
467
|
+
<ActorTabs actors={actors} />
|
|
412
468
|
</div>
|
|
413
469
|
|
|
414
|
-
{/* Bottom Panel - Envelopes & Logic */}
|
|
415
470
|
<div className="flex-1 overflow-hidden p-4">
|
|
416
471
|
<ScrollArea className="h-full">
|
|
417
|
-
<
|
|
472
|
+
<SignalList signals={signals} />
|
|
418
473
|
</ScrollArea>
|
|
419
474
|
</div>
|
|
475
|
+
{/* ActorTabs / SignalList as defined above */}
|
|
420
476
|
</div>
|
|
421
477
|
);
|
|
422
478
|
}
|
|
@@ -425,48 +481,36 @@ export function WorkspaceLayout() {
|
|
|
425
481
|
### Grid Layout
|
|
426
482
|
|
|
427
483
|
```tsx
|
|
428
|
-
|
|
484
|
+
import { ActorCard } from "./ActorCard";
|
|
485
|
+
|
|
486
|
+
export function ActorGrid({ actors }: { actors: Actor[] }) {
|
|
429
487
|
return (
|
|
430
488
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
431
|
-
{
|
|
432
|
-
<
|
|
489
|
+
{actors.map(actor => (
|
|
490
|
+
<ActorCard key={actor.id} actor={actor} />
|
|
433
491
|
))}
|
|
434
492
|
</div>
|
|
435
493
|
);
|
|
436
494
|
}
|
|
437
495
|
```
|
|
438
496
|
|
|
439
|
-
## Utils
|
|
440
|
-
|
|
441
|
-
The project uses `cn()` utility for class merging:
|
|
442
|
-
|
|
443
|
-
```tsx
|
|
444
|
-
// src/lib/utils.ts
|
|
445
|
-
import { clsx, type ClassValue } from "clsx";
|
|
446
|
-
import { twMerge } from "tailwind-merge";
|
|
447
|
-
|
|
448
|
-
export function cn(...inputs: ClassValue[]) {
|
|
449
|
-
return twMerge(clsx(inputs));
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
// Usage
|
|
453
|
-
<div className={cn(
|
|
454
|
-
"base-classes",
|
|
455
|
-
isActive && "active-classes",
|
|
456
|
-
className
|
|
457
|
-
)} />
|
|
458
|
-
```
|
|
459
|
-
|
|
460
497
|
## Best Practices
|
|
461
498
|
|
|
462
|
-
1. **
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
499
|
+
1. **Let the primitive keep its surface**: `Card` already resolves to `foreground`
|
|
500
|
+
through `--color-card`. Adding `bg-*` on top fights the alias.
|
|
501
|
+
2. **`text-font`, never `text-foreground`**: the one shadcn name the alias table
|
|
502
|
+
cannot rescue.
|
|
503
|
+
3. **Contrast labels on brand fills**: `text-on-primary` in ONE code,
|
|
504
|
+
`text-primary-foreground` inside a CLI-generated primitive — both resolve to
|
|
505
|
+
the same computed color.
|
|
506
|
+
4. **Variants over overrides**: extend the `cva` block rather than passing a
|
|
507
|
+
className that re-colors the button.
|
|
508
|
+
5. **Sweep after `shadcn add`**: the CLI bypasses the design hook.
|
|
509
|
+
6. **Monospace for data**: `font-mono` for IDs, JSON, code.
|
|
510
|
+
7. **Icons from lucide only**: via `<Icon>` / `<IconBadge>`, never inline SVG in
|
|
511
|
+
a React component.
|
|
468
512
|
|
|
469
513
|
---
|
|
470
514
|
|
|
471
|
-
**
|
|
472
|
-
**
|
|
515
|
+
**Tech**: shadcn/ui (`style: radix-nova`) · `radix-ui` ^1.4.3 · Tailwind CSS 4 · React 19
|
|
516
|
+
**Tree**: `one.ie/web` — for `template/site` use `template:shadcn`
|