@spunto/design-system 0.9.2 → 0.10.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/README.md CHANGED
@@ -40,7 +40,9 @@ const nextConfig = { transpilePackages: ["@spunto/design-system"] }
40
40
  - **`./colors`** — `cssVar`, `chartColors`, `chartRamp`, `segColors` for JS/chart contexts.
41
41
  - **Primitives** — form + layout building blocks styled on `@base-ui/react`:
42
42
  - _Basics_ — `Button` (+`buttonVariants`), `Card` (+parts), `Badge` (+`badgeVariants`),
43
- `Separator`, `Spinner`, `Skeleton`, `Avatar` (+`AvatarImage`/`AvatarFallback`).
43
+ `Separator`, `Spinner`, `Skeleton`, `Avatar` (+`AvatarImage`/`AvatarFallback`),
44
+ `Kbd` — one keyboard cap, or a whole shortcut (`keys="mod+k"` → ⌘ K, Ctrl K off Apple),
45
+ spelled out for screen readers.
44
46
  - _Forms_ — `Input`, `Textarea`, `Label`, `Switch`, `Checkbox`,
45
47
  `RadioGroup` (+`RadioGroupItem`), `Select` (+`SelectTrigger`/`SelectValue`/
46
48
  `SelectContent`/`SelectItem`/`SelectGroup`/`SelectGroupLabel`/`SelectSeparator`).
@@ -51,6 +53,20 @@ const nextConfig = { transpilePackages: ["@spunto/design-system"] }
51
53
  (a confirmation variant, non-dismissible), `Tooltip`. Their portals render into
52
54
  the provider's overlay container; `Tooltip`'s shared delay group is mounted by the
53
55
  provider too.
56
+ - _CommandPalette_ — `CommandPalette` (+`CommandPaletteInput`/`List`/`Group`/`Item`/
57
+ `Empty`/`Loading`/`Separator`/`Footer`/`Trigger`), the ⌘K palette: an input, groups,
58
+ items, and a jump. **Domain-free**, hence its place in the root entry — it knows
59
+ nothing of projects, workers or deployments; those are items the app hands it. Base UI
60
+ `Autocomplete` (combobox/listbox roles, `aria-activedescendant`, ↑↓ + scroll-into-view,
61
+ ↵ activates the highlighted item) rendered *inline* inside a Base UI `Dialog` (focus
62
+ trap, focus restore, Escape, backdrop), portalled into the provider's overlay container
63
+ like the other overlays. Compositional like `Dialog`/`Select`, not a config array —
64
+ which is why the root runs Base UI in `mode="none"` and each item decides for itself
65
+ whether it matches, with the same `Autocomplete.useFilter()` collator. Presentational
66
+ only: `loading` is a prop, results are children, and a server-side search is
67
+ `value`/`onValueChange` + `filter={null}`. Navigation is `href` + `render.link`, never
68
+ `next/link` — same rule as `WorkerCard`. Not virtualized: a few hundred items stay
69
+ fluid (a non-matching item renders nothing), beyond that filter server-side.
54
70
  - _Terminal_ — `Terminal` (+`TerminalHandle`, `TerminalOptions`), a transport-agnostic
55
71
  xterm.js surface: mount, shared dark ANSI theme, fit-on-resize. No opinion on where
56
72
  bytes come from (WebSocket, SSE, a static string) — feed it via the `write`/`writeln`
@@ -73,6 +89,36 @@ const nextConfig = { transpilePackages: ["@spunto/design-system"] }
73
89
  provider is also the umbrella that mounts the tooltip delay group and the overlay
74
90
  portal container the dialogs/selects render into.
75
91
 
92
+ ## Domain components — `@spunto/design-system/workers`
93
+
94
+ Everything above is domain-free: a `Button` knows nothing about Spunto. Components
95
+ that **do** know a Spunto concept live behind their own entry point, so the root
96
+ export stays primitives-only and a third-party consumer never carries the notion
97
+ of a worker. **The rule for what comes next: any new component that knows a domain
98
+ concept goes behind a domain sub-export, never in the root entry.**
99
+
100
+ ```tsx
101
+ import { Button, Card } from "@spunto/design-system" // primitives
102
+ import { WorkerCard } from "@spunto/design-system/workers" // domain
103
+ ```
104
+
105
+ - **`WorkerCard`** — a Spunto worker as a card: state, author, node, setup
106
+ progress, git branches, resources, banners, actions. **Purely presentational** —
107
+ hand it a snapshot plus slots and it draws. The rule that keeps it that way:
108
+ *everything that CALLS the API is a slot or a callback; everything that DRAWS is
109
+ in the component.* So the `⋯` menu (`actions`), the footer (`footer`), the link
110
+ (`href` + `render.link`, never `next/link`), the rebuild (`onRebuild`) and the
111
+ tag persistence (`onAddTag`/`onRemoveTag`) all stay in the app.
112
+ - **Its bricks, exported individually** because the table view assembles them
113
+ differently: `WorkerStatusDot`/`WorkerStatusPill` (+`resolveWorkerStatus`,
114
+ `workerStatusConfig`), `SetupProgress` (+`setupProgress`, `phaseLabel`,
115
+ `setupTotalMs`), `StepIndicator`, `ResourceBars`, `GitBranchChips`/
116
+ `GitStatusSummary`, `TagChips` (+`tagColor`), `CreatorAvatar`.
117
+ - **Types are structural**, never the apps' OpenAPI types: the dashboard and
118
+ Spunto Lite model a worker differently, so `WorkerCardWorker` asks for the
119
+ minimum, everything optional but `id`, and an unknown state falls back to
120
+ `pending` instead of throwing.
121
+
76
122
  ## Toasts — `SpuntoProvider` + `toast()`
77
123
 
78
124
  `SpuntoProvider` is the design system's client umbrella provider. Mount it once
@@ -145,3 +191,7 @@ automatically (see `showcase/vite-plugin-llms.ts`).
145
191
  ## Peer requirements
146
192
 
147
193
  - React 19+, and a **Tailwind CSS v4** pipeline in the consuming app.
194
+ - `lucide-react` is a **regular dependency** (since `0.9.3`): the worker
195
+ components use ~15 icons, and inlining them as SVG or passing them all as props
196
+ would have been worse than the dependency. It's tree-shakable and both apps
197
+ already ship it.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spunto/design-system",
3
- "version": "0.9.2",
3
+ "version": "0.10.0",
4
4
  "description": "Spunto's shared design system — warm/flame tokens, color constants, and UI primitives.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -33,6 +33,10 @@
33
33
  "types": "./src/colors.ts",
34
34
  "import": "./src/colors.ts"
35
35
  },
36
+ "./workers": {
37
+ "types": "./src/components/workers/index.ts",
38
+ "import": "./src/components/workers/index.ts"
39
+ },
36
40
  "./fonts": {
37
41
  "types": "./src/components/fonts.tsx",
38
42
  "import": "./src/components/fonts.tsx"
@@ -54,6 +58,7 @@
54
58
  "@xterm/xterm": "^6.0.0",
55
59
  "class-variance-authority": "^0.7.1",
56
60
  "clsx": "^2.1.1",
61
+ "lucide-react": "^1.7.0",
57
62
  "tailwind-merge": "^3.6.0"
58
63
  },
59
64
  "peerDependencies": {