@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 +51 -1
- package/package.json +6 -1
- package/src/components/command-palette.tsx +702 -0
- package/src/components/kbd.tsx +117 -0
- package/src/components/workers/creator-avatar.tsx +38 -0
- package/src/components/workers/git-branch-chips.tsx +128 -0
- package/src/components/workers/index.ts +35 -0
- package/src/components/workers/resource-bars.tsx +104 -0
- package/src/components/workers/setup-progress.tsx +130 -0
- package/src/components/workers/tag-chips.tsx +139 -0
- package/src/components/workers/tag-color.ts +28 -0
- package/src/components/workers/types.ts +44 -0
- package/src/components/workers/worker-card.tsx +345 -0
- package/src/components/workers/worker-status.tsx +181 -0
- package/src/index.ts +40 -1
- package/src/utils.ts +23 -0
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.
|
|
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": {
|