Dev Chat summary – February 12, 2020 (5.4 week 9)

@davidbaumwald facilitated the chat on this agenda.

Full meeting transcript on Slack

This devchat marked week 9 of the 5.4 release cycle.

Announcements

WordPress 5.4 Release Candidate 2 was released on Tuesday March 11th as expected 🎉

Feedback from hosts is needed on Make/Hosting regarding SimpleXML PHP extension usage.

@joemcgill shared that XML Sitemaps Feature Plugin version 0.2.0 was released this week and could continue to use feedback from folks testing.

@audrasjb shared that Plugins & Themes Auto-updates Feature Plugin version 0.2.1 was released this week. This feature now have a dedicated Slack channel, created right after the last devchat: #core-auto-updates. There will be weekly meetings on Tuesdays at 18:00 UTC. The kick-off meeting recap is available on Make/Core.

@chanthaboune shared the roadmap to get an All-women Release Squad by the end of 2020.

Upcoming releases

WordPress 5.4 Release Candidate 3 is scheduled for Tuesday March 18th, 2020.

trunk is open for 5.5, but the priority is on 5.4 Release Candidate cycle. Polyglots Team already started to work on translation packages.

Components Check-In

@imath worked on Ticket #49236 and needs some feedback. @jeffpaul advised him to slate it to 5.5 with early keyword so it could be handled at the early stage of the development cycle.

@garrett-eclipse found a list of the components and sub-components without maintainers:

There’s the potential to merge some of the less active sub-components like Charset and Emoji into it’s parent Formatting component. But that would needs further discussion.

Open floor

The main discussion of the open-floor was the Block Editor’s Full Screen Mode enabled by default since WP 5.4 Release Candidate 1.

Here is a quick transcript of the discussion. Please note that no decision has been taken during this chat.

@peterwilsoncc wanted to know when was this committed to the WordPress repository. @jorgefilipecosta answered it was introduced during Beta 3, before WP 5.4 RC 1 was released.

@peterwilsoncc: “same for the release in which it was moved from experimental to stable (for want of a better word) Gutenberg?”. @jorgefilipecosta answered that Full screen mode was not experimental, it was stabilized and working for a long time, it was just not enabled by default (although some hosts were doing it), and the Gutenberg team just had a small PR that enabled the mode by default.

@peterwilsoncc noted that in the discussion on the Make/Core blog, @matt mentions some user testing. @peterwilsoncc asked how much was done.

@joostdevalk proposed to revert and take another look for 5.5, given the negative feedback about this change.

@clorith pointed out that it is still being worked on, and even had a design change between RC1 and RC2. It feels like it’s not ready, and needs more UX work before it goes in.

@chanthaboune asked how the feedback has been in support forums. @ipstenu answered that it’s hard to get feedback in support forums at this stage, since only people beta testing would see it and they tend to be a little more technical savvy than mainstream users.

@youknowriad wanted to clarify some of these questions:
– “I believe we should just the merits of the full screen on its own not whether it can be disabled or not. For instance the customizer is in full screen and it can’t be disabled.
– The UX work after RC1 was a bug fix for RTL languages.
– The feedback is balanced. There were good comments about it. Most negative feedback is about the fact that it becomes default.
– This feature has been on the Gutenberg plugin for more than a year now, It’s in before 5.0.”

@pbiron asked if it was enabled by default in the plugin before being merged into core.

@youknowriad answered that was a request from @matt as release lead prior to the RC.

@joostdevalk added that it’s sounds good to say that @matt has every right to make that call. But he disagrees that this is a good idea in its current form, and he think it will be necessary to guide changes like this more. The Block Editor is changing its default behavior without explaining that in the interface.

For @peterwilsoncc, at this point the question is whether it should be enabled by default rather than whether the feature should exist.

@joemcgill’s main concern is that the reaction to this change will be for people to install code that permanently overrides the feature preference, which makes it harder to move to a fullscreen mode default in the future.

@nilovelez noted that it may seem daunting for existing users, as some part of the UI will apparently be gone, but existing users are the ones that won’t even notice the change. Some attendees disagreed on that as the current behavior for existing users is saved with LocalStorage so it won’t stay for users that use different devices to connect to WordPress Admin.

@clorith also mentioned that Apple clears LocalStorage at set intervals, so users would lose their “don’t use fullscreen” option.

@johnbillion feels concerned that how to switch back to non full screen mode is not obvious.

@youknowriad answered the argument can be turned to the opposite direction for people preferring the full screen mode if it’s disabled. That’s why he think the core team should discuss whether it’s good not whether it can be disabled. For @clorith, given that it’s been off by default, then this is an unexpected change, and thus should not be used as the basis.

@joostdevalk proposed to show how to get out of full screen mode and how to set personal preference in the interface, and save preferences as a user meta and not on the user’s browser.

@jorgefilipecosta pointed out that a new welcome modal is shown to new users. He asked if it would make sense to introduce full screen mode there. @joyously stated that most of the users wouldn’t see it. @jorgefilipecosta, answered that users that won’t see the new modal won’t switch to default FullScreen mode, their preferences will be kept unchanged.

@audrasjb added that users don’t necessarily come to the editor from the posts list. With fullscreen mode and the WP logo button, they can only go back to the Posts list instead of having the full Admin menu. This is the only Admin action/link directly available after editing/publishing a post.

@jorgefilipecosta raised that the development of database persisting mechanism is in progress and that should happen soon. @ipstenu added it really should be a requirement for this feature to land in WordPress Core. @jorgefilipecosta mentioned database persisting for user’s preferences is expected to land in WP 5.5.

In terms of actions, @peterwilsoncc suggested:

  • Setting full screen to off by default
  • Adding some onboarding for when the switch is made
  • Enable once the user’s preference is saved in the database
  • Clarifying exiting full-screen mode (currently active, stated for completeness)

@johnbillion pointed out Matt mentioned that some hosts enabled full screen mode. He asked what is the feedback been regarding not getting lost, switching modes, etc.

@chanthaboune tried to summarize the concerns raised by the attendees:

  • Consistency/persistency of the visual experience
  • More thoughtful user flows
  • Clearer introduction to the full screen functionality

#5-4, #block-editor, #feature-plugins

Fullscreen mode enabled by default in the editor

Starting with WordPress 5.4, the editor behaves differently the first time you open the editor in a new installation or on a new device—or any other time WordPress resets the user preferences.

Now the editor opens in fullscreen mode by default. Note that for now, that’s a local setting, which is why it’s going to reset when your preferences do, including incognito mode. Future releases will store the setting in the WordPress database.

Want to turn it off? It’s simple—just use the pulldown in the editor’s menu.

You can also control the editor’s mode programmatically with the data module. A quick reminder: the code below is JavaScript, not PHP.

const isFullscreenMode = wp.data.select( 'core/edit-post' ).isFeatureActive( 'fullscreenMode' );

if ( isFullscreenMode ) {
    wp.data.dispatch( 'core/edit-post' ).toggleFeature( 'fullscreenMode' );
}

#5-4, #block-editor, #dev-notes

New gradient theme APIs

WordPress 5.4 lets your theme use gradients as backgrounds in Cover and Buttons blocks, courtesy of some new theme APIs. You’ll notice they parallel the approaches of the colors and fonts API.

Configure the predefined set of gradients

Start by configuring a predefined set of gradients. Do that with the theme-support option editor-gradient-presets, then pass an array that represents the gradient set:

add_theme_support(
    'editor-gradient-presets',
    array(
        array(
            'name'     => __( 'Vivid cyan blue to vivid purple', 'themeLangDomain' ),
            'gradient' => 'linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)',
            'slug'     => 'vivid-cyan-blue-to-vivid-purple'
        ),
        array(
            'name'     => __( 'Vivid green cyan to vivid cyan blue', 'themeLangDomain' ),
            'gradient' => 'linear-gradient(135deg,rgba(0,208,132,1) 0%,rgba(6,147,227,1) 100%)',
            'slug'     =>  'vivid-green-cyan-to-vivid-cyan-blue',
        ),
        array(
            'name'     => __( 'Light green cyan to vivid green cyan', 'themeLangDomain' ),
            'gradient' => 'linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%)',
            'slug'     => 'light-green-cyan-to-vivid-green-cyan',
        ),
        array(
            'name'     => __( 'Luminous vivid amber to luminous vivid orange', 'themeLangDomain' ),
            'gradient' => 'linear-gradient(135deg,rgba(252,185,0,1) 0%,rgba(255,105,0,1) 100%)',
            'slug'     => 'luminous-vivid-amber-to-luminous-vivid-orange',
        ),
        array(
            'name'     => __( 'Luminous vivid orange to vivid red', 'themeLangDomain' ),
            'gradient' => 'linear-gradient(135deg,rgba(255,105,0,1) 0%,rgb(207,46,46) 100%)',
            'slug'     => 'luminous-vivid-orange-to-vivid-red',
        ),
    )
);

For more, see https://developer.wordpress.org/block-editor/developers/themes/theme-support/#block-gradient-presets.

Disable custom gradients

You can also disable custom gradients:

add_theme_support( 'disable-custom-gradients' );

This call limits your users to the default gradients you defined in the block editor or that you added to the editor-gradient-presets theme support setting.

For more, see https://developer.wordpress.org/block-editor/developers/themes/theme-support/#disabling-custom-gradients.

Disable gradient functionality

You can also use these APIs to shut down gradient functionality altogether. Just combine these two calls:

add_theme_support( 'disable-custom-gradients' );
add_theme_support( 'editor-gradient-presets', array() );

#5-4, #block-editor, #dev-notes

Markup and style-related changes

WordPress 5.4 makes several DOM structure changes on the block editor. Ideally, your code doesn’t depend on WordPress Core class names or a specific DOM, since class names and the DOM structure are not part of the WordPress public API.

Remove legacy “editor-” class name compatibility

WordPress 5.2 updated the CSS class names of a lot of the components in the block editor, changing editor- prefixes on those class names to block-editor-. Where the old class names still existed, largely in component references, the conventional wisdom urged developers to avoid those references or update them accordingly.

In WordPress 5.4, these old editor--prefixed class names are gone from components in the block-editor scripts. If you’re still referencing the editor-prefixed CSS class name of a component, you’ll need to update to the block-editor- equivalent.

Div with class edit-post-layout__content removed

The `edit-post-layout__content` div is gone from the DOM of the block editor. Check your custom styles and plugin files to make sure you’re not targeting it fir styling.

Blocks and rich text components lose redundant wrappers

Blocks and RichText have been refactored to simplify and lighten the React and DOM tree.

The key to this refactor: moving controls out of the elements and into adjacent popovers, which made four div wrappers redundant—so now they’re gone.

The result: significant performance improvement—and the editor-content DOM looks a lot more like the front end. So styling blocks is now a lot easier for both block and theme authors. Eventually, the plan is to let blocks render the very same tree in the editor as on the front end.

Here’s how those changes have affected the block-editor DOM:

The block-editor-rich-text class is now part of the editable element, unless you’re still using the wrapperClasses prop (which you should really stop using). If you really need a wrapper around the editable element, you’re better off creating your own.

The data-block attribute, containing the block ID, has relocated to the outer block wrapper element. The block-editor-block-list__block-edit class is gone completely; so is the div element. Selectors like .wp-block > .block-editor-block-list__block-edit > [data-block] won’t work anymore. Use .wp-block or just the [data-type] attribute instead.

Simpler block margins

 17877 changes the way the block editor lays out blocks. Before now, every block came with built-in padding, left and right, and negative margins to compensate.

Well, in a bid to radically simplify the CSS you need to style blocks, to develop blocks, to build themes and style the editor in your themes, the built-in padding and negative margins are refactored out of existence—they’re GONE.

Now, if your current block or editor styles have been compensating for those previous margins/paddings, they might look a little off in version 5.4. If so, try getting rid of the styles you wrote to compensate.

#5-4, #block-editor, #dev-notes

General Block Editor API Updates

Meta attribute sources deprecated in 5.4

WordPress 5.4 deprecates meta attribute sources.

Your existing code that uses these attributes should still work, but there’s a new way to get where you want to go.

Instead of meta attributes, use EntityProvider and related hooks APIs. EntityProvider and related hooks APIs provide a more flexible and powerful way to build blocks that source data from a variety of properties of WordPress entities and data.

Here’s how your block’s objects can permit reading and writing to the meta of a post:

const [meta, setMeta] = useEntityProp('postType', 'post', 'meta')

Shortcode transforms: Support isMatch predicate

To bring shortcodes in line with other types of block transformations, you can add an optional isMatch function to see if a given shortcode should transform into a specific block.

For instance, this hypothetical Antarctica Weather block only cares about [weather] shortcodes for Antarctica:

transforms: {
    from: [
        {
            type: 'shortcode',
            tag: 'weather',
            isMatch( { named: { latitude } } ) {
                return parseInt( latitude, 10 ) < -70;
            },
            attributes: {
                latitude: {
                    type: 'number',
                    shortcode: ( { named: { latitude } } ) =>
                        parseInt( latitude, 10 ),
                },
                longitude: {
                    type: 'number',
                    shortcode: ( { named: { longitude } } ) =>
                        parseInt( longitude, 10 ),
                },
            },
        },
    ],
},

If isMatch returns false, the shortcode won’t become an Antarctica Weather block. At that point, another block type can pick it up (presumably, one that matches the [weather] shortcode), or it can stay a shortcode and get encapsulated in a Shortcode block.

New AsyncModeProvider API

Because nobody wants laggy typing in the Editor, the BlockEditor uses an Async Rendering Mode: The selected block gets rerendered synchronously on each change—while the unselected blocks only refresh when the browser goes idle (i.e., while it’s not actively doing some task).

That behavior comes courtesy of the Async Mode, implemented in the wordpress/data package.

In WordPress 5.4, you can use that same sort of asynchronous behavior to speed things up in your own React state trees—as long as they rely on the data module.

That’s because version 5.4 puts the AsyncModeProvider component where you can find it and use it — or, conversely, not use it, since you can also use it to opt out of the block async rendering mode.

import { AsyncModeProvider } from '@wordpress/data';
const MyComponent = () => {
  return (
    <>
        The following component updates synchronously on data store changes
        <MySyncComponent />
        <AsyncModeProvider value={ true }>
            The following component updates asynchronously on data store changes
            <MyAsyncComponent />
        </AsyncModeProvider>
    </>
  );
}

For more about the AsyncMode, you can check this blog post.

A custom media upload handler in a block editor. In a SETTING!

Did you know? You can use the wordpress/block-editor package by itself, to add block-editor pages just about anywhere. Use it for custom WPAdmin pages or even in a completely WordPress-agnostic context.

Here’s an example from the Gutenberg Playground. In a situation like this, WordPress 5.4 lets you add a custom media-upload handler to the block editor—as a setting! (One of your users probably wants this right now.)

import { BlockEditorProvider } from '@wordpress/block-editor';

/**
 * Media Upload Handler
 *
 * @param   {Object}   $0                   Parameters object passed to the function.
 * @param   {?Object}  $0.additionalData    Additional data to include in the request.
 * @param   {string}   $0.allowedTypes      Array with the types of media that can be uploaded, if unset all types are allowed.
 * @param   {Array}    $0.filesList         List of files.
 * @param   {?number}  $0.maxUploadFileSize Maximum upload size in bytes allowed for the site.
 * @param   {Function} $0.onError           Function called when an error happens.
 * @param   {Function} $0.onFileChange      Function called each time a file or a temporary representation of the file is available.
 */
const myMediaUploadHandler = ( settings ) => {
   const mediaObject = {
      id, alt, caption, title, url,
   };    

    settings.onFileChange([mediaObject]);
}

const MyCustomEditor = () => {
  return (
        <BlockEditorProvider settings={ { mediaUpload: myMediaUploadHandler  } }>
            <MyEditorLayout />
        </BlockEditorProvider>
  );
}

Now, realize this: if you leave the mediaUpload handler out of your BlockEditor instance, your editor won’t support media upload at all. Or, it might not let the current user upload media with their current permissions.

You can also give Media Blocks access to this setting in their edit functions, so they can support uploads.

const MyBlockEdit = () => {
   const mediaUpload = useSelect( ( select ) => {
      return select( 'core/block-editor' ).getSettings().mediaUpload;
   }, [] );

   return (
      <>
           { !! mediaUpload && <MyMediaUploadComponent onUpload={ mediaUpload } /> }
       </>
   );
   <
}

Easier drag-and-drop

Do you get complaints about drag-and-drop being more like swing-and-miss? In WordPress 5.4, you can listen to sweet, sweet silence.

That’s because the positioning classes that rendered in the DropZone component (is-close-to-topis-close-to-bottomis-close-to-left and is-close-to-right) are GONE.

In fact, the drop zone is gone. So users have a much bigger target to grab in the blocks they want to move. Easier grab, easier drag, happier users. And you’re the hero.

And with the exit of the drop zone, the editor.BlockDropZone component filter is also gone. That filter was originally supposed to filter media uploads that happened by drag-and-drop— but it didn’t seem to be doing the job well.

If you’d been using that filter, and its removal is a problem, please leave a comment on this note. If there’s enough demand, it’s possible a filter like it, focused on a broader media-upload use case, could emerge from the discussion.

RichText: don’t set focus when applying format

When you’re formatting text in a rich-text instance, does it annoy you to see the focus go back automatically to the editable element? Do your users complain about that behavior?

Well, get happy! In support of more complex UI, to give your users better control of rich-text instances, (e.g. a color control: who wants to have to click back into the color UI for every color change?) the focus will stay where you (or your users) are working until all the color changes, or whatever, are DONE.

Of course, that means that if you do want to keep setting the focus back, say, after a button click, you’ll have to actively make that happen when you’re registering the format type.

You’ll want to do that with the new onFocus function for the edit component.

For example, here’s how that works with the bold format button: https://github.com/WordPress/gutenberg/blob/c5eb9626dc1c73ad9bc543a5d171e9ab4a840996/packages/format-library/src/bold/index.js#L21-L53

New Guide component

A new Guide component was added to the @wordpress/components package (wp.components.Guide). Guide allows developers to easily create a step-by-step guide to display to users. The block editor uses Guide to implement a new welcome modal which appears on first launch.

Guide is a React component that renders a user guide in a modal. The guide consists of several GuidePage components which the user can step through one by one. The guide is finished when the modal is closed or when the user clicks Finish on the last page of the guide.

function MyTutorial() {
    const [ isOpen, setIsOpen ] = useState( true );

    if ( ! isOpen ) {
        return null;
    }

    <Guide onFinish={ () => setIsOpen( false ) }>
        <GuidePage>
            <p>Welcome to the ACME Store! Select a category to begin browsing our wares.</p>
        </GuidePage>
        <GuidePage>
            <p>When you find something you love, click <i>Add to Cart</i> to add the product to your shopping cart.</p>
        </GuidePage>
    </Guide>
}

Deprecation of wordpress/nux

The @wordpress/nux package (wp.nux) has been deprecated along with the DotTip component that it contained. Importing the package will display a warning in the browser console. It is recommended that plugins using wp.nux and DotTip migrate to Guide instead.

#5-4, #block-editor, #dev-notes

New @wordpress/create-block package for block scaffolding

Block scaffolding is a shorthand term that describes the supporting directory structure you need for WordPress to recognize a block. Typically that directory includes files like index.php, index.js, style.css and perhaps others—which in turn hold calls like register_block_type.

You’ve likely noticed a lot of tools that aim to automate the scaffolding build—or at least make it easier to build your own blocks. They’re nothing new in the WordPress ecosystem. And there’s even one in WP-CLI: the wp scaffold block command.

You’ve probably also noticed that some of those third-party tools get you up and running with just one npx command, while WP-CLI still needs a full WordPress installation to run. And WP-CLI doesn’t play well with advanced JavaScript tooling like code transpiling, linting or formatting.

Until now.

WordPress 5.4 brings you a brand-new, officially supported npm-based scaffolding package.

Create Block generates PHP, JS and CSS code—and everything else you need to start building your WordPress plugin. Its quick-start mode lets you pass it a slug that then becomes both the target location for the generated files AND the internal block name:

$ npm init @wordpress/block todo-list
wordpress-create-block

You don’t need to install or configure tools like webpack, Babel or ESLint yourself. They’re preconfigured and out of sight. So you can focus on the code.

Create Block also has an interactive mode that lets you customize several essential block options before code generation:

$ npm init @wordpress/block

Finally, despite its support for modern JavaScript tooling, Create Block also lets you to pick an ES5 template—and skip the transpiling tools that trigger ESNext and JSX support.

Note: If you’re concerned about backwards compatibility, the new tool comes straight from the existing WP-CLI implementation—and in particular, the optional ES5 template uses the existing ES5 code.

#5-4, #block-editor, #dev-notes

Block Collections

Collections allow specific block types to be grouped together for added visibility in the editor’s Inserter menu, regardless of their categories. For instance, a plugin such as CoBlocks may register a Map block of category Widgets and a Post Carousel block of category Layout. By registering a collection for the coblocks namespace, these blocks will appear in the Inserter under their respective categories but also grouped under a CoBlocks collection.

The Block Collections API thus aims to improve the relationship of block discovery between users and plugin authors without compromising the semantics of block types, notably around categories (e.g. formatting, layout, widget, embed).

registerBlockCollection( 'coblocks', {
	title: 'CoBlocks',
	icon: brandAssets.categoryIcon,
} );

#5-4, #block-editor, #dev-notes

New: the block variations API

Just as you can declare a block’s style variations when you register a block, a block type can define block variations the user can pick from. The difference is that, beyond changing the look, this field offers a way to apply initial custom attributes and inner blocks at the point of insertion.

By default, all the variations will show up in the Inserter along with the regular block-type item. But you can set the isDefault flag for any of the listed variations—and in the process, you’ll override the regular block type in the Inserter.

variations: [
    {
        name: 'wordpress',
        isDefault: true,
        title: __( 'WordPress' ),
        description: __( 'Code is poetry!' ),
        icon: WordPressIcon,
        attributes: { service: 'wordpress' },
    },
    {
        name: 'google',
        title: __( 'Google' ),
        icon: GoogleIcon,
        attributes: { service: 'google' },
    },
    {
        name: 'twitter',
        title: __( 'Twitter' ),
        icon: TwitterIcon,
        attributes: { service: 'twitter' },
    },
],

An object describing a variation defined for the block type can contain these fields:

  • name (type string) – The unique and machine-readable name.
  • title (type string) – A human-readable variation title.
  • description (optional, type string) – A detailed variation description.
  • icon (optional, type String | Object) – An icon helping to visualize the variation. It can have the same shape as the block type.
  • isDefault (optional, type boolean) – Indicates whether the current variation is the default one. Defaults to false.
  • attributes (optional, type Object) – Values that override block attributes.
  • innerBlocks (optional, type Array[]) – Initial configuration of nested blocks.
  • example (optional, type Object) – Example provides structured data for the block preview. You can set to undefined to disable the preview shown for the block type.
  • scope (optional, type String[]) – the list of scopes where the variation is applicable. When not provided, it assumes all available scopes. Available options: block, inserter.

#5-4, #block-editor, #dev-notes

New Blocks in WordPress 5.4

Social Icons Block

This new block lets users link to social media and other popular websites by using those sites’ logos. Initially called Social Links, Social Icons were an experimental feature in Gutenberg 6.5 but held out of WordPress 5.3. Since then, the Block Variations API has progressed to the point that Social Icons in Gutenberg 7.5 are much simpler and more stable – and ready for merge in WordPress 5.4.

This reimplementation is a breaking change in the way Social Icons are saved (see details). Only sites that have run the Gutenberg plugin since September are potentially concerned. 

In WordPress 5.4, the core block editor will not recognize any Social Icons blocks built before Gutenberg 7.5.

There are two ways to deal with this:

  • (Recommended method) Manually migrate any content with old Social Icons. Here’s how: load a post in the block editor (Gutenberg 7.5 or higher) and save it. The block editor will automatically update its contents. 
  • Keep the Gutenberg plugin installed after upgrading to WordPress 5.4. The plugin will give you manual backwards compatibility for the old Social Icons.

Buttons Block

This new block is a collection of buttons, because authors often need to use several at a time (for instance: download and read more buttons).

The buttons block shows each button as an individual button-block child of the Buttons block. You won’t be able to insert a button block outside Buttons, but your existing button blocks will work the way they always have.

In case you were using the button block as part of a template or a system that automatically inserted a button block, you’ll want to use the Buttons block with a nested button instead.

Plus, here’s some good news: you won’t need to migrate your existing button blocks. They’ll just work — again, as they always have.

#5-4, #block-editor, #dev-notes

Block Editor Keyboard Shortcuts in WordPress 5.4

WordPress 5.4 introduces a new package called @wordpress/keyboard-shortcuts to centralize the registration/removal and documentation of the available keyboard shortcuts in the block editor screen.

Registering shortcuts

You should register keyboard shortcuts when you load the screen/plugin for the first time, by calling the registerShortcut action.

wp.data.dispatch( 'core/keyboard-shortcuts' ).registerShortcut( {
	// Shortcut name (identifier)
	name: 'plugin/shortcut-name',

 	// Catergory (global, block or selection)
	category: 'block',

	// Description 
	description: 'Short description of your shortcut.',

	// The key combination used to trigger the shortcut
	// Could be just a single character or a character with
	// a modifier.
	keyCombination: {
		modifier: 'primaryAlt',
		character: 't',
	},

	// Some shortcuts can be triggered using several 
	// key combination, the aliases array is used to define
	// the alternative combinations
	aliases: [
		{
			modifier: 'primary',
			character: 'i',
		},
	],
} );

Registering a shortcut automatically adds it to the keyboard shortcuts help modal, where users can find it.

Implementing the keyboard shortcut behavior

The @wordpress/keyboard-shortcuts package also provides the useShortcut React hook to define the behavior triggered by the keyboard shortcuts.

import { useShortcut } from '@wordpress/keyboard-shortcuts';
import { useCallback } from '@wordpress/element';

const MyComponent = () => {
	useShortcut(
		// Shortcut name
		'plugin/shortcut-name',

		// Shortcut callback
		useCallback(
			( event ) => {
				// Do something when the keyboard 
				// shortcut is triggered
			},
			[]
		)
	);
}

Using this React hook instead of a custom implementation comes with a few advantages:

  • If the shortcut is unregistered by a third-party plugin, the callback is just ignored.
  • The shortcut key combination can be modified at runtime and the callback will still be called properly.

Removing existing shortcuts

Registered shortcuts can also be unregistered (and potentially replaced) by third-party plugins

wp.data.dispatch( 'core/keyboard-shortcuts' ).unregisterShortcut(
	'plugin/shortcut-name'
);

Next steps

In the next releases, this package will also let you offer a centralized UI to modify the keyboard shortcuts per user.

#5-4, #accessibility, #block-editor, #dev-notes