Agent skill
inspector-customization
Create and customize inspector panels for node editors. Use when implementing custom inspector tabs, settings panels, node-specific inspectors, or using inspector UI components.
Install this agent skill to your Project
npx add-skill https://github.com/trkbt10/react-wireflow/tree/main/skills/inspector
SKILL.md
Inspector Customization
This skill covers creating and customizing inspector panels in react-wireflow.
Three Customization Patterns
Pattern 1: Node-Level renderInspector
Define custom inspector content per node type in the NodeDefinition:
import type { NodeDefinition, InspectorRenderProps } from "react-wireflow";
import {
PropertySection,
InspectorDefinitionList,
InspectorDefinitionItem,
InspectorInput,
InspectorSelect,
} from "react-wireflow";
type PersonNodeData = {
name: string;
email: string;
role: "developer" | "designer" | "manager";
};
function PersonInspectorRenderer({
node,
onUpdateNode,
}: InspectorRenderProps<PersonNodeData>): React.ReactElement {
const data = node.data ?? ({} as PersonNodeData);
const handleChange = <K extends keyof PersonNodeData>(
key: K,
value: PersonNodeData[K]
) => {
onUpdateNode({ data: { ...data, [key]: value } });
};
return (
<PropertySection title="Person Details">
<InspectorDefinitionList>
<InspectorDefinitionItem label="Name">
<InspectorInput
value={data.name ?? ""}
onChange={(e) => handleChange("name", e.target.value)}
placeholder="Enter name"
/>
</InspectorDefinitionItem>
<InspectorDefinitionItem label="Role">
<InspectorSelect
value={data.role ?? "developer"}
onChange={(e) =>
handleChange("role", e.target.value as PersonNodeData["role"])
}
>
<option value="developer">Developer</option>
<option value="designer">Designer</option>
<option value="manager">Manager</option>
</InspectorSelect>
</InspectorDefinitionItem>
</InspectorDefinitionList>
</PropertySection>
);
}
const PersonNodeDefinition: NodeDefinition<PersonNodeData> = {
type: "person",
displayName: "Person",
ports: [...],
renderInspector: PersonInspectorRenderer,
};
Pattern 2: Custom Tabs via InspectorPanel
Add custom tabs to the inspector panel:
import {
InspectorPanel,
InspectorLayersTab,
InspectorPropertiesTab,
InspectorSettingsTab,
InspectorSection,
PropertySection,
type InspectorPanelTabConfig,
} from "react-wireflow";
const StatisticsTab: React.FC = () => (
<InspectorSection>
<PropertySection title="Editor Statistics">
<InspectorDefinitionList>
<InspectorDefinitionItem label="Total Nodes">
<ReadOnlyField>5</ReadOnlyField>
</InspectorDefinitionItem>
</InspectorDefinitionList>
</PropertySection>
</InspectorSection>
);
const CustomInspectorPanel: React.FC = () => {
const tabs: InspectorPanelTabConfig[] = React.useMemo(
() => [
{
id: "layers",
label: "Layers",
render: () => <InspectorLayersTab />,
},
{
id: "properties",
label: "Properties",
render: () => <InspectorPropertiesTab />,
},
{
id: "statistics",
label: "Stats",
render: () => <StatisticsTab />,
},
{
id: "settings",
label: "Settings",
render: () => <InspectorSettingsTab />,
},
],
[]
);
return <InspectorPanel tabs={tabs} />;
};
Pattern 3: Custom Settings Panels
Add custom panels to the Settings tab:
import {
InspectorSettingsTab,
InspectorDefinitionList,
InspectorDefinitionItem,
InspectorSelect,
InspectorButton,
type InspectorSettingsPanelConfig,
} from "react-wireflow";
const ExportSettingsPanel: React.FC = () => {
const [format, setFormat] = React.useState<"json" | "yaml">("json");
return (
<InspectorDefinitionList>
<InspectorDefinitionItem label="Format">
<InspectorSelect
value={format}
onChange={(e) => setFormat(e.target.value as "json" | "yaml")}
>
<option value="json">JSON</option>
<option value="yaml">YAML</option>
</InspectorSelect>
</InspectorDefinitionItem>
<InspectorDefinitionItem label="">
<InspectorButton variant="primary" size="small">
Export Data
</InspectorButton>
</InspectorDefinitionItem>
</InspectorDefinitionList>
);
};
const settingsPanels: InspectorSettingsPanelConfig[] = [
{
title: "Export Options",
component: ExportSettingsPanel,
},
];
// Use in tabs:
{
id: "settings",
label: "Settings",
render: () => <InspectorSettingsTab panels={settingsPanels} />,
}
Available Inspector Components
Panel Components
| Component | Description |
|---|---|
InspectorPanel |
Main container with tab support |
InspectorLayersTab |
Built-in layers/tree tab |
InspectorPropertiesTab |
Built-in properties tab (uses node's renderInspector) |
InspectorSettingsTab |
Built-in settings tab with extensible panels |
InspectorHistoryTab |
Built-in undo/redo history tab |
Layout Components
| Component | Description |
|---|---|
InspectorSection |
Basic section wrapper |
PropertySection |
Collapsible section with title |
InspectorField |
Vertical field layout (label above input) |
InspectorFieldRow |
Horizontal field layout |
InspectorDefinitionList |
Definition list container |
InspectorDefinitionItem |
Label-value pair in definition list |
PositionInputsGrid |
Grid for X/Y coordinate inputs |
InspectorSectionTitle |
Standalone section title |
InspectorTabbedContainer |
Nested tabs within inspector |
Input Components
| Component | Description |
|---|---|
InspectorInput |
Text input field |
InspectorNumberInput |
Number input with label |
InspectorTextarea |
Multi-line text input |
InspectorSelect |
Dropdown select |
InspectorButton |
Button (variants: primary, danger, default) |
InspectorIconButton |
Icon-only button |
InspectorButtonGroup |
Segmented button group (radio-style) |
InspectorToggleGroup |
Toggle button group (checkbox-style) |
InspectorLabel |
Form label |
ReadOnlyField |
Non-editable display field |
InspectorRenderProps Reference
type InspectorRenderProps<TData> = {
node: Node & { data: TData };
externalData: unknown;
isLoadingExternalData: boolean;
externalDataError: Error | null;
onUpdateNode: (updates: Partial<Node>) => void;
onUpdateExternalData: (data: unknown) => Promise<void>;
onDeleteNode: () => void;
};
Best Practices
- Always use inspector components for consistent theming across light/dark modes
- Use
PropertySectionfor collapsible groups of related fields - Use
InspectorDefinitionListfor label-value pairs - Use
InspectorButtonGroupfor mutually exclusive options - Keep inspector content scrollable - avoid fixed heights
Example File
See complete example at:
src/examples/demos/custom/inspector/custom-inspector/CustomInspectorExample.tsx
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
custom-node-definition
Create custom node definitions with renderers, ports, external data, and constraints. Use when implementing new node types, custom node appearances, or node-specific behaviors.
setup-pre-commit
Set up Husky pre-commit hooks with lint-staged (Prettier), type checking, and tests in the current repo. Use when user wants to add pre-commit hooks, set up Husky, configure lint-staged, or add commit-time formatting/typechecking/testing.
edit-article
Edit and improve articles by restructuring sections, improving clarity, and tightening prose. Use when user wants to edit, revise, or improve an article draft.
git-guardrails-claude-code
Set up Claude Code hooks to block dangerous git commands (push, reset --hard, clean, branch -D, etc.) before they execute. Use when user wants to prevent destructive git operations, add git safety hooks, or block git push/reset in Claude Code.
scaffold-exercises
Create exercise directory structures with sections, problems, solutions, and explainers that pass linting. Use when user wants to scaffold exercises, create exercise stubs, or set up a new course section.
obsidian-vault
Search, create, and manage notes in the Obsidian vault with wikilinks and index notes. Use when user wants to find, create, or organize notes in Obsidian.
Didn't find tool you were looking for?