Claude-skill-registry 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
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/inspector" ~/.claude/skills/majiayu000-claude-skill-registry-inspector-customization && rm -rf "$T"
manifest:
skills/data/inspector/SKILL.mdsource content
Inspector Customization
This skill covers creating and customizing inspector panels in react-wireflow.
Three Customization Patterns
Pattern 1: Node-Level renderInspector
renderInspectorDefine 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
InspectorPanelAdd 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 |
|---|---|
| Main container with tab support |
| Built-in layers/tree tab |
| Built-in properties tab (uses node's ) |
| Built-in settings tab with extensible panels |
| Built-in undo/redo history tab |
Layout Components
| Component | Description |
|---|---|
| Basic section wrapper |
| Collapsible section with title |
| Vertical field layout (label above input) |
| Horizontal field layout |
| Definition list container |
| Label-value pair in definition list |
| Grid for X/Y coordinate inputs |
| Standalone section title |
| Nested tabs within inspector |
Input Components
| Component | Description |
|---|---|
| Text input field |
| Number input with label |
| Multi-line text input |
| Dropdown select |
| Button (variants: primary, danger, default) |
| Icon-only button |
| Segmented button group (radio-style) |
| Toggle button group (checkbox-style) |
| Form label |
| 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
for collapsible groups of related fieldsPropertySection - Use
for label-value pairsInspectorDefinitionList - Use
for mutually exclusive optionsInspectorButtonGroup - Keep inspector content scrollable - avoid fixed heights
Example File
See complete example at:
src/examples/demos/custom/inspector/custom-inspector/CustomInspectorExample.tsx