How to Manage the Admin-Wide Command Palette in WordPress 6.9

Command Center

The original command palette was released with WordPress version 6.3, but it was only available in the block editor context (i.e., visible in the editor but nowhere else). With WordPress 6.9, this command palette is now everywhere in the admin. This opens up possibilities and what you’re capable of doing with the new palette. For example, if you want to create a “flush permalinks” command, there’s nothing to stop you.

In this tutorial, I’ll go over what’s new in the global command palette, how to tweak it, and, at a high level, how to create your own commands.

Table of Contents

How to open the Command Palette?

Visit the WordPress admin. Use CMD+K (on a Mac) or CTRL+K (on Windows) to open the palette. You can begin typing, for example, the names of available menu items to visit, and the appropriate commands will be displayed.

What is the Command Palette useful for?

Since this is the very beginning of global admin enablement, the command palette is primarily helpful for common shortcuts. However, since the commands are in React and using WP components, you can get really creative and tailor commands specific to your use cases.

For example, you can create a command to set a new site icon. You can also add a command to flush permalinks. You can even add commands to aid plugin discoverability or provide a shortcut to the plugin upload workflow with an upload modal. The possibilities are limitless.

How to disable the global Command Palette?

If you’re not into shortcuts, I don’t blame you. Here’s how to disable the global command palette. The key is the script handle wp-core-commands, which is used to register the command palette.

Disabling commands in just the block editor

To disable the command palette in just the block editor, you can use the following snippet:

<?php
/**
 * Disable command palette in only the block editor, but not the whole admin area.
 *
 * @package wp-disable-commands
 */

add_action( 'enqueue_block_editor_assets', 'wp_disable_commands_enqueue_scripts' );

function wp_disable_commands_enqueue_scripts() {
	wp_deregister_script( 'wp-core-commands' );
}
Code language: PHP (php)

Disabling commands in the admin area, but not the block editor

You can use the following snippet to disable the command area in the general admin, but not in the block editor:

<?php
/**
 * Disable in just the admin area, but not the block editor.
 */
add_action( 'admin_enqueue_scripts', 'wp_disable_commands_enqueue_scripts' );

function wp_disable_commands_enqueue_scripts() {
	// If block editor, return.
	if ( get_current_screen()->is_block_editor() ) {
		return;
	}

	wp_deregister_script( 'wp-core-commands' );
}Code language: PHP (php)

Disable the command palette everywhere

To disable the command palette completely, use the following snippet:

<?php
/**
 * Disable the command palette everywhere.
 */
add_action( 'admin_enqueue_scripts', 'wp_disable_commands_enqueue_scripts' );

function wp_disable_commands_enqueue_scripts() {

	wp_deregister_script( 'wp-core-commands' );
}
Code language: PHP (php)

How to enable the command palette on the frontend

To load the command palette on the frontend, you can use the following snippet:

<?php
/**
 * Enable the command palette on the frontend.
 */
add_action( 'wp_enqueue_scripts', 'wp_enable_command_palette_frontend' );

function wp_enable_command_palette_frontend() {
	if ( ! is_user_logged_in() || ! function_exists( 'wp_enqueue_command_palette_assets' ) ) {
		return;
	}

	// Make sure user has permission to access the command palette.
	if ( ! current_user_can( 'manage_options' ) ) {
		return;
	}

	wp_enqueue_command_palette_assets(); // 6.9 function.

	// Needed to clear up some potential conflicts with other plugins.
	wp_add_inline_style(
		'wp-commands',
		'.commands-command-menu__container .has-icon:not(.components-button) {
			width: inherit;
			height: inherit;
		}'
	);
}
Code language: PHP (php)

The key is new WP 6.9 function wp_enqueue_command_palette_assets.

Running your commands in just the block editor

If you have already created a script with your commands, use hook enqueue_block_editor_assets to load the commands in only the block editor. Do NOT use enqueue_block_assets as this can load in an iframe and will not render the command palette correctly.

<?php
/**
 * Show commands in only the block editor.
 */
add_action( 'enqueue_block_editor_assets', 'wp_show_commands_in_block_editor_enqueue_scripts' );

function wp_show_commands_in_block_editor_enqueue_scripts() {
	if ( file_exists( plugin_dir_path( __FILE__ ) . 'build/block-commands.asset.php' ) ) {
		$deps = require_once plugin_dir_path( __FILE__ ) . 'build/block-commands.asset.php';
		wp_enqueue_script(
			'my-block-commands',
			plugins_url( 'build/block-commands.js', __FILE__ ),
			$deps['dependencies'],
			$deps['version'],
			true
		);
	}
}Code language: PHP (php)

Running your commands in just the admin (not the block editor)

To run a site-wide commands script, use hook admin_enqueue_scripts and check for the block editor.

<?php
/**
 * Show commands in only the admin, but not the block editor.
 */
add_action( 'admin_enqueue_scripts', 'wp_show_commands_in_admin_enqueue_scripts' );

function wp_show_commands_in_admin_enqueue_scripts() {
	if ( get_current_screen()->is_block_editor() ) {
		return;
	}
	if ( file_exists( plugin_dir_path( __FILE__ ) . 'build/site-commands.asset.php' ) ) {
		$deps = require_once plugin_dir_path( __FILE__ ) . 'build/site-commands.asset.php';
		wp_enqueue_script(
			'site-commands',
			plugins_url( 'build/site-commands.js', __FILE__ ),
			$deps['dependencies'],
			$deps['version'],
			true
		);
	}
}
Code language: PHP (php)

Developing your own commands

I highly recommend a Node/Webpack setup using @wordpress/scripts for creating custom command palette commands. I also have a tutorial on how to set up a custom command palette plugin from scratch if you prefer a more in-depth tutorial on commands.

Adding commands to an existing block plugin

If you’re going to add commands to an existing block plugin, I highly recommend you create a separate endpoint so you can load the script separately. Since blocks can be loaded in an iframe, but the command palette cannot, it needs to run in a separate context.

If using @wordpress/scripts, you can modify Webpack and change the entry parameters. This way, a separate script is generated for each new build. The default entry point is index, so we preserve that.

module.exports = ( env ) => {
	return [
		{
			...defaultConfig,
			module: {
				...defaultConfig.module,
				rules: [ ...defaultConfig.module.rules ],
			},
			mode: env.mode,
			devtool: env.mode === 'production' ? false : 'source-map',
			entry: {
				index: [ './src/index.js' ],
				commands: [ './src/commands/index.js' ],
			},
		},
	];
};
Code language: JavaScript (javascript)

I recommend adding @wordpress/commands and @wordpress/icons as project dependencies:

npm install --save-dev @wordpress/commands @wordpress/icons
Code language: Bash (bash)

This will create a build folder with two separate scripts, one you can use for the block editor, and one you can use for commands.

/plugin-folder/
└── /build/
    ├── index.js
    ├── index.asset.php
    ├── commands.js
    └── commands.asset.phpCode language: AsciiDoc (asciidoc)

Registering commands for just the block editor

Adding a Command to Just the Block Editor

If you’re registering commands for just the block editor, I recommend using registerPlugin coupled with the useCommand hook.

You’ll want to enqueue your commands script using hook enqueue_block_editor_assets in order to load for just the block editor.

add_action(
	'enqueue_block_editor_assets',
	function () {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}

		// Enqueue the commands script.
		$deps = require plugin_dir_path( DLX_PHOTO_BLOCK_FILE ) . 'build/commands.asset.php';

		wp_enqueue_script(
			'dlx-photo-block-commands',
			plugins_url( 'build/commands.js', DLX_PHOTO_BLOCK_FILE ),
			$deps['dependencies'],
			$deps['version'],
			true
		);
	}
);Code language: PHP (php)

In the command, use registerPlugin to register the command, but return null so as to not render anything to screen.

import { useCommand } from '@wordpress/commands';
import { plus, pencil } from '@wordpress/icons';
import { __ } from '@wordpress/i18n';
import { registerPlugin } from '@wordpress/plugins';

const registerCommands = () => {
	useCommand( {
		name: 'myplugin/my-command-name',
		label: __( 'My Command Name' ),
		icon: plus,
		callback: ( { close } ) => {
			document.location.href = 'post-new.php';
			close();
		},
	} );
};

// Works in the block editor.
registerPlugin( 'myplugin-my-command-name', {
	render: () => {
		registerCommands();
		return null;
	},
} );Code language: JavaScript (javascript)

Registering commands for the entire admin view

Admin-wide Commands in WordPress

To register a command for the entire admin, a different approach is needed. We need to render an empty div so we can target it via React and run the useCommand hook.

You would use a combination of admin_enqueue_scripts and admin_footer to queue up the command script.

add_action(
	'admin_enqueue_scripts',
	function () {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}

		// Enqueue the commands script.
		$deps = require plugin_dir_path( DLX_PHOTO_BLOCK_FILE ) . 'build/commands.asset.php';

		wp_enqueue_script(
			'dlx-photo-block-commands',
			plugins_url( 'build/commands.js', DLX_PHOTO_BLOCK_FILE ),
			$deps['dependencies'],
			$deps['version'],
			true
		);
	}
);

add_action(
	'admin_footer',
	function () {
		echo '<div id="dlx-photo-block-commands" style="display: none; visibility: hidden; position: absolute; top: 0; left: 0; width: 0; height: 0; overflow: hidden;"></div>';
	}
);Code language: PHP (php)

In JavaScript/React, we can register the plugin using registerPlugin for the block editor, and use createRoot to attach useCommand to the remaining admin area.

import { useCommand } from '@wordpress/commands';
import { createRoot } from '@wordpress/element';
import { plus, pencil } from '@wordpress/icons';
import { __ } from '@wordpress/i18n';
import { registerPlugin } from '@wordpress/plugins';

const registerCommands = () => {
	useCommand( {
		name: 'myplugin/my-command-name',
		label: __( 'My Command Name' ),
		icon: plus,
		callback: ( { close } ) => {
			document.location.href = 'post-new.php';
			close();
		},
	} );
};

// Works in the block editor.
registerPlugin( 'myplugin-my-command-name', {
	render: () => {
		registerCommands();
		return null;
	},
} );

// Works in the admin area.
const Commands = () => {
	registerCommands();
	return null;
};

const root = createRoot( document.getElementById( 'dlx-photo-block-commands' ) );
if ( null !== root ) {
	root.render( <Commands /> );
}Code language: JavaScript (javascript)

Conclusion

With the admin-wide command palette coming with WordPress 6.9, the possibilities are wide open for custom commands and advanced shortcuts.

Within this tutorial, I demonstrated:

  • How to disable and enable the command palette for the various admin sections.
  • How to enable the palette for the frontend.
  • How to add custom commands to the block editor and admin view.

Please leave a comment if you have any questions about this exciting new feature.

Like the tutorial you just read? There's more like it.

There's more where that came from. Enter your email and I'll send you more like it.

This field is for validation purposes and should be left unchanged.

Leave Your Valuable Feedback

Your email address will not be published. Required fields are marked *