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.0
A step-by-step compatibility process for shipping a WordPress 7.0-ready release — set up a test site, audit your blocks, fix the breaking changes, and ship with confidence.
22 min
- WordPress
WordPress 7.0 for Block Developers: Breaking Changes
WordPress 7.0 enforces the iframed editor, broadens contentOnly mode, and drops PHP 7.3. Here are the breaking changes block and plugin developers must fix before users upgrade.
25 min
- WordPress
WordPress 7.0 AI: Client, Abilities & Connectors
The headline feature of WordPress 7.0 is native AI in Core. Here is what the WP AI Client, the Abilities API, and the Connectors system actually mean for plugin developers.
25 min