In Part 3 we hardcoded calloutType: 'info'. In Part 5 we let users change it through the inspector sidebar.
The InspectorControls slot
InspectorControls is a slot component. Whatever you render inside it appears in the block’s right-sidebar inspector — not inline in the block.
import { InspectorControls, useBlockProps, RichText } from '@wordpress/block-editor';
import { PanelBody, SelectControl, ToggleControl } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
export default function Edit({ attributes, setAttributes }) {
const { title, body, calloutType, dismissible } = attributes;
const blockProps = useBlockProps({
className: `my-callout my-callout-${calloutType}`,
});
return (
<>
<InspectorControls>
<PanelBody title={__('Callout settings', 'my-first-block')} initialOpen>
<SelectControl
label={__('Type', 'my-first-block')}
value={calloutType}
options={[
{ label: 'Info', value: 'info' },
{ label: 'Tip', value: 'tip' },
{ label: 'Warning', value: 'warning' },
{ label: 'Error', value: 'error' },
]}
onChange={(value) => setAttributes({ calloutType: value })}
/>
<ToggleControl
label={__('Dismissible', 'my-first-block')}
help={__('Show a close button.', 'my-first-block')}
checked={dismissible}
onChange={(value) => setAttributes({ dismissible: value })}
/>
</PanelBody>
</InspectorControls>
<div {...blockProps}>
<RichText
tagName="h4"
value={title}
onChange={(value) => setAttributes({ title: value })}
/>
<RichText
tagName="p"
value={body}
onChange={(value) => setAttributes({ body: value })}
/>
</div>
</>
);
}
Add dismissible to block.json attributes:
"dismissible": { "type": "boolean", "default": false }
Common controls from @wordpress/components
| Component | Use |
|---|---|
SelectControl | Dropdown for fixed-choice options |
ToggleControl | Boolean on/off |
TextControl | Single-line text |
TextareaControl | Multi-line text |
ColorPalette | Theme-aware color picker |
FontSizePicker | Theme-aware font size |
RangeControl | Numeric slider |
ButtonGroup | Multi-button selection |
PanelBody | Collapsible section wrapper |
RadioControl | Radio button group |
Group related controls
Wrap related controls in a PanelBody. Each panel is collapsible. For our Callout block:
<InspectorControls>
<PanelBody title="Appearance" initialOpen>
<SelectControl ... /> {/* type */}
</PanelBody>
<PanelBody title="Behavior" initialOpen={false}>
<ToggleControl ... /> {/* dismissible */}
</PanelBody>
</InspectorControls>
Toolbar controls (for block-toolbar, not the inspector)
If a control belongs in the toolbar above the selected block (alignment, link, bold), use BlockControls instead of InspectorControls:
import { BlockControls, AlignmentToolbar } from '@wordpress/block-editor';
<BlockControls>
<AlignmentToolbar
value={attributes.alignment}
onChange={(value) => setAttributes({ alignment: value })}
/>
</BlockControls>
Verification
Callout settings test
My Callout block
Heads up
Selecting “Warning” in the inspector changes the color theme to amber.
Insert your block. The right sidebar now shows “Callout settings” panel with a Type dropdown and Dismissible toggle. Change Type → the block re-renders with the new color theme immediately.
What’s next
Part 6 introduces nested blocks via InnerBlocks — letting users compose other blocks inside our Callout (so they can put a list or an image inside, not just text).
Get the next one in your inbox. Practical tips, no fluff.
More tutorials
View all- WordPress
How to Prepare Your Plugin or Theme for WordPress 7.1
A WordPress 7.1 compatibility checklist: iframed editor, client-side media hooks, Abilities public flag, jQuery UI 1.14.2, plus features that did not ship (React 19, collaboration).
22 min
- WordPress
What's New in WordPress 7.1 for Developers
WordPress 7.1 field guide for developers: client-side media, Abilities API, always-iframed editor, SVG Icon API, global styles, and what to test before users upgrade.
18 min
- WordPress
Abilities API Changes in WordPress 7.1
WordPress 7.1 upgrades the Abilities API: a unified public flag, wp_get_abilities() filtering, execution lifecycle hooks, JSON Schema for clients, and typed REST input.
25 min