Files
2026-04-28 10:47:34 -03:00

309 lines
9.1 KiB
Plaintext

---
title: "Inspector"
sidebarTitle: "Inspector"
description: "Contextual sidebar components for document, node, and text editing."
icon: "sidebar"
---
The Inspector is a sidebar that provides a way to inspect and edit the email's properties. From the Inspector, you can edit document, node, and text properties such as colors, fonts, and padding.
View a minimal example of the Inspector at the [Standalone Editor Inspector](https://react.email/editor/examples/standalone-editor-inspector) demo page.
Everything is accessed through a single import:
```tsx
import { Inspector } from '@react-email/editor/ui';
```
`Inspector.Root` must be rendered inside the current editor context, and it
requires the [EmailTheming](/editor/api-reference/theming-api) extension to be present in the editor.
## Core components
### Inspector.Root
Wraps your inspector UI and decides which panel should be active based on the
current selection.
```tsx
import { StarterKit } from '@react-email/editor/extensions';
import { EmailTheming } from '@react-email/editor/plugins';
import { Inspector } from '@react-email/editor/ui';
import { EditorContent, EditorContext, useEditor } from '@tiptap/react';
const extensions = [StarterKit, EmailTheming];
export function MyEditor() {
const editor = useEditor({
extensions,
content,
});
return (
<EditorContext.Provider value={{ editor }}>
<div className="flex">
<EditorContent editor={editor} />
<Inspector.Root className="w-60 shrink-0 border-l p-4">
<Inspector.Document />
<Inspector.Node />
<Inspector.Text />
</Inspector.Root>
</div>
</EditorContext.Provider>
);
}
```
<Tip>
If you use the standalone `EmailEditor` component, pass the inspector as a
child. No `EditorContext.Provider` is needed. See the
[Inspector feature guide](/editor/features/inspector#using-with-emaileditor).
</Tip>
<Tip>
`Inspector.Root` already wraps itself in
[EditorFocusScope](/editor/api-reference/ui/editor-focus-scope) by default,
so the Inspector handles the editor's focus idiomatically and reliably. Add
`EditorFocusScope` yourself only when custom inspector controls render
additional portaled content.
</Tip>
<ResponseField name="asChild" type="boolean" default="false">
Render without the default `aside` wrapper and pass props to the child via
Radix UI's [Slot](https://www.radix-ui.com/primitives/docs/utilities/slot).
</ResponseField>
All standard props from `aside` are also supported if `asChild` is `false`.
### Inspector.Document
This is meant for inspecting and changing properties related to the entire editor's content. That is, [EmailTheming](/editor/api-reference/theming-api), page-level settings, and other document-wide concerns.
It shows up when the editor is not focused on a specific node or text selection, or when the editor is unfocused.
```tsx
<Inspector.Document />
```
<ResponseField name="children" type="(context: InspectorDocumentContext) => ReactNode">
Optional render prop. When provided, you receive the document inspector
context instead of the default UI.
</ResponseField>
#### InspectorDocumentContext
<ResponseField name="styles" type="PanelGroup[]">
Theme-backed document style groups after merging defaults.
</ResponseField>
<ResponseField name="setGlobalStyle" type="(classReference, property, value) => void">
Updates a single document-level style.
</ResponseField>
<ResponseField name="batchSetGlobalStyle" type="(changes) => void">
Applies multiple document style changes at once.
</ResponseField>
<ResponseField name="findStyleValue" type="(classReference, property) => string | number">
Reads the current or default value for a document style.
</ResponseField>
### Inspector.Node
Renders when a node is focused or selected. Without `children`, it shows the
default node-specific sections for the active node type.
```tsx
<Inspector.Node />
```
<ResponseField name="children" type="(context: InspectorNodeContext) => ReactNode">
Optional render prop. When provided, you receive the node inspector context
instead of the default UI.
</ResponseField>
#### InspectorNodeContext
<ResponseField name="nodeType" type="string">
Active node type, such as `image`, `button`, or `section`.
</ResponseField>
<ResponseField name="nodePos" type="{ pos: number; inside: number }">
ProseMirror position information for the focused node.
</ResponseField>
<ResponseField name="getStyle" type="(prop) => string | number | undefined">
Reads a resolved style value for the node.
</ResponseField>
<ResponseField name="setStyle" type="(prop, value) => void">
Updates one inline style on the focused node.
</ResponseField>
<ResponseField name="batchSetStyle" type="(changes) => void">
Applies multiple inline style updates in one call.
</ResponseField>
<ResponseField name="getAttr" type="(name) => unknown">
Reads a node attribute.
</ResponseField>
<ResponseField name="setAttr" type="(name, value) => void">
Updates a node attribute.
</ResponseField>
<ResponseField name="themeDefaults" type="Record<string, string | number | undefined>">
Resolved theme defaults for the current node.
</ResponseField>
<ResponseField name="presetColors" type="string[]">
Colors collected from the current document.
</ResponseField>
### Inspector.Text
Renders when text is selected. Without `children`, it shows typography controls
and link controls when a link mark is active.
```tsx
<Inspector.Text />
```
<ResponseField name="children" type="(context: InspectorTextContext) => ReactNode">
Optional render prop. When provided, you receive the text inspector context
instead of the default UI.
</ResponseField>
#### InspectorTextContext
<ResponseField name="marks" type="Record<string, boolean>">
Active text marks like `bold`, `italic`, and `underline`.
</ResponseField>
<ResponseField name="toggleMark" type="(mark: string) => void">
Toggles a text mark on the current selection.
</ResponseField>
<ResponseField name="alignment" type="string">
Current block alignment.
</ResponseField>
<ResponseField name="setAlignment" type="(value: string) => void">
Updates the parent block alignment.
</ResponseField>
<ResponseField name="linkHref" type="string">
Current link URL when a link mark is active.
</ResponseField>
<ResponseField name="linkColor" type="string">
Resolved link color.
</ResponseField>
<ResponseField name="setLinkColor" type="(color: string) => void">
Updates the active link color.
</ResponseField>
<ResponseField name="isLinkActive" type="boolean">
Whether the current text selection is inside a link.
</ResponseField>
<ResponseField name="getStyle" type="(prop) => string | number | undefined">
Reads the resolved parent block style.
</ResponseField>
<ResponseField name="setStyle" type="(prop, value) => void">
Updates the parent block style.
</ResponseField>
<ResponseField name="presetColors" type="string[]">
Colors collected from the current document.
</ResponseField>
### Inspector.Breadcrumb
Renders the current path from the document root to the focused node.
```tsx
<Inspector.Breadcrumb />
```
<ResponseField name="children" type="(segments: InspectorBreadcrumbSegment[]) => ReactNode">
Optional render prop for completely custom breadcrumb rendering.
</ResponseField>
Each segment includes:
<ResponseField name="node" type="FocusedNode">
The node for this breadcrumb segment. The root segment is the `body` node.
</ResponseField>
<ResponseField name="focus" type="() => void">
Focuses the corresponding node.
</ResponseField>
<Tip>
Use `getNodeMeta(nodeType)` to get the label and icon the default breadcrumb
uses for a given node type:
```tsx
import { getNodeMeta } from '@react-email/editor/ui';
<Inspector.Breadcrumb>
{(segments) =>
segments.map((segment, i) => {
const { label } = getNodeMeta(segment.node.nodeType);
return (
<button key={i} type="button" onClick={() => segment.focus()}>
{label}
</button>
);
})
}
</Inspector.Breadcrumb>
```
</Tip>
## Built-in sections
Use these inside custom `Inspector.Node` or `Inspector.Text` render functions to
reuse the default section UIs in your own layout.
```tsx
<Inspector.Node>
{(context) => (
<>
<Inspector.Size {...context} />
<Inspector.Padding {...context} />
<Inspector.Border {...context} />
</>
)}
</Inspector.Node>
```
| Component | Context | Description |
| -- | -- | -- |
| `Inspector.Attributes` | Node | Editable attribute fields based on the local attribute schema |
| `Inspector.Background` | Node | Background color editor |
| `Inspector.Border` | Node | Border width, color, style, and radius controls |
| `Inspector.Link` | Text | Read-only URL plus link color controls for active links |
| `Inspector.Padding` | Node | Four-sided padding editor |
| `Inspector.Size` | Node | Width and height controls |
| `Inspector.Typography` | Node or Text | Typography, formatting, and alignment controls |
## CSS import
```tsx
import '@react-email/editor/styles/inspector.css';
```
<Tip>
`@react-email/editor/themes/default.css` bundles all UI component styles.
Unless you need to cherry-pick, use this single import:
```tsx
import '@react-email/editor/themes/default.css';
```
</Tip>