-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #136 from 10up/guide/tools-panel
ToolsPanel and ToolsPanelItem Examples
- Loading branch information
Showing
1 changed file
with
211 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,211 @@ | ||
# ToolsPanel and ToolsPanelItem | ||
|
||
## Preface: | ||
WordPress recently adopted a new UI approach for grouping related settings in the Inspector Controls sidebar. Instead of grouping the settings in PanelBody components which create an accordion based user experience, the new ToolPanel approach allows users to toggle individual settings from a semantic group. This reduces the number of unused controls shown to the user when they open a block sidebar. This approach also makes it much easier for block extenders (developers) to add additional settings into these semantic panels. For example: a block has a custom typography setting which isn't already in core such as, writing mode, you can create a block extension and add your own custom setting into the typography panel of a block. | ||
|
||
## Reference Guide WordPress Documentation: | ||
* [ToolsPanel](https://developer.wordpress.org/block-editor/reference-guides/components/tools-panel/) | ||
* [ToolsPanelItem](https://developer.wordpress.org/block-editor/reference-guides/components/tools-panel-item/) | ||
|
||
Both of these are **experimental**. | ||
|
||
## Use Case: | ||
If you have custom controls that should exist within or be added to an existing block support panels group (ie: `border`, `color`, `dimensions`, `typography` or `styles`) in the WP Admin block settings and you would like a fine grained ability on when to enable or have the user enable a specific control. This functionality also provides the benefit of resetting a control to a default state. Additionally new panels can be created using `ToolsPanel` as shown in the example below where a new `Animation` panel would be created. | ||
|
||
### Caveats: | ||
* The `ToolsPanel` component can be used to create entirely new panels that can house `ToolsPanelItem`'s, or extensions can be made to an existing `ToolsPanel`'s by adding individual `ToolsPanelItem`'s to it. | ||
* `ToolsPanel` provides a `resetAll` function that can take each `ToolsPanelItem`'s singular `resetAllFilter` by passing an array of | ||
these functions through to the panel’s `resetAll` callback to iterate over to reset all data within that panel simultaneously. | ||
|
||
## Code Example: | ||
The example below showcases three usages within an `edit.js` file within a custom block: | ||
1. Using a `ToolsPanelItem` to create a singular control that adjusts the alignment of a block within the `typography` group | ||
2. Using a `ToolsPanel` for multiple `ToolsPanelItem`'s in this situation there are multiple controls within the `styles` group that would be used together to create an animation | ||
3. Using a `ToolsPanelItem` to create a singular control that adjusts the width of the block inside the `dimensions` group it also has the `isShownByDefault` which means it will always be displayed inside the block settings and does not need to be clicked on to enable and display. | ||
|
||
```js | ||
import { __ } from '@wordpress/i18n'; | ||
import { useBlockProps, InspectorControls, useSetting, RichText } from '@wordpress/block-editor'; | ||
import { | ||
SelectControl, | ||
__experimentalToggleGroupControl as ToggleGroupControl, | ||
__experimentalToggleGroupControlOption as ToggleGroupControlOption, | ||
__experimentalToolsPanel as ToolsPanel, | ||
__experimentalToolsPanelItem as ToolsPanelItem, | ||
__experimentalUnitControl as UnitControl, | ||
} from '@wordpress/components'; | ||
|
||
const ExampleBlockEdit = (props) => { | ||
const { attributes, setAttributes, clientId } = props; | ||
const { title, width, animationName, animationDuration, animationEasing, alignment } = | ||
attributes; | ||
|
||
const blockProps = useBlockProps({ | ||
style: { | ||
width, | ||
textAlign: alignment, | ||
animationName, | ||
animationDuration, | ||
animationTimingFunction: animationEasing, | ||
}, | ||
}); | ||
|
||
const units = useSetting('spacing.units'); | ||
|
||
const resetAll = () => { | ||
setAttributes({ | ||
animationName: '', | ||
animationDuration: '', | ||
animationEasing: '', | ||
}); | ||
}; | ||
|
||
return ( | ||
<> | ||
<InspectorControls group="typography"> | ||
<ToolsPanelItem | ||
hasValue={() => !!alignment} | ||
label={__('Alignment')} | ||
onDeselect={() => setAttributes({ alignment: undefined })} | ||
resetAllFilter={() => ({ | ||
alignment: undefined, | ||
})} | ||
onSelect={() => setAttributes({ alignment: 'left' })} | ||
panelId={clientId} | ||
> | ||
<ToggleGroupControl | ||
label={__('Toggle')} | ||
value={alignment} | ||
onChange={(value) => setAttributes({ alignment: value })} | ||
> | ||
<ToggleGroupControlOption value="left" label={__('Left')} /> | ||
<ToggleGroupControlOption value="right" label={__('Right')} /> | ||
</ToggleGroupControl> | ||
</ToolsPanelItem> | ||
</InspectorControls> | ||
<InspectorControls group="styles"> | ||
<ToolsPanel label={__('Animation')} resetAll={resetAll}> | ||
<ToolsPanelItem | ||
hasValue={() => !!animationName} | ||
label={__('Name')} | ||
onDeselect={() => setAttributes({ animationName: undefined })} | ||
onSelect={() => setAttributes({ animationName: 'fade-in' })} | ||
> | ||
<SelectControl | ||
label={__('Animation Name')} | ||
value={animationName} | ||
onChange={(value) => setAttributes({ animationName: value })} | ||
options={[ | ||
{ | ||
label: __('Fade In'), | ||
value: 'fade-in', | ||
}, | ||
{ | ||
label: __('Slide In Down'), | ||
value: 'slide-in-down-fade', | ||
}, | ||
{ | ||
label: __('Slide In Up'), | ||
value: 'slide-in-up-fade', | ||
}, | ||
{ | ||
label: __('Slide In Left'), | ||
value: 'slide-in-left-fade', | ||
}, | ||
{ | ||
label: __('Slide In Right'), | ||
value: 'slide-in-right-fade', | ||
}, | ||
]} | ||
/> | ||
</ToolsPanelItem> | ||
<ToolsPanelItem | ||
hasValue={() => !!animationDuration} | ||
label={__('Duration')} | ||
onDeselect={() => setAttributes({ animationDuration: undefined })} | ||
onSelect={() => setAttributes({ animationDuration: '300' })} | ||
> | ||
<SelectControl | ||
label={__('Animation Duration')} | ||
value={animationDuration} | ||
onChange={(value) => setAttributes({ animationDuration: value })} | ||
options={[ | ||
{ label: __('150ms'), value: '150' }, | ||
{ label: __('200ms'), value: '200' }, | ||
{ label: __('250ms'), value: '250' }, | ||
{ label: __('300ms'), value: '300' }, | ||
{ label: __('350ms'), value: '350' }, | ||
{ label: __('400ms'), value: '400' }, | ||
{ label: __('450ms'), value: '450' }, | ||
{ label: __('500ms'), value: '500' }, | ||
]} | ||
/> | ||
</ToolsPanelItem> | ||
<ToolsPanelItem | ||
hasValue={() => !!animationEasing} | ||
label={__('Easing')} | ||
onDeselect={() => setAttributes({ animationEasing: undefined })} | ||
onSelect={() => setAttributes({ animationEasing: 'ease' })} | ||
> | ||
<SelectControl | ||
label={__('Animation Easing')} | ||
value={animationEasing} | ||
onChange={(value) => setAttributes({ animationEasing: value })} | ||
options={[ | ||
{ label: __('Ease'), value: 'ease' }, | ||
{ | ||
label: __('Ease In'), | ||
value: 'ease-in', | ||
}, | ||
{ | ||
label: __('Ease Out'), | ||
value: 'ease-out', | ||
}, | ||
{ | ||
label: __('Ease In Out'), | ||
value: 'ease-in-out', | ||
}, | ||
{ | ||
label: __('Linear'), | ||
value: 'linear', | ||
}, | ||
]} | ||
/> | ||
</ToolsPanelItem> | ||
</ToolsPanel> | ||
</InspectorControls> | ||
<InspectorControls group="dimensions"> | ||
<ToolsPanelItem | ||
hasValue={() => !!width} | ||
label={__('Width')} | ||
onDeselect={() => setAttributes({ width: undefined })} | ||
resetAllFilter={() => ({ | ||
width: undefined, | ||
})} | ||
isShownByDefault | ||
panelId={clientId} | ||
> | ||
<UnitControl | ||
label={__('Width')} | ||
labelPosition="top" | ||
value={width || ''} | ||
min={0} | ||
onChange={(value) => setAttributes({ width: value })} | ||
units={units} | ||
/> | ||
</ToolsPanelItem> | ||
</InspectorControls> | ||
<div {...blockProps}> | ||
<RichText | ||
className="wp-block-example-block__title" | ||
tagName="h2" | ||
placeholder={__('Custom Title')} | ||
value={title} | ||
onChange={(title) => setAttributes({ title })} | ||
/> | ||
</div> | ||
</> | ||
); | ||
}; | ||
export default ExampleBlockEdit; | ||
``` |
ccb401b
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
10up-gutenberg-best-practices – ./
10up-gutenberg-best-practices-fabiankaegy.vercel.app
10up-gutenberg-best-practices-git-main-fabiankaegy.vercel.app
10up-gutenberg-best-practices.vercel.app