@substrate-kit/cli 0.1.1 → 0.2.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.
Files changed (146) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/LICENSE +21 -0
  3. package/README.md +25 -8
  4. package/dist/cli.d.ts.map +1 -1
  5. package/dist/cli.js +10 -60
  6. package/dist/cli.js.map +1 -1
  7. package/dist/commands/add.d.ts +1 -0
  8. package/dist/commands/add.d.ts.map +1 -1
  9. package/dist/commands/add.js +51 -106
  10. package/dist/commands/add.js.map +1 -1
  11. package/dist/commands/docs.d.ts +4 -2
  12. package/dist/commands/docs.d.ts.map +1 -1
  13. package/dist/commands/docs.js +33 -54
  14. package/dist/commands/docs.js.map +1 -1
  15. package/dist/commands/init.d.ts.map +1 -1
  16. package/dist/commands/init.js +158 -122
  17. package/dist/commands/init.js.map +1 -1
  18. package/dist/index.js +0 -0
  19. package/dist/mcp/server.d.ts.map +1 -1
  20. package/dist/mcp/server.js +8 -7
  21. package/dist/mcp/server.js.map +1 -1
  22. package/dist/mcp/tools/get-component.d.ts +1 -1
  23. package/dist/mcp/tools/get-component.d.ts.map +1 -1
  24. package/dist/mcp/tools/get-component.js +10 -6
  25. package/dist/mcp/tools/get-component.js.map +1 -1
  26. package/dist/mcp/tools/get-docs.d.ts +17 -0
  27. package/dist/mcp/tools/get-docs.d.ts.map +1 -0
  28. package/dist/mcp/tools/get-docs.js +23 -0
  29. package/dist/mcp/tools/get-docs.js.map +1 -0
  30. package/dist/mcp/tools/install.d.ts +2 -1
  31. package/dist/mcp/tools/install.d.ts.map +1 -1
  32. package/dist/mcp/tools/install.js +19 -30
  33. package/dist/mcp/tools/install.js.map +1 -1
  34. package/dist/mcp/tools/search.d.ts +1 -1
  35. package/dist/mcp/tools/search.d.ts.map +1 -1
  36. package/dist/mcp/tools/search.js +2 -4
  37. package/dist/mcp/tools/search.js.map +1 -1
  38. package/dist/{mcp/types.d.ts → registry.d.ts} +6 -1
  39. package/dist/registry.d.ts.map +1 -0
  40. package/dist/registry.js +48 -0
  41. package/dist/registry.js.map +1 -0
  42. package/dist/utils/agents-file.d.ts +4 -0
  43. package/dist/utils/agents-file.d.ts.map +1 -0
  44. package/dist/utils/agents-file.js +36 -0
  45. package/dist/utils/agents-file.js.map +1 -0
  46. package/dist/utils/docs.d.ts +7 -0
  47. package/dist/utils/docs.d.ts.map +1 -0
  48. package/dist/utils/docs.js +28 -0
  49. package/dist/utils/docs.js.map +1 -0
  50. package/dist/utils/shadcn.d.ts +12 -0
  51. package/dist/utils/shadcn.d.ts.map +1 -0
  52. package/dist/utils/shadcn.js +29 -0
  53. package/dist/utils/shadcn.js.map +1 -0
  54. package/dist/utils/version.d.ts +3 -0
  55. package/dist/utils/version.d.ts.map +1 -0
  56. package/dist/utils/version.js +8 -0
  57. package/dist/utils/version.js.map +1 -0
  58. package/docs/components/action.mdx +30 -0
  59. package/docs/components/alignment-controls.mdx +30 -0
  60. package/docs/components/badge.mdx +22 -0
  61. package/docs/components/breadcrumbs.mdx +25 -0
  62. package/docs/components/collapsible-pane.mdx +35 -0
  63. package/docs/components/colour-picker.mdx +66 -0
  64. package/docs/components/command-palette.mdx +36 -0
  65. package/docs/components/context-menu.mdx +31 -0
  66. package/docs/components/controls-timeline.mdx +107 -0
  67. package/docs/components/controls.mdx +168 -0
  68. package/docs/components/design-canvas.mdx +51 -0
  69. package/docs/components/document-tabs.mdx +25 -0
  70. package/docs/components/easing-curve-editor.mdx +85 -0
  71. package/docs/components/empty-state.mdx +26 -0
  72. package/docs/components/gallery.mdx +60 -0
  73. package/docs/components/history-controls.mdx +47 -0
  74. package/docs/components/image-picker.mdx +50 -0
  75. package/docs/components/layer-list.mdx +36 -0
  76. package/docs/components/node.mdx +85 -0
  77. package/docs/components/number-input.mdx +44 -0
  78. package/docs/components/number-slider.mdx +32 -0
  79. package/docs/components/pane.mdx +39 -0
  80. package/docs/components/panel.mdx +28 -0
  81. package/docs/components/popover.mdx +32 -0
  82. package/docs/components/progress-bar.mdx +24 -0
  83. package/docs/components/resizer.mdx +24 -0
  84. package/docs/components/select.mdx +31 -0
  85. package/docs/components/shortcut-overlay.mdx +43 -0
  86. package/docs/components/slider.mdx +20 -0
  87. package/docs/components/spring-editor.mdx +85 -0
  88. package/docs/components/status-bar.mdx +42 -0
  89. package/docs/components/surface.mdx +47 -0
  90. package/docs/components/swatch-palette.mdx +36 -0
  91. package/docs/components/text-area.mdx +26 -0
  92. package/docs/components/timeline.mdx +96 -0
  93. package/docs/components/toast.mdx +42 -0
  94. package/docs/components/toggle-group.mdx +40 -0
  95. package/docs/components/toggle.mdx +27 -0
  96. package/docs/components/toolbar.mdx +24 -0
  97. package/docs/components/tree-list.mdx +46 -0
  98. package/docs/components/xy-pad.mdx +49 -0
  99. package/docs/hooks/use-clipboard.mdx +70 -0
  100. package/docs/hooks/use-drag-reorder.mdx +60 -0
  101. package/docs/hooks/use-selection.mdx +68 -0
  102. package/docs/hooks/use-undoable.mdx +83 -0
  103. package/docs/hooks/use-viewport.mdx +75 -0
  104. package/docs/utilities/bounding-box.mdx +76 -0
  105. package/docs/utilities/keyboard-shortcuts.mdx +64 -0
  106. package/docs/utilities/snap.mdx +73 -0
  107. package/package.json +6 -3
  108. package/registry.json +331 -16
  109. package/skills/3d-scene/SKILL.md +2 -1
  110. package/skills/animation/SKILL.md +2 -1
  111. package/skills/canvas-2d/SKILL.md +68 -6
  112. package/skills/composing-panels/SKILL.md +9 -12
  113. package/skills/data-visualisation/SKILL.md +2 -1
  114. package/skills/image-generation/SKILL.md +2 -1
  115. package/skills/install-components/SKILL.md +22 -16
  116. package/skills/scaffold-playground/SKILL.md +42 -22
  117. package/skills/substrate-canvas/SKILL.md +5 -0
  118. package/skills/substrate-controls/SKILL.md +57 -2
  119. package/skills/substrate-interaction/SKILL.md +19 -10
  120. package/skills/substrate-scaffold/SKILL.md +4 -4
  121. package/skills/theming/SKILL.md +8 -2
  122. package/skills/wire-interactions/SKILL.md +6 -3
  123. package/templates/agents-section.md +41 -0
  124. package/dist/commands/browse.d.ts +0 -2
  125. package/dist/commands/browse.d.ts.map +0 -1
  126. package/dist/commands/browse.js +0 -25
  127. package/dist/commands/browse.js.map +0 -1
  128. package/dist/commands/create.d.ts +0 -9
  129. package/dist/commands/create.d.ts.map +0 -1
  130. package/dist/commands/create.js +0 -415
  131. package/dist/commands/create.js.map +0 -1
  132. package/dist/commands/variables.d.ts +0 -4
  133. package/dist/commands/variables.d.ts.map +0 -1
  134. package/dist/commands/variables.js +0 -111
  135. package/dist/commands/variables.js.map +0 -1
  136. package/dist/mcp/registry.d.ts +0 -3
  137. package/dist/mcp/registry.d.ts.map +0 -1
  138. package/dist/mcp/registry.js +0 -43
  139. package/dist/mcp/registry.js.map +0 -1
  140. package/dist/mcp/tools/theme.d.ts +0 -10
  141. package/dist/mcp/tools/theme.d.ts.map +0 -1
  142. package/dist/mcp/tools/theme.js +0 -37
  143. package/dist/mcp/tools/theme.js.map +0 -1
  144. package/dist/mcp/types.d.ts.map +0 -1
  145. package/dist/mcp/types.js +0 -2
  146. package/dist/mcp/types.js.map +0 -1
@@ -0,0 +1,36 @@
1
+ ---
2
+ title: Layer list
3
+ description: Reorderable layer panel with visibility, lock toggles, and inline rename.
4
+ ---
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ npx shadcn@latest add https://substrate.georgedrury.co.uk/r/layer-list
10
+ ```
11
+
12
+ ## Examples
13
+
14
+ ### Default
15
+
16
+ <ComponentPreview name="layer-list-demo" />
17
+
18
+ ## Interaction
19
+
20
+ - **Click** a row to select it.
21
+ - **Double-click** the name to rename inline. Press Enter to confirm or Escape to cancel.
22
+ - **Visibility toggle** — hides/shows the layer.
23
+ - **Lock toggle** — locks the layer to prevent selection or editing.
24
+
25
+ ## Components
26
+
27
+ | Component | Description |
28
+ | ----------------------- | ------------------------------------------------ |
29
+ | `LayerList` | Vertical flex container for layer items |
30
+ | `LayerItem` | Row with selection, hover, and depth indentation |
31
+ | `LayerIcon` | Colour dot or icon thumbnail |
32
+ | `LayerName` | Truncated name with double-click-to-rename |
33
+ | `LayerActions` | Right-aligned action slot, visible on hover |
34
+ | `LayerToggle` | Generic toggle button for layer actions |
35
+ | `LayerVisibilityToggle` | Convenience eye/eye-off toggle |
36
+ | `LayerLockToggle` | Convenience lock/unlock toggle |
@@ -0,0 +1,85 @@
1
+ ---
2
+ title: Node
3
+ description: Compound card for node-based editors – typed ports, composable body, and themeable port colours via CSS variables.
4
+ ---
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ npx shadcn@latest add https://substrate.georgedrury.co.uk/r/node
10
+ ```
11
+
12
+ ## Examples
13
+
14
+ ### Default
15
+
16
+ Three node types demonstrating the component anatomy: a filter node with controls, a generator node with colour and dimensions, and an output node with a preview area.
17
+
18
+ <ComponentPreview name="node-demo" />
19
+
20
+ ### Port types
21
+
22
+ Each port type maps to a CSS variable that consumers can override to match their brand.
23
+
24
+ <ComponentPreview name="node-port-types" />
25
+
26
+ ## Port type system
27
+
28
+ Ports are typed. Each type has a corresponding CSS variable for its colour:
29
+
30
+ | Type | CSS variable | Default |
31
+ | ---------- | ---------------------- | ------- |
32
+ | `number` | `--node-port-number` | Blue |
33
+ | `colour` | `--node-port-colour` | Pink |
34
+ | `image` | `--node-port-image` | Purple |
35
+ | `geometry` | `--node-port-geometry` | Green |
36
+ | `text` | `--node-port-text` | Amber |
37
+ | `boolean` | `--node-port-boolean` | Orange |
38
+ | `any` | `--node-port-any` | Grey |
39
+
40
+ Override any of these in your `globals.css` to change port colours globally.
41
+
42
+ ## Node chrome variables
43
+
44
+ | Variable | Tailwind class | Fallback | Description |
45
+ | ----------------- | -------------------- | ---------- | --------------------- |
46
+ | `--node-bg` | `bg-node-bg` | `--card` | Card background |
47
+ | `--node-border` | `border-node-border` | `--border` | Card border |
48
+ | `--node-header` | `bg-node-header` | `--muted` | Header background |
49
+ | `--node-selected` | `ring-node-selected` | `--ring` | Selection ring colour |
50
+
51
+ ## Components
52
+
53
+ | Component | Description |
54
+ | ------------- | --------------------------------------------------------------- |
55
+ | `NodeCard` | Outer card with border, shadow, and selected ring |
56
+ | `NodeHeader` | Title bar with optional custom `colour` background |
57
+ | `NodeTitle` | Truncated title text |
58
+ | `NodeBadge` | Small type/category badge in the header |
59
+ | `NodeBody` | Content area for controls (compose Action, NumberSlider, etc.) |
60
+ | `NodePorts` | Vertical list of input/output ports |
61
+ | `NodePort` | A single typed port with dot, label, and direction |
62
+ | `NodePortDot` | Coloured dot indicator (filled when connected, hollow when not) |
63
+ | `NodePreview` | Optional image/canvas preview area |
64
+ | `NodeDivider` | Horizontal separator between sections |
65
+
66
+ ## Composing node bodies
67
+
68
+ The body of a node uses the same components you'd use in a panel pane. ActionControls automatically adapts nested components:
69
+
70
+ ```tsx
71
+ <NodeBody>
72
+ <Action>
73
+ <ActionLabel>Radius</ActionLabel>
74
+ <ActionControls>
75
+ <NumberSlider
76
+ value={blur}
77
+ onChange={setBlur}
78
+ min={0}
79
+ max={50}
80
+ suffix="px"
81
+ />
82
+ </ActionControls>
83
+ </Action>
84
+ </NodeBody>
85
+ ```
@@ -0,0 +1,44 @@
1
+ ---
2
+ title: Number input
3
+ description: Numeric input with drag-to-scrub on the label, arrow key stepping, and shift for larger increments.
4
+ ---
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ npx shadcn@latest add https://substrate.georgedrury.co.uk/r/number-input
10
+ ```
11
+
12
+ ## Examples
13
+
14
+ ### Default
15
+
16
+ <ComponentPreview name="number-input-demo" />
17
+
18
+ ### With labels and suffix
19
+
20
+ <ComponentPreview name="number-input-labels" />
21
+
22
+ ## Interaction
23
+
24
+ - **Drag on label** — pointer left/right to scrub the value. Hold Shift for larger increments.
25
+ - **Arrow keys** — Up/Down to step the value when the input is focused. Hold Shift for `shiftStep`.
26
+ - **Click label** — focuses and selects the input for direct typing.
27
+ - **Enter** — commits the typed value.
28
+ - **Escape** — cancels editing and blurs.
29
+
30
+ ## Props
31
+
32
+ | Prop | Type | Default | Description |
33
+ | ----------- | ------------------------- | ------- | --------------------------------------------------------------------------------------- |
34
+ | `value` | `number` | — | Current value |
35
+ | `onChange` | `(value: number) => void` | — | Called when the value changes |
36
+ | `onStart` | `() => void` | — | Called once at the start of a drag or before a step. Useful for pushing undo snapshots. |
37
+ | `label` | `string` | — | Inline label with drag-to-scrub cursor |
38
+ | `suffix` | `string` | — | Trailing text (e.g. `°`, `%`, `px`) |
39
+ | `min` | `number` | — | Minimum value |
40
+ | `max` | `number` | — | Maximum value |
41
+ | `step` | `number` | `1` | Increment per pixel of drag or arrow key press |
42
+ | `shiftStep` | `number` | `10` | Increment when Shift is held |
43
+ | `precision` | `number` | `2` | Decimal places for display |
44
+ | `disabled` | `boolean` | — | Disables input and drag |
@@ -0,0 +1,32 @@
1
+ ---
2
+ title: Number slider
3
+ description: Linked slider and numeric input – drag the track or type a value.
4
+ ---
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ npx shadcn@latest add https://substrate.georgedrury.co.uk/r/number-slider
10
+ ```
11
+
12
+ ## Examples
13
+
14
+ ### Default
15
+
16
+ <ComponentPreview name="number-slider-demo" />
17
+
18
+ ## Props
19
+
20
+ | Prop | Type | Default | Description |
21
+ | ----------- | ------------------------- | ------- | ----------------------------------------------------------------- |
22
+ | `value` | `number` | — | Current value |
23
+ | `onChange` | `(value: number) => void` | — | Called when the value changes |
24
+ | `onStart` | `() => void` | — | Called once at the start of a gesture. Useful for undo snapshots. |
25
+ | `min` | `number` | `0` | Minimum value |
26
+ | `max` | `number` | `100` | Maximum value |
27
+ | `step` | `number` | `1` | Increment per step |
28
+ | `shiftStep` | `number` | `10` | Increment when Shift is held (number input only) |
29
+ | `precision` | `number` | `2` | Decimal places for display |
30
+ | `label` | `string` | — | Label on the number input (with drag-to-scrub) |
31
+ | `suffix` | `string` | — | Trailing text (e.g. `%`, `px`) |
32
+ | `disabled` | `boolean` | — | Disables both slider and input |
@@ -0,0 +1,39 @@
1
+ ---
2
+ title: Pane
3
+ description: Content section within a panel for composing property editors.
4
+ ---
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ npx shadcn@latest add https://substrate.georgedrury.co.uk/r/pane
10
+ ```
11
+
12
+ ## Examples
13
+
14
+ ### Default
15
+
16
+ <ComponentPreview name="pane-demo" />
17
+
18
+ ### With history controls
19
+
20
+ Drop `HistoryControls` (or individual `HistoryButton` elements) into a `PaneHeader` and they auto-push to the right and compact to match the header height.
21
+
22
+ <ComponentPreview name="pane-history" />
23
+
24
+ ## Theme variables
25
+
26
+ Pane inherits panel tokens. `PaneAction` uses `bg-panel` for its background.
27
+
28
+ | Variable | Tailwind class | Fallback | Description |
29
+ | --------- | -------------- | -------- | ------------------------ |
30
+ | `--panel` | `bg-panel` | `--card` | Action button background |
31
+
32
+ ## Components
33
+
34
+ | Component | Description |
35
+ | ------------ | ------------------------------------------------------ |
36
+ | `Pane` | Container with vertical spacing and horizontal padding |
37
+ | `PaneHeader` | Flex row for label + action |
38
+ | `PaneLabel` | Section title text |
39
+ | `PaneAction` | Button slot in the header |
@@ -0,0 +1,28 @@
1
+ ---
2
+ title: Panel
3
+ description: Side panel container with position variants and scroll area.
4
+ ---
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ npx shadcn@latest add https://substrate.georgedrury.co.uk/r/panel
10
+ ```
11
+
12
+ ## Examples
13
+
14
+ <ComponentPreview background="canvas" name="panel-demo" />
15
+
16
+ ## Theme variables
17
+
18
+ | Variable | Tailwind class | Fallback | Description |
19
+ | -------------------- | ----------------------- | ------------------- | ----------------------- |
20
+ | `--panel` | `bg-panel` | `--card` | Panel background colour |
21
+ | `--panel-foreground` | `text-panel-foreground` | `--card-foreground` | Panel text colour |
22
+
23
+ ## Props
24
+
25
+ | Prop | Type | Default | Description |
26
+ | ---------- | --------------------- | ----------- | -------------------------------------------------------- |
27
+ | `position` | `"left" \| "right"` | `"right"` | Which side the panel sits on. Controls border direction. |
28
+ | `variant` | `"tool" \| "default"` | `"default"` | Panel variant. Tool variant uses flex column layout. |
@@ -0,0 +1,32 @@
1
+ ---
2
+ title: Popover
3
+ description: Floating panel built on Radix Popover. Use for mini-inspectors, quick settings, and overflow controls.
4
+ ---
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ npx shadcn@latest add https://substrate.georgedrury.co.uk/r/popover
10
+ ```
11
+
12
+ ## Examples
13
+
14
+ ### Default
15
+
16
+ <ComponentPreview name="popover-demo" />
17
+
18
+ ## Components
19
+
20
+ | Component | Description |
21
+ | ---------------- | ---------------------------------- |
22
+ | `Popover` | Root wrapper (Radix Popover.Root) |
23
+ | `PopoverTrigger` | Element that opens the popover |
24
+ | `PopoverContent` | Floating panel with optional arrow |
25
+ | `PopoverClose` | Positioned close button |
26
+
27
+ ## Props (PopoverContent)
28
+
29
+ | Prop | Type | Default | Description |
30
+ | ------------ | --------- | ------- | ------------------------------- |
31
+ | `showArrow` | `boolean` | — | Show a directional arrow |
32
+ | `sideOffset` | `number` | `6` | Gap between trigger and popover |
@@ -0,0 +1,24 @@
1
+ ---
2
+ title: Progress bar
3
+ description: Thin progress indicator for exports, asset loading, and generation. Supports determinate and indeterminate states.
4
+ ---
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ npx shadcn@latest add https://substrate.georgedrury.co.uk/r/progress-bar
10
+ ```
11
+
12
+ ## Examples
13
+
14
+ ### Default
15
+
16
+ <ComponentPreview name="progress-bar-demo" />
17
+
18
+ ## Props
19
+
20
+ | Prop | Type | Default | Description |
21
+ | --------------- | --------- | ------- | ---------------------------------------- |
22
+ | `value` | `number` | — | Current progress value |
23
+ | `max` | `number` | `100` | Maximum value |
24
+ | `indeterminate` | `boolean` | — | Show an animated indeterminate indicator |
@@ -0,0 +1,24 @@
1
+ ---
2
+ title: Resizer
3
+ description: Drag handle for resizing adjacent panels or panes. Visual grab dots on hover.
4
+ ---
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ npx shadcn@latest add https://substrate.georgedrury.co.uk/r/resizer
10
+ ```
11
+
12
+ ## Examples
13
+
14
+ ### Default
15
+
16
+ Hover over the divider to see the grab dots.
17
+
18
+ <ComponentPreview name="resizer-demo" />
19
+
20
+ ## Props
21
+
22
+ | Prop | Type | Default | Description |
23
+ | ------------- | ------------------------------ | ------------ | ---------------- |
24
+ | `orientation` | `"horizontal"` \| `"vertical"` | `"vertical"` | Resize direction |
@@ -0,0 +1,31 @@
1
+ ---
2
+ title: Select
3
+ description: Dropdown select for blend modes, fonts, export formats. Built on Radix Select with ActionControls awareness.
4
+ ---
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ npx shadcn@latest add https://substrate.georgedrury.co.uk/r/select
10
+ ```
11
+
12
+ ## Examples
13
+
14
+ ### Default
15
+
16
+ Placed inside an `ActionControls` row, the trigger automatically loses its border and fills the available width.
17
+
18
+ <ComponentPreview name="select-demo" />
19
+
20
+ ## Components
21
+
22
+ | Component | Description |
23
+ | ----------------- | -------------------------------------- |
24
+ | `Select` | Root wrapper (Radix Select.Root) |
25
+ | `SelectTrigger` | Button that opens the dropdown |
26
+ | `SelectValue` | Displays the currently selected value |
27
+ | `SelectContent` | Dropdown panel with items |
28
+ | `SelectItem` | Selectable option with check indicator |
29
+ | `SelectGroup` | Labelled group of items |
30
+ | `SelectLabel` | Non-interactive group heading |
31
+ | `SelectSeparator` | Horizontal divider |
@@ -0,0 +1,43 @@
1
+ ---
2
+ title: Shortcut overlay
3
+ description: Modal showing all registered keyboard shortcuts, triggered by pressing ?.
4
+ ---
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ npx shadcn@latest add https://substrate.georgedrury.co.uk/r/shortcut-overlay
10
+ ```
11
+
12
+ ## Examples
13
+
14
+ ### Default
15
+
16
+ <ComponentPreview name="shortcut-overlay-demo" />
17
+
18
+ ## Props
19
+
20
+ | Prop | Type | Default | Description |
21
+ | -------------- | ------------------------- | ------- | ------------------------------ |
22
+ | `groups` | `ShortcutGroup[]` | — | Groups of shortcuts to display |
23
+ | `open` | `boolean` | — | Controlled open state |
24
+ | `onOpenChange` | `(open: boolean) => void` | — | Controlled open change handler |
25
+ | `trigger` | `string` | `"?"` | Key that toggles the overlay |
26
+
27
+ ### ShortcutGroup
28
+
29
+ ```ts
30
+ type ShortcutGroup = {
31
+ heading: string
32
+ shortcuts: { key: string; label: string }[]
33
+ }
34
+ ```
35
+
36
+ The `key` string is split on `+` and each part rendered as an individual `<kbd>`. For example `"⌘ + Z"` renders as two separate key badges.
37
+
38
+ ## Components
39
+
40
+ | Component | Description |
41
+ | ----------------- | ---------------------------------------------------- |
42
+ | `ShortcutOverlay` | Dialog modal with ? key listener |
43
+ | `ShortcutKey` | Inline keyboard shortcut badge (reusable standalone) |
@@ -0,0 +1,20 @@
1
+ ---
2
+ title: Slider
3
+ description: Slider component built on Radix Slider primitive.
4
+ ---
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ npx shadcn@latest add https://substrate.georgedrury.co.uk/r/slider
10
+ ```
11
+
12
+ ## Examples
13
+
14
+ ### Default
15
+
16
+ <ComponentPreview name="slider-demo" />
17
+
18
+ ### Range
19
+
20
+ <ComponentPreview name="slider-range" />
@@ -0,0 +1,85 @@
1
+ ---
2
+ title: Spring editor
3
+ description: Spring curve preview with duration and bounce, or stiffness, damping and mass.
4
+ ---
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ npx shadcn@latest add https://substrate.georgedrury.co.uk/r/spring-editor
10
+ ```
11
+
12
+ This also installs the `spring` utility library.
13
+
14
+ ## Examples
15
+
16
+ ### Default
17
+
18
+ <ComponentPreview name="spring-editor-demo" />
19
+
20
+ ## Usage
21
+
22
+ A spring is described one of two ways. A time spring sets how long the motion appears to take and how much it overshoots. A physics spring sets stiffness, damping and mass directly. The editor shows the sliders for whichever shape the value has, and the Type switch converts between them, restoring the previous settings when you switch back.
23
+
24
+ ```tsx
25
+ const [spring, setSpring] = useState<Spring>({
26
+ type: "spring",
27
+ visualDuration: 0.3,
28
+ bounce: 0.2,
29
+ })
30
+
31
+ <SpringEditor value={spring} onChange={setSpring} />
32
+ ```
33
+
34
+ The value matches Motion's spring transition, so it can be passed straight to `transition`.
35
+
36
+ ## Theme variables
37
+
38
+ | Variable | Tailwind class | Fallback | Description |
39
+ | --------------- | ---------------- | ----------- | ------------------- |
40
+ | `--spring-curve` | `bg-spring-curve` | Text colour | Spring curve stroke |
41
+
42
+ ## Components
43
+
44
+ | Component | Description |
45
+ | -------------- | ----------------------------------------------------------------- |
46
+ | `SpringEditor` | Curve, Time / Physics switch and sliders in a vertical stack |
47
+ | `SpringCurve` | SVG plot of the spring's progress over time, overshoot included |
48
+ | `SpringFields` | The sliders alone, for the value's own mode |
49
+
50
+ ## Props
51
+
52
+ ### SpringEditor and SpringFields
53
+
54
+ | Prop | Type | Default | Description |
55
+ | ---------- | -------------------------- | ------- | ---------------------------------------------- |
56
+ | `value` | `Spring` | — | Current spring |
57
+ | `onChange` | `(spring: Spring) => void` | — | Called when the spring changes |
58
+ | `onStart` | `() => void` | — | Fires when a drag or edit begins, for undo |
59
+
60
+ ### SpringCurve
61
+
62
+ | Prop | Type | Default | Description |
63
+ | ---------- | -------- | ------- | ---------------------------- |
64
+ | `value` | `Spring` | — | Spring to plot |
65
+ | `duration` | `number` | `2` | Seconds shown across the width |
66
+
67
+ ## Spring utility
68
+
69
+ ```tsx
70
+ import {
71
+ type Spring,
72
+ springMode,
73
+ springParams,
74
+ springProgress,
75
+ springSettleDuration,
76
+ } from "@/lib/substrate/spring"
77
+ ```
78
+
79
+ | Export | Description |
80
+ | ---------------------- | -------------------------------------------------------------------- |
81
+ | `Spring` | Type: `{ type: "spring", visualDuration?, bounce?, stiffness?, damping?, mass? }` |
82
+ | `springMode` | `"physics"` when stiffness, damping or mass is set, `"time"` otherwise |
83
+ | `springParams` | Resolves either shape to stiffness, damping and mass |
84
+ | `springProgress` | Progress at a time in seconds; goes past 1 when the spring overshoots |
85
+ | `springSettleDuration` | Seconds until the spring is within 0.5% of its target |
@@ -0,0 +1,42 @@
1
+ ---
2
+ title: Status bar
3
+ description: Bottom information strip showing document metadata, cursor position, and zoom controls.
4
+ ---
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ npx shadcn@latest add https://substrate.georgedrury.co.uk/r/status-bar
10
+ ```
11
+
12
+ ```bash
13
+ npx shadcn@latest add https://substrate.georgedrury.co.uk/r/zoom-controls
14
+ ```
15
+
16
+ ## Examples
17
+
18
+ ### Default
19
+
20
+ <ComponentPreview name="status-bar-demo" />
21
+
22
+ ## Components
23
+
24
+ ### StatusBar
25
+
26
+ | Component | Description |
27
+ | -------------------- | -------------------------------------------- |
28
+ | `StatusBar` | Fixed-height strip with border-top |
29
+ | `StatusBarSection` | Aligned group (`left`, `center`, or `right`) |
30
+ | `StatusBarItem` | Inline text item with tabular-nums |
31
+ | `StatusBarSeparator` | Thin vertical divider |
32
+
33
+ ### ZoomControls
34
+
35
+ | Prop | Type | Default | Description |
36
+ | -------------- | ------------------------ | ------- | ----------------------------- |
37
+ | `zoom` | `number` | — | Current zoom level (1 = 100%) |
38
+ | `onZoomChange` | `(zoom: number) => void` | — | Called when zoom changes |
39
+ | `onZoomToFit` | `() => void` | — | Optional fit-to-view callback |
40
+ | `min` | `number` | `0.1` | Minimum zoom |
41
+ | `max` | `number` | `10` | Maximum zoom |
42
+ | `step` | `number` | `0.25` | Zoom increment per click |
@@ -0,0 +1,47 @@
1
+ ---
2
+ title: Surface
3
+ description: Full-bleed container for rendering engines — canvas, WebGL, video or any visual content.
4
+ ---
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ npx shadcn@latest add https://substrate.georgedrury.co.uk/r/surface
10
+ ```
11
+
12
+ ## Examples
13
+
14
+ <ComponentPreview name="surface-demo" background="canvas" />
15
+
16
+ ## Theme variables
17
+
18
+ | Variable | Tailwind class | Fallback | Description |
19
+ | --------------------- | ------------------------ | -------------------- | ----------------------- |
20
+ | `--canvas` | `bg-canvas` | `--background` | Surface background |
21
+ | `--canvas-foreground` | `text-canvas-foreground` | `--foreground-muted` | Surface foreground/grid |
22
+
23
+ ## Components
24
+
25
+ | Component | Description |
26
+ | ----------------- | ------------------------------------------------------------------ |
27
+ | `Surface` | Absolute-positioned container with `bg-canvas` and overflow hidden |
28
+ | `SurfaceControls` | Overlay layer with pointer-events pass-through except on children |
29
+ | `SurfaceGrid` | CSS radial-gradient dot pattern sized via the `size` prop |
30
+
31
+ ## Props
32
+
33
+ ### Surface
34
+
35
+ Extends `React.ComponentProps<"div">`.
36
+
37
+ ### SurfaceControls
38
+
39
+ | Prop | Type | Default | Description |
40
+ | ---------- | -------------------------------------------------------------- | ---------------- | ---------------------------------- |
41
+ | `position` | `"top-left" \| "top-right" \| "bottom-left" \| "bottom-right"` | `"bottom-right"` | Which corner to anchor controls to |
42
+
43
+ ### SurfaceGrid
44
+
45
+ | Prop | Type | Default | Description |
46
+ | ------ | -------- | ------- | -------------------------- |
47
+ | `size` | `number` | `20` | Grid dot spacing in pixels |
@@ -0,0 +1,36 @@
1
+ ---
2
+ title: Swatch palette
3
+ description: Grid of colour swatches for quick selection. Pairs with ColourPicker.
4
+ ---
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ npx shadcn@latest add https://substrate.georgedrury.co.uk/r/swatch-palette
10
+ ```
11
+
12
+ ## Examples
13
+
14
+ ### Default
15
+
16
+ <ComponentPreview name="swatch-palette-demo" />
17
+
18
+ ## Props
19
+
20
+ | Prop | Type | Default | Description |
21
+ | ---------- | -------------------------- | ------- | ------------------------------- |
22
+ | `colours` | `string[]` | — | Array of hex colour strings |
23
+ | `value` | `string` | — | Currently selected colour |
24
+ | `onSelect` | `(colour: string) => void` | — | Called when a swatch is clicked |
25
+ | `columns` | `number` | `8` | Grid column count |
26
+
27
+ ## Presets
28
+
29
+ Two built-in palettes are exported for convenience:
30
+
31
+ ```ts
32
+ import {
33
+ MATERIAL_COLOURS,
34
+ TAILWIND_COLOURS,
35
+ } from "@/components/substrate/swatch-palette"
36
+ ```