# Quick start ## Install ```sh pnpm add @dolphinspired/solid-stage ``` Peer dependency: Solid 1.9+. The library is **browser-only** (it uses `ResizeObserver` and `getBoundingClientRect`; there is no SSR build). ### Vite: exclude Kobalte from dep optimization Add this to your `vite.config.ts`: ```ts optimizeDeps: { exclude: ['@kobalte/core'] }, ``` Without it, the dev server can throw `React is not defined` when a Kobalte-based popup first opens, such as the `ColorField` picker. `vite-plugin-solid` resolves Kobalte to raw JSX, but it only sets up your direct Solid dependencies, and Kobalte reaches you through this library. So Vite's dep optimizer compiles that JSX with its React default. Production builds aren't affected, so `vite build` won't warn you. Clear the cache after adding it, by deleting `node_modules/.vite` or running Vite once with `--force`. ## Import the styles once The library ships one stylesheet. Import it once, anywhere in your app entry: ```ts import '@dolphinspired/solid-stage/styles.css'; ``` ## Wrap your app in a `.stage-root` Every token (colour, size, spacing) is declared on `.stage-root`, and all portalled UI (select popovers, the modal, tooltips) mounts into the **nearest** `.stage-root`. So your stage must live inside an element carrying that class: ```tsx function App() { return (
{/* …your stage… */}
); } ``` To restyle, set CSS variables on that element (or any container inside it): ```tsx
``` ## A minimal stage `EditorPanels` is the outer shell: optional bars, optional left/right panels, and a required `center` (your canvas, preview, or any content). A root stage owns the window (`position: fixed; inset: 0`). ```tsx import { EditorPanels, Section, TextField } from '@dolphinspired/solid-stage'; import { createSignal } from 'solid-js'; import '@dolphinspired/solid-stage/styles.css'; function App() { const [name, setName] = createSignal('Untitled'); return (
Your world here
} leftPanel={
} />
); } ``` That's a complete editor: a centre region, a collapsible left panel, and a collapsible section (whose open/closed state already persists to `localStorage`) holding one text field. ## Add a reactive store Hand-wiring a `createSignal` per field gets old. `createEditorStore` gives you one typed reactive source of truth with optional persistence, and a `bind` helper that fills in `value` + `onChange` for any field: ```tsx import { EditorPanels, FieldGroup, Section, TextField, NumberField, BooleanField, createEditorStore } from '@dolphinspired/solid-stage'; interface Settings { name: string; level: number; snap: boolean; } function App() { const [state, setState, bind] = createEditorStore({ defaults: { name: 'Untitled', level: 1, snap: true }, persist: { key: 'my-editor', version: 1 }, }); return (
} leftPanel={
} />
); } ``` `{...bind('name')}` expands to `value={() => state.name} onChange={(v) => setState('name', v)}`. The store reads/writes through `state`/`setState` (Solid's `createStore` API), so your canvas reacts with a plain `createEffect`. See [State](./state.md). ## Add a canvas For a 3D/2D world in the centre, `CanvasStage` gives you a sized viewport with World / HUD / Pointer layers: ```tsx import { CanvasStage } from '@dolphinspired/solid-stage'; renderer.setSize(width, height)}> el.appendChild(renderer.domElement)} /> {/* overlay UI */} ``` Drop it into `EditorPanels`'s `center`. See [Layout](./layout.md#canvasstage). ## Where next - [Concepts](./concepts.md) — the mental model behind all of this. - [Controls & fields](./controls.md) — the full widget set. - [Overlays](./overlays.md) — wire up modal / toast / tooltip (each needs a one-time host component mounted in your `.stage-root`).