Miscellaneous Editor changes in WordPress 6.4

In this dev notedev note Each important change in WordPress Core is documented in a developers note, (usually called dev note). Good dev notes generally include a description of the change, the decision that led to this change, and a description of how developers are supposed to work with that change. Dev notes are published on Make/Core blog during the beta phase of WordPress release cycle. Publishing dev notes is particularly important when plugin/theme authors and WordPress developers need to be aware of those changes.In general, all dev notes are compiled into a Field Guide at the beginning of the release candidate phase., you will find a collection of smaller changes to existing features and APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. updates. For component updates, please see also Updates to user-interface components in WordPress 6.4.

Updated Nov 07, 2023 to add a note on how to retrieve the full Image Light box markup in filters.


Table of Contents


Background image blockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. support

In WordPress 6.4, a new background image block support has been added, with the Group block opted-in by default. For themes using theย appearanceToolsย feature inย theme.json, the control will be available in the inspector controls, under Background.

The feature allows users to set a background image for a Group block. The selected image will be output at render-time for the block via an inline style applied to the blockโ€™s wrapper. When a background image is set, the ruleย background-size: coverย is output along with theย background-imageย property. This ensures that any background images adequately cover the block. Ideas for enhancements in future releases are being tracked in this GitHubGitHub GitHub is a website that offers online implementation of git repositories that can easily be shared, copied and modified by other developers. Public repositories are free to host, private repositories require a paid subscription. GitHub introduced the concept of the โ€˜pull requestโ€™ where code changes done in branches by contributors can be reviewed and discussed before being merged by the repository owner. https://github.com/ issue:ย #54336

How to add backgroundImage support to a theme

There are two ways to add support forย backgroundImageย to a block theme. The simplest is to opt in to theย appearanceToolsย setting, which automatically enables a number of design tools (read more in the developer handbook).

For themes that wish to have more granular control over which UIUI User interface tools are enabled, theย backgroundImageย support can be opted into by settingย settings.background.backgroundImageย toย trueย inย theme.json. For example:

{
	"settings": {
		"background": {
			"backgroundImage": true

Note that as of WP 6.4, theย backgroundImageย support is only available at the individual block level, and not in global styles or at the site root.

For context and more information, viewย #53081.

Props to @andrewserong for the dev note (top)

FilterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. behavior when using newย Expand on Clickย in Image block

If your image block with `Expand on Click` enabled has Lightbox markup that you canโ€™t seem to access from inside your filter function, below is some extra information you might need.

As of WordPress 6.4, please be aware that a built-in filter for the image block has been applied with priority 15 for images with `Expand on Click`. This means that if your filter has a priority of 15 or lower (the default is 10), then the markup used to create the Lightbox behavior will not be available to your function for processing by default.

Please make sure to use priority of at least 16 when adding filters to process the image block if you need to access the Lightbox markup.

add_filter( 'render_block_core/image', 'my_custom_html', 16 )

More information on this issue.

Props to @artemiosans and @afercia for surfacing the issue and documentation (top)

Fluid typography: configurable minimum and maximum viewport values

WordPress 6.4 introduces configurable minimum and maximum viewport width values to fluid typography settings in theme.json.Theme developers can now define their own default viewport โ€œboundariesโ€ for calculating fluid font sizes. These boundaries determine the browser viewport widths at which any font size clamp values will stop being โ€œfluidโ€.

For example, given the following theme.jsonJSON JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML. settings:

"settings": { 
    "typography": { 
        "fluid": { 
            "maxViewportWidth": "800px", 
            "minViewportWidth": "600px" 
        }, 
    } 
}

Between the browser widths ofย 600pxย andย 800px, a font size will be fluid, and therefore scale up or down according to the current viewport size. If the browser width is narrower thanย 600pxย or wider thanย 800px, the font size will no longer shrink or grow.

Due to the way the Block Editor calculates fluid font size values,ย maxViewportWidthย andย minViewportWidthย only acceptย px,ย remย andย emย units.

In the case of unsupported values, including CSSCSS Cascading Style Sheets. variables, fallbackย maxViewportWidthย andย minViewportWidthย are used โ€“1600pxย andย '320px'ย respectively.

For context and more information, viewย #53081.

Props to @ramonopoly for the dev note (top)

Disable layout controls fromย theme.json

With WordPress 6.4, it is now possible to disable layout controls globally for all blocks or on a per-block level fromย theme.json. This ensures that affected blocks still output their default layout styles, but the controls to edit them wonโ€™t be available in the block sidebarSidebar A sidebar in WordPress is referred to a widget-ready area used by WordPress themes to display information that is not a part of the main content. It is not always a vertical column on the side. It can be a horizontal rectangle below or above the content area, footer, header, or any where in the theme..

To disable the controls for all blocks,ย "allowEditing": falseย should be added toย settings.layout, like so:

"settings": {
    "layout": {
        "allowEditing": false
    }
}

To disable the controls for individual blocks, addย "allowEditing": falseย inย settings.blocks.[block name].layout, thus:

"settings": {
    "blocks": {
        "core/cover": {
            "layout": {
                "allowEditing": false
            }
        }
    }
}

For context and more information, viewย  #53378. (top)

Props to @isabel_brison for above dev note (top)

RichTextโ€™s multiline prop replaces with simple multiple instances

RichTextโ€˜sย multilineย prop has been deprecated since 6.1 and was scheduled for removal in 6.3. Weโ€™re leaving the deprecated prop in place, but its functionality has been simplified internally, so you may experience changes.

Instead of one large rich text field, each line is now its own rich text field. Contributors added a splitting and merging functionality, so the fallback is gracious, but some things like paste may work differently. Itโ€™s worth noting that this prop remains deprecated and all block authors are encouraged to useย InnerBlocksย instead.

For context and more information, viewย #54310.

Props to @ellatrix for the above dev note (top)

New public hook in the Block Editor API: useBlockEditingMode()

Blocks can set an editing โ€œmodeโ€ using theย useBlockEditingModeย hook. useBlockEditingMode()ย allows a block to restrict the user interface that is displayed for editing that block and its inner blocks.

The block editing mode can be one of three options:

  • 'disabled': Prevents editing the block entirely, that is, it cannot be selected.
  • 'contentOnly': Hides all non-content UI, for example, auxiliary controls in the toolbar, the block movers, block settings.
  • 'default': Allows editing the block as normal.

The block editing mode is inherited by all the blockโ€™s inner blocks, unless inner blocks have their own modes set.

Usage:

function MyBlock( { attributes, setAttributes } ) { 
     useBlockEditingMode( 'disabled' ); 
     // MyBlock will be marked as 'disabled' editing mode. 
     return ; 
}

useBlockEditingMode()ย also returns a blockโ€™s current editing mode, which can be utilized to further configure block properties. For example, a component inheriting its parentโ€™s block editing mode:

function ChildComponent( props ) { 
     const blockEditingMode = useBlockEditingMode(); 
     let text = 'Child component'; 
     if ( blockEditingMode === 'disabled' ) { 
     // Block is disabled, add custom block properties to indicate disabled mode.
          text+= ' is disabled!'; 
     } 

    if ( blockEditingMode === 'default' ) {
       // Block can be edited, show controls or other editing-related settings.     \
         
    } 
   return 
{ text }
; }

For context and more information, viewย #52094.

Props to @ramonopoly for above dev note (top)

Threeย experimental APIs were stabilizedย in WordPress 6.4. That means they should be safe from backward-compatibility issues when you use them in production:

  • defaultBlock
  • directInsert
  • getDirectInsertBlock

More information on GitHub #52083. The documentation on Nested Blocks reflects the updates.

Props to @smrubenstein for dev note (top)

Introduce SCRIPT_DEBUG to make package compatibile with Webpack 5

This change in WordPress coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. is mostly an internal optimization to send less code to the browser. It could be useful for developers usingย @wordpress/scriptsย that it is possible to hide code behind this debug flag.

if ( typeof SCRIPT_DEBUG !== 'undefined' && SCRIPT_DEBUG === true ) {
    // This code runs only in the development mode and gets completely removed from the production build.
}

For context and more information, viewย #50122.

Props to @gziolo for above dev note (top)

Add edits data to the useEntityRecord

Now, the useEntityRecord adds to its output a key calledย editsย containing the nonTransientEdits of an entity record. A code example

const widget = useEntityRecord( 'root', 'widget', 1 ); 
widget.edit( { hello: 'foo' } );

Expected result:

{ edits: { hello: 'foo' } ... }

For context and more information, viewย #541673.

Props to @mmaattiiaass for above dev note (top)


Props for review of the full post to @webcommsat and @priethor

#6-4, #dev-notes, #dev-notes-6-4

Script loading changes in WordPress 6.4

Script loading strategies are now employed in coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. and bundled themes to improve performance of loading scripts with defer and async attributes. Additionally, scripts on the frontend and login screen are now constructed using script helper functions, making it possible to utilize Content Security Policy to harden against any XSS vulnerabilities. This change also has back-compat implications for the obsolete use of the clean_url filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. to inject defer and async attributes; plugins should now use the script loading strategies APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. instead. The full details follow.

Utilizing script loading strategies

In WordPress 6.3, the script loading strategies were introduced (#12009), enabling scripts to finally have an API for marking them to be printed with async or defer without resorting to filtering script_loader_tag (or worse clean_url, per below). For more information, refer to the dev note on Registering scripts with async and defer attributes in WordPress 6.3.

In WordPress 6.4, script loading strategies are now being employed for frontend scripts in core and bundled themes. For the most part, the defer loading strategy is used since it is more consistent in its loading behavior, in that a defer script always executes once the DOM has loaded; a script with `async` may actually blockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. rendering if it is already cached.ย 

Additionally, scripts now loading with defer have been moved from the footer to the head so that they are discovered earlier while the document is loading and can execute sooner once the document is loaded. The changes include:

  • The defer loading strategy is being used for all block view scripts, such as the Navigation, File, and Search blocks as well as any blocks added by plugins. (#59115)
  • The defer loading strategy is also now being used for the wp-embed script which is included when there is a WordPress post embed present on the page. (#58931)
  • Frontend scripts used in bundled themes also use the defer loading strategy. (#59316)
  • The async loading strategy is used for the comment-reply script, and it continues to load in the footer since it is low priority being that comments are not visible when first viewing a post. (#58870)

If there is any theme or pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party. that enqueues a script that depends on any of the above scripts (which is unlikely), the script loading strategy API considers the dependents of a delayed script so that if any of them are blocking, the delayed script will also fall back to blocking. This ensures the execution order is preserved.

Eliminating manual construction of script tags

Throughout WordPress core there have been many places where script tags are manually constructed instead of relying on the helper functions wp_print_inline_script_tag(), wp_get_inline_script_tag(), wp_print_script_tag(), and wp_get_script_tag(). In WordPress 6.4 via #58664, these functions are now employed for all scripts printed to the frontend and for scripts printed on the login screen. This includes all scripts printed via wp_enqueue_script() as well as other functions that interact with WP_Scripts, namely wp_add_inline_script() and wp_localize_script(). More details onย  #59446 which continues this work throughout wp-adminadmin (and super admin).

Using these helper functions makes core easier to read and maintain with less code duplication. It also opens the door to being able to leverage Content Security Policy (CSP) for hardening WordPress against script injection attacks (XSS vulnerabilities). This is due to these functions allowing additional attributes to be added to script tags via the wp_script_attributes and wp_inline_script_attributes filters, allowing the nonce attribute to be added. Refer to an example plugin that enables Strict CSP on the frontend and login screens.

On a related note to the script loading strategies above, there is one aspect of this change that breaks a prior method for adding async or defer to scripts using the clean_url filter:

<?php
// โš  WARNING: Do not do this.
function defer_parsing_of_js ( $url ) {
    if ( FALSE === strpos( $url, '.js' ) ) return $url;
    if ( strpos( $url, 'jquery.js' ) ) return $url;
    return "$url' defer ";
}
add_filter( 'clean_url', 'defer_parsing_of_js', 11, 1 );

This no longer works with WordPress 6.4 because the script URLURL A specific web address of a website or web page on the Internet, such as a websiteโ€™s URL www.wordpress.org is now escaped when constructing the HTMLHTML HyperText Markup Language. The semantic scripting language primarily used for outputting content in web browsers. attributes for the script tagtag A directory in Subversion. WordPress uses tags to store a single snapshot of a version (3.6, 3.6.1, etc.), the common convention of tags in version control systems. (Not to be confused with post tags.). So previously if it resulted in this script tag:

<script src='/wp-includes/js/underscore.js?ver=1.13.4' defer></script>

It now results in:

<script src="/wp-includes/js/underscore.js?ver=1.13.4%27%20defer"></script>

The clean_url filter (introduced in WP 2.3) never should have been used for this purpose once the script_loader_tag filter was introduced in WP 4.1. The clean_url filter runs on every single URL on the page, not just the script URLs. Also, the clean_url filter approach relied on scripts being printed with single-quoted HTML attribute values.ย 

Plugins continuing to use the clean_url filter in this way will find that the desired attribute is no longer injected, and that the attribute instead appears appended to the ver query parameter for the script. Plugins seeking to add defer or async attributes should instead now use the script loading strategies API. More on the dev notedev note Each important change in WordPress Core is documented in a developers note, (usually called dev note). Good dev notes generally include a description of the change, the decision that led to this change, and a description of how developers are supposed to work with that change. Dev notes are published on Make/Core blog during the beta phase of WordPress release cycle. Publishing dev notes is particularly important when plugin/theme authors and WordPress developers need to be aware of those changes.In general, all dev notes are compiled into a Field Guide at the beginning of the release candidate phase. Registering scripts with async and defer attributes in WordPress 6.3.ย 

Props to @webcommsat and @flixos90 for reviewing.

#6-4, #dev-notes, #dev-notes-6-4

Changes to attachment pages

As of WordPress 6.4, attachment pages for new WordPress installations are fully disabled.

Until WordPress 6.4 was released, WordPress created attachment pages by default for every attachment uploaded. On the vast majority of sites, these attachment pages donโ€™t add any meaningful information. They do, however, exist, get indexed by search engines, and sometimes even rank in search results, leading to bad results for users and site owners.

This change introduces aย wp_attachment_pages_enabledย database option to control the attachment pagesโ€™ behavior:

  • On existing sites, the option is set toย 1ย on upgrade, so that attachment pages continue to work as is.
  • For new sites, the option is set toย 0ย by default, which means attachment pages are redirected to the attachment URLURL A specific web address of a website or web page on the Internet, such as a websiteโ€™s URL www.wordpress.org.
  • Sites administrators who want to enable or disable the attachment pages can set the option toย 1ย orย 0, respectively.

When attachment pages are disabled, the adminadmin (and super admin) link โ€œView attachment pageโ€ changes to โ€œView Media Fileโ€.

Setting the option

Via WP CLICLI Command Line Interface. Terminal (Bash) in Mac, Command Prompt in Windows, or WP-CLI for WordPress.

To test this change or if you just want to change it on a live site, you can use WP CLI. You would do so like this:

wp option set wp_attachment_pages_enabled 0|1

Via a pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party.

Another option is to use this small plugin built by @costdev during the development process that allows enabling the attachment pages through an admin bar item.

Via the admin options page

While this is not usually recommended, you can visit wp-admin/options.php on your site, search for wp_attachment_pages_enabled and change the option right there.

TracTrac An open source project by Edgewall Software that serves as a bug tracker and project management tool for WordPress. ticketticket Created for both bug reports and feature development on the bug tracker. #57913

Props to @joostdevalk for writing the dev notedev note Each important change in WordPress Core is documented in a developers note, (usually called dev note). Good dev notes generally include a description of the change, the decision that led to this change, and a description of how developers are supposed to work with that change. Dev notes are published on Make/Core blog during the beta phase of WordPress release cycle. Publishing dev notes is particularly important when plugin/theme authors and WordPress developers need to be aware of those changes.In general, all dev notes are compiled into a Field Guide at the beginning of the release candidate phase..

Props to @sabernhardt @bph and @webcommsat for peer review.

#6-4, #dev-notes, #dev-notes-6-4

Introducing admin notice functions in WordPress 6.4

Adminadmin (and super admin) notices are widely used within WordPress CoreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. and in the extender community. Admin notices have common markup patterns and CSSCSS Cascading Style Sheets. classes, but required maintaining HTMLHTML HyperText Markup Language. The semantic scripting language primarily used for outputting content in web browsers. independently for each notice throughout a project.

In #57791, two new functions were proposed: wp_get_admin_notice() and wp_admin_notice().

These functions abstract the HTML markup generation to reduce the maintenance burden, encourage consistency, and enable argument and message filtering for all admin notices. In addition, a new wp_admin_notice action has been introduced, which fires before a notice is output.

New functions

wp_get_admin_notice()

  • Returns the markup for an admin notice.
  • Note: The markup is not fully escaped and care should be taken to select the appropriate escaping function before output.

wp_admin_notice()

  • Outputs the markup for an admin notice.
  • Markup is created using wp_get_admin_notice() and escaped using wp_kses_post() before output.

Parameters

Both functions have the following parameters:

  • string $message The message for the notice.
  • array $args An array of arguments for the notice.
    • string $type Optional. The type of admin notice. This will be appended to 'notice-' to create the HTML class name. For example, a type of 'success' will produce a 'notice-success' HTML class. Default empty string.
    • bool $dismissible Optional. Whether the notice is dismissible. Default false.
    • string $id Optional. The value for the HTML id attribute. Default empty string.
    • array $additional_classes Optional. An array of additional class names to use for the notice. These are used as provided. Default empty array.
    • array $attributes Optional. An associative array of HTML attributes for the notice. Boolean true attributes may just include the name of the attribute. Default empty array.
    • bool $paragraph_wrap Optional. Whether to wrap the message in <p></p> tags. Default true.

Filters

wp_get_admin_notice() applies the following filters:

  • wp_admin_notice_args โ€“ Filters the arguments for an admin notice.
    • Passed arguments: array $args, string $message
  • wp_admin_notice_markup โ€“ Filters the markup for an admin notice.
    • Passed arguments: string $markup, string $message, array $args

Actions

wp_admin_notice() fires the following action:

  • wp_admin_notice โ€“ Fires before an admin notice is output.
    • Passed arguments: string $message, array $args

Example usage

Output a dismissible success notice

wp_admin_notice(
  __( 'Plugin update failed.', 'my-text-domain' ),
  array(
    'type'               => 'error',
    'dismissible'        => true,
    'additional_classes' => array( 'inline', 'notice-alt' ),
    'attributes'         => array( 'data-slug' => 'plugin-slug' )
  )
);

Result

<div class="notice notice-error is-dismissible inline notice-alt" data-slug="plugin-slug"><p>Plugin update failed.</p></div>

Create a collection of notices to output at onceย 

$output = '';
foreach ( $success_messages as $message ) {
  $output .= wp_get_admin_notice(
    $message,
    array( 'type' => 'success' )
  );
}

echo wp_kses_post( $output );

Result

<div class="notice notice-success"><p>Success message 1</p></div>

(repeated for each notice)

Add a class to every โ€˜warningโ€™ admin notice

add_filter( 'wp_admin_notice_args', 'myprefix_add_class_to_warnings' );
function myprefix_add_class_to_warnings( $args ) {
  if ( 'warning' === $args['type'] ) {
    $args['additional_classes'][] = 'my-class';
  }

  return $args;
}

Result

<div class="notice notice-warning my-class"><p>Warning message 1</p></div>

(repeated for each warning notice)

Usage in WordPress Core

The new admin notice functions have been implemented in most locations in WordPress Core. Further work will be done in WordPress 6.5 to complete the process and migrate older notices (using the 'updated' and 'error' classes) to the current admin notice pattern ('notice-success', 'notice-info', 'notice-warning', and 'notice-error').

Props to @joedolson and @webcommsat for peer review.

#6-4, #dev-notes, #dev-notes-6-4

Updates to user-interface components in WordPress 6.4

This post lists notable changes to theย @wordpress/componentsย package for the WordPress 6.4 release

Table of Contents

Making Popover.Slot optional

As part of a wider effort to streamline the developer experience of using GutenbergGutenberg The Gutenberg project is the new Editor Interface for WordPress. The editor improves the process and experience of creating new content, making writing rich content much simpler. It uses โ€˜blocksโ€™ to add richness rather than shortcodes, custom HTML etc. https://wordpress.org/gutenberg/ as a platform/framework to build blockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. editors, the Popover component has been tweaked so that itโ€™s not necessary anymore to manually specify a Popover.Slot component (and a SlotFillProvider) somewhere in the ReactReact React is a JavaScript library that makes it easy to reason about, construct, and maintain stateless and stateful user interfaces. https://reactjs.org tree.

The Popover component now works out of the box, and the Popover.Slot component can be optionally used to tweak where the popover should render in the DOM tree.

A side-effect of this change is that some instances of Popover may not render inline anymore when a Popover.Slot is not rendered on the page, affecting both the popoverโ€™s DOM position and the styles inherited via the CSSCSS Cascading Style Sheets. cascade. To mitigate this use case, a new inline prop has been added to the Popover component, to force the component to render inline, thus preserving the legacy behavior.

For more information visit #53889, #53982, and #54912.ย (top)

Rewriting Tooltip and TabPanel

The Tooltip and the TabPanel components have been completely rewritten to leverage third-party, headless libraries (specifically ariakit) as the first tasks of a new experimental effort within the package.

Both migrations were intentionally designed to avoid changes to the APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. or developer experience, while also bringing several benefits:

  • better compliance with semantics, accessibilityAccessibility Accessibility (commonly shortened to a11y) refers to the design of products, devices, services, or environments for people with disabilities. The concept of accessible design ensures both โ€œdirect accessโ€ (i.e. unassisted) and โ€œindirect accessโ€ meaning compatibility with a personโ€™s assistive technology (for example, computer screen readers). (https://en.wikipedia.org/wiki/Accessibility) requirements, and related WAI-ARIA patterns;
  • better user experience thanks to using a widely used, well-tested underlying implementation;
  • better types and improved unit tests;
  • less maintenance required in the long term.

Specifically to the Tooltip component, the refactor also fixed a long-standing issue and presented the opportunity to align with other components already using a new placement prop in lieu of the legacy, now deprecated position prop.

For TabPanel, the only noteworthy change is that tabpanel elements now get a tabstop. This means that when focused on a Tab, pressing the [Tab] key will apply focus to the tabpanel itself, rather than jumping directly to the next focusable element within the tabpanel element.

As mentioned above, this was part of an experiment around using third-party libraries more deliberately in the components package. In the future, we may look at more opportunities for such rewrites, especially for components with more complex semantics and accessibility implementations.

For more information visit #48440, #54264, #54406, and #52133.ย (top)

New props for the Modal component

The Modal component has been enhanced with a couple of additions to its APIs. Thanks to a new headerActions prop, developers using the Modal can inject buttons (and other elements) into the Modalโ€˜s headerHeader The header of your site is typically the first thing people will experience. The masthead or header art located across the top of your page is part of the look and feel of your website. It can influence a visitorโ€™s opinion about your content and you/ your organizationโ€™s brand. It may also look different on different screen sizes., next to the close button.

The focusOnMount prop has also received an update, and it now accepts a new "firstContentElement" option. When setting focusOnMount="firstContentElement", the Modal component will try to focus on the first tabbable element within the Modalโ€˜s content (ie. the markup passed via the children prop).

This is different from the pre-existing "firstElement" option, which causes focus to go to the first element anywhere within the Modal, including its header (usually the close button).

Note that it is the responsibility of the developer to ensure that, when focusOnMount="firstContentElement", there is at least one tabbable element within the Modalโ€˜s children.

For more information visit #53328 and #54590.ย (top)

Improving size consistency for UIUI User interface components

UI components across the editor (input fields, buttons, etc) are currently rendering in a range of heights between 30px and 40px. In order to add consistency and visual polish to the editorโ€™s UI, we started working on standardizing components toward having a default height of 40px.

To ensure a smooth transition to the new default sizes, we have started to introduce a new, temporary __next40pxDefaultSize prop on selected components around the codebase, which will allow consumers to start opting into the new default size. Sometime after that, the temporary prop will be deprecated and ultimately removed, causing _all_ instances of the components to switch to the default 40px size out of the box.

To start opting into the new 40px default height, set theย __next40pxDefaultSizeย prop toย true:

<Button __next40pxDefaultSize>
  Code is poetry
</Button>

So far, the components exposing the new temporary __next40pxDefaultSize prop are:

For more information visit #46734 and #46741.ย (top)

More granular control of decimal places on NumberControl-based components

A new spinFactor prop has been added to NumberControl, allowing consumers of the components to specify by how much should the inputโ€™s value increment/decrement with respect to the step. This is particularly useful when more granular control is needed (thus allowing for more decimal places and a smaller step) but without sacrificing the UXUX User experience around manually incrementing/decrementing the value.

Even if the prop was added to NumberControl, all components based on NumberControl can benefit from this change โ€” this includes, for example, UnitControl and LineHeightControl.

For more information visit #52902.ย (top)

Rendering CircularOptionPicker as a listbox by default

To improve CircularOptionPickerโ€˜s semantics and keyboard navigation, the component has been tweaked to render and behave as a listbox by default. This change also causes the component to become a single tab stop, with the individual color options accessed using arrow keys.

In the (few) instances in which it makes sense for CircularOptionPicker to still render as a list of individual buttons, consumers of the component can use the asButtons prop to switch back to the legacy behavior.

For more information visit #52255 and #54290.ย (top)

Adding an option for FormTokenField to create a new token when losing focus

A new tokenizeOnBlur prop has been added to FormTokenField, causing the component to tokenize its current input instead of discarding it when losing focus.

This is particularly useful when FormTokenField is used in places like modals, where the user may press a button causing the modal to close and FormTokenField to lose focus before its input could be tokenized.

For more information visit #54445.ย (top)

Controlling open/closed state of Dropdown and DropdownMenu

The open/closed state of the Dropdown and DropdownMenu components can now be controlled by their consumers via the open, onToggle and defaultOpen props, allowing more flexibility and more advanced behaviors when using these components.

For more information visit #54257.ย (top)

Props toย @brookemk, @tyxla and @shireling for the help in writing theseย dev notesdev note Each important change in WordPress Core is documented in a developers note, (usually called dev note). Good dev notes generally include a description of the change, the decision that led to this change, and a description of how developers are supposed to work with that change. Dev notes are published on Make/Core blog during the beta phase of WordPress release cycle. Publishing dev notes is particularly important when plugin/theme authors and WordPress developers need to be aware of those changes.In general, all dev notes are compiled into a Field Guide at the beginning of the release candidate phase..

Props to @bph and @webcommsat for reviews

#6-4, #dev-notes, #dev-notes-6-4

Newย `registerInserterMediaCategory`ย API

From WordPress 6.4, extenders can register their own inserter media categories and provide users with more options from which to choose.

Even though the coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress.โ€™s media categories are a blockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. editor setting, it is a private one, which means it cannot be updated through the public updateSettings action. Extenders can only add new inserter media categories, and they donโ€™t have any control over the core media categories, except for being able to disable the Openverse media categoryCategory The 'category' taxonomy lets you group posts / content together that share a common bond. Categories are pre-defined and broad ranging. with enableOpenverseMediaCategory block editor setting.

Every inserter media category should have a unique name property, which is used internally like an id, so itโ€™s best to prefix this. Additionally, each category should have a unique label to be differentiated from the other ones(labels.name property).

You can read more about the used interfaces that a media category, media item and the request for media should abide to, on the documentation pages.

The example uses the Openverse category object and just updates the names used:

wp.data.dispatch( 'core/block-editor' ).registerInserterMediaCategory( {
	name: 'my-new-category',
	labels: {
		name: 'My new category',
		search_items: 'Search Openverse',
	},
	mediaType: 'image',
	async fetch( query = {} ) {
		const defaultArgs = {
			mature: false,
			excluded_source: 'flickr,inaturalist,wikimedia',
			license: 'pdm,cc0',
		};
		const finalQuery = { ...query, ...defaultArgs };
		// Sometimes you might need to map the supported request params 
                // according to `InserterMediaRequest`.
		// interface. In this example the `search` query param is named `q`.
		const mapFromInserterMediaRequest = {
			per_page: 'page_size',
			search: 'q',
		};
		const url = new URL( 'https://api.openverse.engineering/v1/images/' );
		Object.entries( finalQuery ).forEach( ( [ key, value ] ) => {
			const queryKey = mapFromInserterMediaRequest[ key ] || key;
			url.searchParams.set( queryKey, value );
		} );
		const response = await window.fetch( url, {
			headers: {
				'User-Agent': 'WordPress/inserter-media-fetch',
			},
		} );
		const jsonResponse = await response.json();
		const results = jsonResponse.results;
		return results.map( ( result ) => ( {
			...result,
			// If your response result includes an `id` prop 
                        // that you want to access later, it should
			// be mapped to `InserterMediaItem`'s `sourceId` prop. 
                        // This can be useful if you provide a report URL getter.
			// Additionally you should always clear the `id` value of 
                        // your response results because it is used to identify 
                        // WordPress media items.
			sourceId: result.id,
			id: undefined,
			caption: result.caption,
			previewUrl: result.thumbnail,
		} ) );
	},
	getReportUrl: ( { sourceId } ) =>
		`https://wordpress.org/openverse/image/${ sourceId }/report/`,
	isExternalResource: true,
} );

Props to @bph and @webcommsat for review.

#6-4, #dev-notes, #dev-notes-6-4

Introducing Block Hooks for dynamic blocks

WordPress 6.4 introduces BlockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. HooksHooks In WordPress theme and development, hooks are functions that can be applied to an action or a Filter in WordPress. Actions are functions performed when a certain event occurs in WordPress. Filters allow you to modify certain functions. Arguments used to hook both filters and actions look the same. (#53987), a feature that provides an extensibility mechanism for Block Themes. This is the first step in emulating WordPressโ€™ย Hooksย concept that allows developers to extend Classic Themes using filters and actions.

Specifically, the Block Hooks APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. allowsย a block to automatically insert itself relative to instances of other block types. For example, a โ€œLikeโ€ button block can ask to be inserted before the Post Content block, or an eCommerce shopping cart block can ask to be inserted after the Navigation block.

Tenets and current limitations

There are two coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. tenets of Block Hooks:

  1. Front-end insertion should happen as soon as the pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party. containing a hooked block is activated. In other words, the user isnโ€™t required to insert the block in the Editor manually. Similarly, disabling the plugin should remove the hooked block from the front end.
  2. The user has the ultimate control over any automatically inserted blocks. This means that a hooked block is visible in the Editor, and the userโ€™s decision to keep, remove, customize, or move the block will be respected and reflected on the front end.

To account for both tenets, tradeoffs had to be made. Block hooks are limited to templates, template parts, and patterns (i.e., the elements that define the layout of the theme). For patterns, this includes those provided by the theme, fromย Block Pattern Directory, or from calls toย register_block_pattern.

Blocks cannot be hooked into post content or patterns crafted by the user, such as synced patterns or theme templates and template parts that the user has modified.

Furthermore, as of WordPress 6.4, you canโ€™t automatically insert blocks that have a save function, or block validation errors will occur. In colloquial terms, this means that Block Hooks work with Dynamic blocks, not Static blocks. Refer to this article on the difference between the two.

Using Block Hooks

You can implement Block Hooks in two different ways: in a blockโ€™s block.json file or using the new hooked_block_types filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output.. While simpler, the block.json method provides a more limited implementation, so letโ€™s review that first.

block.json

The block.json method allows you to hook a third-party block unconditionally, meaning that the block will be inserted relative to all instances of the target (anchor) block provided the abovementioned limitations.

In the blockโ€™s block.json file, include the blockHooks property. This property takes an object where the key (string) is the name of the block you want to hook into, and the value (string) specifies its position. Possible positions are:

  • beforeย โ€“ inject before the target block.
  • afterย โ€“ inject after the target block.
  • firstChildย โ€“ inject before the first inner block of the target container block.
  • lastChildย โ€“ inject after the last inner block of the target container block.
{
    blockHooks: {
        'core/verse': 'before'
        'core/spacer': 'after',
        'core/column': 'firstChild',
        'core/comment-template': 'lastChild',
    }
}

In the example above, the block will be inserted before every Verse block that appears in an unmodified template, template part, or pattern. It will also be inserted after every Spacer block, etc.

When using the block.json method with firstChild or lastChild, a Setting SidebarSidebar A sidebar in WordPress is referred to a widget-ready area used by WordPress themes to display information that is not a part of the main content. It is not always a vertical column on the side. It can be a horizontal rectangle below or above the content area, footer, header, or any where in the theme. panel titled Plugins will be added to the target block in the Editor. This allows the user to toggle on and off the hooked block.

Below is an example of a Like button block that is hooked to the lastChild position in the Comment Template block.

The Like button block is hooked to the 'lastChild' position of the Core Comment Template block.

hooked_block_types

The hooked_block_types filter provides more flexibility. It allows you to hook any Dynamic block unconditionally, like the block.json method, or conditionally based on the template, template part, or pattern where the target (anchor) block is located.

The callback function for the filter accepts four parameters:

  • $hooked_blocksย (array) โ€“ An array of hooked blocks.
  • $position (string) โ€“ The relative position of the hooked block: before, after, first_child, or last_child.
  • $anchor_blockย (string) โ€“ The name of the anchor block.
  • $contextย (WP_Block_Template|array) โ€“ The block template, template part, or pattern the anchor block belongs to.

Below are a few examples using the Like button block plugin (ockham/like-button) built to demonstrate Block Hooks functionality in a third-party block. The pattern example does require the Twenty Twenty-Four theme.

function example_block_hooks( $hooked_blocks, $position, $anchor_block, $context ) {

	// Template/Template Part hooks.
	if ( $context instanceof WP_Block_Template ) {
		
		// Hooks the "Like" button block before the Post Title in the Single template.
		if ( 
			'core/post-title' === $anchor_block &&
			'before' === $position &&
			'single' === $context->slug
		) {
			$hooked_blocks[] = 'ockham/like-button';
		}

		// Hooks the Login/Logout link block after the Navigation block if the context of the template part is a header.
		if ( 
			'core/group' === $anchor_block &&
			'last_child' === $position &&
			'header' === $context->area
		) {
			$hooked_blocks[] = 'core/loginout';
		}
	}

	// Pattern hooks.
	if ( is_array( $context ) && isset( $context['slug'] ) ) {
		
		// Hooks into the Post Meta pattern in the Twenty Twenty-Four theme.
		if ( 
			'core/post-terms' === $anchor_block && 
			'after' === $position && 
			'twentytwentyfour/post-meta' === $context['slug']
		) {
			$hooked_blocks[] = 'ockham/like-button';
		}
	}

	return $hooked_blocks;
}
add_filter( 'hooked_block_types', 'example_block_hooks', 10, 4 );

Itโ€™s important to note thatย $contextย will be anย objectย of typeย WP_Block_Templateย for templates and template parts and anย arrayย for patterns. If you want to insert blocks conditionally using this parameter, make sure to check the parameter type before applying hooking blocks.

You will also note that you can only specify the name of the block that is being hooked. There is no way to set the attributes of the hooked block, so only the default instance of the block is inserted. Future improvements to Block Hooks will likely account for this limitation and others, providing a robust way for developers to extend Block Themes.

For more information on what additional features are currently being worked on, stay tuned to the tracking issue for Block Hook improvements.

Props to @bernhard-reiter, @gziolo, @webcommsat, and @bph for reviews.

#6-4, #dev-notes, #dev-notes-6-4