You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/architecture.md
+10-8Lines changed: 10 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -146,26 +146,26 @@ The devtools shell is a Solid.js application that renders the entire devtools UI
146
146
-**`setConfig(config)`** -- Updates configuration and plugins at runtime. Plugins are reactive: adding or removing them updates the tab bar immediately.
147
147
148
148
The shell renders:
149
-
- A **trigger button** (the floating devtools toggle, customizable or replaceable)
149
+
- A **trigger button** (the floating rainbow palm mark, customizable or replaceable)
150
150
- A **resizable Workbench panel** (docked to the top or bottom of the viewport, resizable via pointer or keyboard)
151
151
- A compact **36px TanStack Devtools header** with Plugins, Marketplace, SEO, and Settings destinations. The palm emblem is inline SVG, so it stays sharp and takes its colour from the theme.
152
152
- A fixed-height **44px secondary strip** for plugin and SEO navigation. It scrolls horizontally when space is limited, and a pull tab on its bottom edge folds it away behind the header. Folding changes nothing else — the panel keeps its height and the destination content keeps running — so the tab is rendered only on the destinations that have a strip.
153
153
- A separate **Marketplace** header tab that does not disturb mounted plugin panes
154
154
- A **settings panel** for theme, hotkeys, position, and other preferences
155
155
- Up to three simultaneous **plugin mount frames**, divided into equal widths by static separators
156
156
157
-
Settings and UI state (panel size, position, active tab, theme) are persisted in `localStorage` so they survive page reloads.
157
+
Settings and UI state (panel size, position, active tab, theme, and whether the secondary strip is folded) are persisted in `localStorage` so they survive page reloads.
158
158
159
159
The core shell owns the Workbench header, navigation, mount-frame geometry, separators, and surrounding light/dark surfaces. Each external plugin owns everything inside its mount target; core styling deliberately does not reach into plugin descendants. Detaching the Workbench uses a fixed `100vh` Picture-in-Picture layout and restores the stored docked height when reattached.
160
160
161
161
#### Workbench surfaces and gutters
162
162
163
163
Two rules keep the shell reading as one surface:
164
164
165
-
-**Chrome versus canvas.** The header and every secondary strip paint the brand surface (cream in light mode, near-black in dark mode) and close with a translucent ink hairline. Destination content and plugin mount frames paint the workspace surface. A plugin pane can paint any colour it likes, so the separator between panes uses a mid-tone border that stays visible against both.
165
+
-**Chrome versus canvas.** The header and every secondary strip paint the brand surface (cream in light mode, near-black in dark mode) and close with a translucent ink hairline. Destination content and plugin mount frames paint the workspace surface. A plugin pane can paint any colour it likes. The resize gutter between panes is invisible at rest and paints a line on hover or keyboard focus.
166
166
-**One gutter.**`WORKBENCH_GUTTER` (16px, or `WORKBENCH_GUTTER_NARROW` at 12px below 430px) is the single inline gutter. The header, the strips, and each destination's content all start there, so the left edge is one column instead of three. `MainPanel withPadding` uses the same value.
167
167
168
-
Colour comes from the semantic theme only. Raw hex values in core-owned source are rejected by `tests/semantic-color-usage.test.ts` unless they carry a narrow, path-scoped `semantic-color-exempt` marker — currently only third-party network marks and the source-inspector highlight alpha. Status colours (success, warning, error, info) mark real state; identity accents do not compete with them, so a card that is both featured and active keeps the neutral outline and lets its badge say which it is.
168
+
Colour comes from the semantic theme only. Raw hex values in core-owned source are rejected by `tests/semantic-color-usage.test.ts` unless they carry a narrow, path-scoped `semantic-color-exempt` marker. The current exemptions are third-party network marks, the source-inspector highlight alpha, and the trigger rainbow mark. Status colours (success, warning, error, info) mark real state; identity accents do not compete with them, so a card that is both featured and active keeps the neutral outline and lets its badge say which it is.
169
169
170
170
### @tanstack/devtools-ui -- Component Library
171
171
@@ -190,15 +190,17 @@ This client is a singleton (`devtoolsEventClient`) used by both the core shell a
190
190
Each framework adapter is a thin wrapper that bridges its framework's component model to the core Solid.js shell. The pattern is the same across all adapters:
191
191
192
192
1.**Creates a `TanStackDevtoolsCore` instance** with the user's plugins and config.
193
-
2.**Mounts it to a DOM element** using the framework's lifecycle hooks (`useEffect` in React, `onMounted` in Vue, `onMount` in Solid).
194
-
3.**Converts framework-specific plugin definitions** into the core's DOM-based `render(el, theme)` interface. Each adapter defines its own plugin type (e.g. `TanStackDevtoolsReactPlugin`) that accepts framework-native components, then wraps them in a `render` callback that the core calls with a target DOM element and the current theme.
195
-
4.**Uses the framework's portal/teleport mechanism** to render plugin components into the core's DOM containers:
193
+
2.**Mounts it to a DOM element** using the framework's lifecycle APIs, such as `useEffect` in React, `onMounted` in Vue, `$effect` in Svelte, and `onMount` in Solid.
194
+
3.**Converts framework-specific plugin definitions** into the core's DOM-based `render(el, props)` interface. Each adapter defines its own plugin type (e.g. `TanStackDevtoolsReactPlugin`) that accepts framework-native components, then wraps them in a `render` callback that the core calls with a target DOM element and `{ theme, devtoolsOpen }`.
195
+
4.**Uses the framework's rendering API** to render plugin components into the core's DOM containers:
196
196
-**React** -- `createPortal()` from `react-dom`
197
197
-**Vue** -- `<Teleport :to="'#' + plugin.id" />`
198
198
-**Solid** -- `<Portal mount={el} />`
199
199
-**Preact** -- Same portal pattern as React
200
+
-**Svelte** -- `mount(component, { target: el, props })`
201
+
-**Angular** -- `createComponent()` with the container's environment injector
200
202
201
-
The key insight: the core shell is always Solid.js, but your plugins run in **your** framework. A React plugin is a real React component rendered by React's `createPortal`into a DOM element that the Solid.js shell created. A Vue plugin is a real Vue component rendered by Vue's `<Teleport>`. The adapters bridge this gap so you never need to think about Solid.js unless you want to.
203
+
The key insight: the core shell is always Solid.js, but your plugins run in **your** framework. Each adapter receives the same plugin props and renders a native framework component into a DOM element created by the Solid.js shell. The adapters bridge this gap so you never need to think about Solid.js unless you want to.
-`triggerMode` - How the trigger is placed. `'fixed'`anchors it to `position`; `'floating'`lets you drag the trigger anywhere on screen (and throw it — it glides with momentum and springs back off the edges). The floating spot is persisted in local storage.
38
+
-`triggerMode` - How the trigger is placed. `'floating'`(the default) lets you drag the trigger anywhere on screen, and throw it: it glides with momentum and springs back off the edges. `'fixed'` anchors it to `position`. The floating spot is persisted in local storage.
-**`Plugin()`**--returnsapluginobjectwith`name`, `id`, `defaultOpen`, anda`render`function that renders your `Component` with the current theme.
80
+
-**`Plugin()`**--returnsapluginobjectwith`name`, `id`, `defaultOpen`, anda`render`function that renders your `Component` with the current plugin props.
81
81
- **`NoOpPlugin()`** -- returns a plugin object with the same metadata but a `render` function that renders an empty fragment. Use this for production builds where you want to strip devtools out.
@@ -38,7 +38,7 @@ type TanStackDevtoolsReactPlugin = {
38
38
}
39
39
```
40
40
41
-
- **`render`** can be a JSX element (simplest -- just pass `<YourPanel />`) or a function that receives the container element and current theme. The function form is useful when you need to access the raw DOM element or respond to theme changes.
41
+
- **`render`** can be a JSX element (simplest -- just pass `<YourPanel />`) or a function that receives the container element and current `{ theme, devtoolsOpen }` props. The function form is useful when you need to access the raw DOM element or respond to plugin state changes.
42
42
- **`name`** works the same way -- use a string for plain text, or JSX / a function for custom tab titles.
43
43
- **`id`** is an optional unique identifier. If omitted, it is generated from the name.
44
44
- **`defaultOpen`** marks the plugin as initially active when no other plugins are open.
Copy file name to clipboardExpand all lines: docs/framework/svelte/adapter.md
+6-4Lines changed: 6 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -38,14 +38,16 @@ type TanStackDevtoolsSveltePlugin = {
38
38
| Field | Type | Description |
39
39
| --- | --- | --- |
40
40
| `id` | `string` (optional) | Unique identifier for the plugin. |
41
-
| `component` | `Component<any>` | The Svelte component to render as the plugin panel content. |
42
-
| `name` | `string \|Component<any>` | Display name for the tab title. Can be a plain string or a Svelte component for custom rendering. |
43
-
| `props` | `Record<string, any>` (optional) | Additional props passed to the plugin component on mount. |
41
+
| `component` | `Component<any>` | The Svelte component to render as the plugin panel content. It receives the shared `theme` and `devtoolsOpen` props. |
42
+
| `name` | `string \|Component<any>` | Display name for the tab title. A custom Svelte component receives the same merged plugin props. |
43
+
| `props` | `Record<string, any>` (optional) | Additional props merged with the shared plugin props when the component mounts. |
44
44
| `defaultOpen` | `boolean` (optional) | Whether this plugin tab should be open by default. |
45
45
46
46
## Key Difference from Other Frameworks
47
47
48
-
The Svelte adapter uses `component` (a Svelte component reference) instead of `render` (a JSX element) in plugin definitions. Props are provided through the `props` field and passed to the component via Svelte's `mount()` API, rather than being embedded directly in a JSX expression.
48
+
The Svelte adapter uses `component` (a Svelte component reference) instead of `render` (a JSX element) in plugin definitions. It passes `{ theme, devtoolsOpen, ...plugin.props }` to the component through Svelte's `mount()` API.
49
+
50
+
When the core renders a plugin again, the adapter updates the existing Svelte host with the latest component and props. If the component identity is unchanged, its state and lifecycle remain intact. The adapter unmounts the host when the plugin is destroyed or the Devtools instance shuts down.
Copy file name to clipboardExpand all lines: docs/framework/svelte/basic-setup.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -48,6 +48,6 @@ Import the desired devtools and provide them to the `TanStackDevtools` component
48
48
<TanStackDevtools {plugins} />
49
49
```
50
50
51
-
> Note: The Svelte adapter uses `component` (a Svelte component reference) instead of `render` (a JSX element) in plugin definitions. Additional props can be provided via the `props` field and are passed to the component on mount.
51
+
> Note: The Svelte adapter uses `component` (a Svelte component reference) instead of `render` (a JSX element) in plugin definitions. Components receive the shared `theme` and `devtoolsOpen` props. Additional values from the plugin's `props` field are merged into the same object when the component mounts.
52
52
53
53
Finally, add any additional configuration you desire to the `TanStackDevtools` component. More information can be found under the [TanStack Devtools Configuration](../../configuration) section.
0 commit comments