Skip to content

Commit

Permalink
prep build 6/10
Browse files Browse the repository at this point in the history
  • Loading branch information
bph committed Jun 10, 2024
2 parents 827c674 + b8fca79 commit 383ce4e
Show file tree
Hide file tree
Showing 24 changed files with 270 additions and 123 deletions.
2 changes: 1 addition & 1 deletion docs/contributors/folder-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ The following snippet explains how the Gutenberg repository is structured omitti
│ Set of documentation pages composing the [Block editor handbook](https://developer.wordpress.org/block-editor/).
├── platform-docs
│ Documentation website targetted to non WordPress developpers
│ Documentation website targeted to non WordPress developers
│ using Gutenberg in their own applications.
│ Deployed on [https://wordpress.org/gutenberg-framework/](https://wordpress.org/gutenberg-framework/).
Expand Down
87 changes: 38 additions & 49 deletions docs/reference-guides/block-api/block-variations.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
# Variations

The Block Variations API allows you to define multiple versions (variations) of a block. A block variation differs from the original block by a set of initial attributes or inner blocks. When you insert the block variation into the Editor, these attributes and/or inner blocks are applied.
The Block Variations API allows you to define multiple versions (variations) of a block. A block variation differs from the original block by a set of initial attributes or inner blocks. When you insert the block variation into the Editor, these attributes and/or inner blocks are applied.

Variations are an excellent way to create iterations of existing blocks without building entirely new blocks from scratch.

To better understand this API, consider the Embed block. This block contains numerous variations for each type of embeddable content (WordPress, Youtube, etc.). Each Embed block variation shares the same underlying functionality for editing, saving, and so on. Besides the name and descriptive information, the main difference is the `providerNameSlug` attribute. Below is a simplified example of the variations in the Embed block. View the [source code](https://github.com/WordPress/gutenberg/blob/trunk/packages/block-library/src/embed/variations.js) for the complete specification.


```js
variations: [
{
Expand Down Expand Up @@ -38,7 +37,7 @@ A block variation is defined by an object that can contain the following fields:
- `innerBlocks` (optional, type `Array[]`) – Initial configuration of nested blocks.
- `example` (optional, type `Object`) – Provides structured data for the block preview. Set to `undefined` to disable the preview. See the [Block Registration API](/docs/reference-guides/block-api/block-registration.md#example-optional) for more details.
- `scope` (optional, type `WPBlockVariationScope[]`) - Defaults to `block` and `inserter`. The list of scopes where the variation is applicable. Available options include:
- `block` - Used by blocks to filter specific block variations. `Columns` and `Query` blocks have such variations, which are passed to the [experimental BlockVariationPicker](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/block-variation-picker/README.md) component. This component handles displaying the variations and allows users to choose one of them.
- `block` - Used by blocks to filter specific block variations. `Columns` and `Query` blocks have such variations, which are passed to the [experimental BlockVariationPicker](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/block-variation-picker/README.md) component. This component handles displaying the variations and allows users to choose one of them.
- `inserter` - Block variation is shown on the inserter.
- `transform` - Block variation is shown in the component for variation transformations.
- `isDefault` (optional, type `boolean`) – Defaults to `false`. Indicates whether the current variation is the default one (details below).
Expand All @@ -55,13 +54,10 @@ Block variations can be declared during a block's registration by providing the
To create a variation for an existing block, such as a Core block, use `wp.blocks.registerBlockVariation()`. This function accepts the name of the block and the object defining the variation.

```js
wp.blocks.registerBlockVariation(
'core/embed',
{
name: 'custom-embed',
attributes: { providerNameSlug: 'custom' },
}
);
wp.blocks.registerBlockVariation( 'core/embed', {
name: 'custom-embed',
attributes: { providerNameSlug: 'custom' },
} );
```

## Removing a block variation
Expand Down Expand Up @@ -102,17 +98,14 @@ By default, all variations will show up in the Inserter in addition to the origi
For example, if you want Media & Text block to display the image on the right by default, you could create a variation like this:

```js
wp.blocks.registerBlockVariation(
'core/media-text',
{
name: 'media-text-media-right',
title: __( 'Media & Text' ),
isDefault: true,
attributes: {
mediaPosition: 'right'
}
}
)
wp.blocks.registerBlockVariation( 'core/media-text', {
name: 'media-text-media-right',
title: __( 'Media & Text' ),
isDefault: true,
attributes: {
mediaPosition: 'right',
},
} );
```

### Caveats to using `isDefault`
Expand Down Expand Up @@ -159,21 +152,21 @@ const variations = [
attributes: { providerNameSlug: 'youtube', responsive: true },
},
// ...
]
];
```

The `isActive` property would then look like this:

```js
isActive: [ 'providerNameSlug' ]
isActive: [ 'providerNameSlug' ];
```

This will cause the block instance value for `providerNameSlug` to be compared to the value declared in the variation's declaration (the values in the code snippet above) to determine which embed variation is active.

Nested object paths are also supported. For example, consider a block variation that has a `query` object as an attribute. It is possible to determine if the variation is active solely based on that object's `postType` property (while ignoring all its other properties):
Nested object paths are also supported since WordPress `6.6.0`. For example, consider a block variation that has a `query` object as an attribute. It is possible to determine if the variation is active solely based on that object's `postType` property (while ignoring all its other properties):

```js
isActive: [ 'query.postType' ]
isActive: [ 'query.postType' ];
```

The function version of this property accepts a block instance's `blockAttributes` as the first argument, and the `variationAttributes` declared for a variation as the second argument. These arguments can be used to determine if a variation is active by comparing them and returning a `true` or `false` (indicating whether this variation is inactive for this block instance).
Expand All @@ -187,33 +180,29 @@ isActive: ( blockAttributes, variationAttributes ) =>

### Specificity of `isActive` matches

_Note: Improved handling since WordPress `6.6.0`._

If there are multiple variations whose `isActive` check matches a given block instance, and all of them are string arrays, then the variation with the highest _specificity_ will be chosen. Consider the following example:

```js
wp.blocks.registerBlockVariation(
'core/paragraph',
{
name: 'paragraph-red',
title: 'Red Paragraph',
attributes: {
textColor: 'vivid-red',
},
isActive: [ 'textColor' ],
}
);

wp.blocks.registerBlockVariation(
'core/paragraph',
{
name: 'paragraph-red-grey',
title: 'Red/Grey Paragraph',
attributes: {
textColor: 'vivid-red',
backgroundColor: 'cyan-bluish-gray'
},
isActive: [ 'textColor', 'backgroundColor' ]
}
);
wp.blocks.registerBlockVariation( 'core/paragraph', {
name: 'paragraph-red',
title: 'Red Paragraph',
attributes: {
textColor: 'vivid-red',
},
isActive: [ 'textColor' ],
} );

wp.blocks.registerBlockVariation( 'core/paragraph', {
name: 'paragraph-red-grey',
title: 'Red/Grey Paragraph',
attributes: {
textColor: 'vivid-red',
backgroundColor: 'cyan-bluish-gray',
},
isActive: [ 'textColor', 'backgroundColor' ],
} );
```

If a block instance has attributes `textColor: vivid-red` and `backgroundColor: cyan-bluish-gray`, both variations' `isActive` criterion will match that block instance. In this case, the more _specific_ match will be determined to be the active variation, where specificity is calculated as the length of each `isActive` array. This means that the `Red/Grey Paragraph` will be shown as the active variation.
Expand Down
2 changes: 1 addition & 1 deletion docs/reference-guides/slotfills/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ See [core code](https://github.com/WordPress/gutenberg/tree/HEAD/packages/editor
```js
export default function PostSummary( { onActionPerformed } ) {
const { isRemovedPostStatusPanel } = useSelect( ( select ) => {
// We use isEditorPanelRemoved to hide the panel if it was programatically removed. We do
// We use isEditorPanelRemoved to hide the panel if it was programmatically removed. We do
// not use isEditorPanelEnabled since this panel should not be disabled through the UI.
const { isEditorPanelRemoved, getCurrentPostType } =
select( editorStore );
Expand Down
1 change: 1 addition & 0 deletions lib/blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ function gutenberg_reregister_core_block_types() {
'archives.php' => 'core/archives',
'avatar.php' => 'core/avatar',
'block.php' => 'core/block',
'button.php' => 'core/button',
'calendar.php' => 'core/calendar',
'categories.php' => 'core/categories',
'cover.php' => 'core/cover',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
font-size: $helptext-font-size;

svg {
fill: $gray-400 !important;
fill: $gray-600 !important;
}

.components-button {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ export function useSettingsForBlockElement(
'fontStyle',
'fontWeight',
'letterSpacing',
'textAlign',
'textTransform',
'textDecoration',
'writingMode',
Expand Down
80 changes: 80 additions & 0 deletions packages/block-library/src/button/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php
/**
* Server-side rendering of the `core/button` block.
*
* @package WordPress
*/

/**
* Renders the `core/button` block on the server,
*
* @since 6.6.0
*
* @param array $attributes The block attributes.
* @param string $content The block content.
* @param WP_Block $block The block object.
*
* @return string The block content.
*/
function render_block_core_button( $attributes, $content ) {
$p = new WP_HTML_Tag_Processor( $content );

/*
* The button block can render an `<a>` or `<button>` and also has a
* `<div>` wrapper. Find the a or button tag.
*/
$tag = null;
while ( $p->next_tag() ) {
$tag = $p->get_tag();
if ( 'A' === $tag || 'BUTTON' === $tag ) {
break;
}
}

/*
* If this happens, the likelihood is there's no block content,
* or the block has been modified by a plugin.
*/
if ( null === $tag ) {
return $content;
}

// If the next token is the closing tag, the button is empty.
$is_empty = true;
while ( $p->next_token() && $tag !== $p->get_token_name() && $is_empty ) {
if ( '#comment' !== $p->get_token_type() ) {
/**
* Anything else implies this is not empty.
* This might include any text content (including a space),
* inline images or other HTML.
*/
$is_empty = false;
}
}

/*
* When there's no text, render nothing for the block.
* See https://github.com/WordPress/gutenberg/issues/17221 for the
* reasoning behind this.
*/
if ( $is_empty ) {
return '';
}

return $content;
}

/**
* Registers the `core/button` block on server.
*
* @since 6.6.0
*/
function register_block_core_button() {
register_block_type_from_metadata(
__DIR__ . '/button',
array(
'render_callback' => 'render_block_core_button',
)
);
}
add_action( 'init', 'register_block_core_button' );
4 changes: 0 additions & 4 deletions packages/block-library/src/button/save.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,6 @@ export default function save( { attributes, className } ) {
width,
} = attributes;

if ( RichText.isEmpty( text ) ) {
return null;
}

const TagName = tagName || 'a';
const isButtonTag = 'button' === TagName;
const buttonType = type || 'button';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,69 @@

exports[`Buttons block color customization sets a background color 1`] = `
"<!-- wp:buttons -->
<div class="wp-block-buttons"><!-- wp:button {"backgroundColor":"luminous-vivid-amber"} /--></div>
<div class="wp-block-buttons"><!-- wp:button {"backgroundColor":"luminous-vivid-amber"} -->
<div class="wp-block-button"><a class="wp-block-button__link has-luminous-vivid-amber-background-color has-background wp-element-button" href=""></a></div>
<!-- /wp:button --></div>
<!-- /wp:buttons -->"
`;

exports[`Buttons block color customization sets a custom gradient background color 1`] = `
"<!-- wp:buttons -->
<div class="wp-block-buttons"><!-- wp:button {"style":{"color":{"gradient":"linear-gradient(200deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%)"}}} /--></div>
<div class="wp-block-buttons"><!-- wp:button {"style":{"color":{"gradient":"linear-gradient(200deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%)"}}} -->
<div class="wp-block-button"><a class="wp-block-button__link has-background wp-element-button" href="" style="background:linear-gradient(200deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%)"></a></div>
<!-- /wp:button --></div>
<!-- /wp:buttons -->"
`;

exports[`Buttons block color customization sets a gradient background color 1`] = `
"<!-- wp:buttons -->
<div class="wp-block-buttons"><!-- wp:button {"gradient":"light-green-cyan-to-vivid-green-cyan"} /--></div>
<div class="wp-block-buttons"><!-- wp:button {"gradient":"light-green-cyan-to-vivid-green-cyan"} -->
<div class="wp-block-button"><a class="wp-block-button__link has-light-green-cyan-to-vivid-green-cyan-gradient-background has-background wp-element-button" href=""></a></div>
<!-- /wp:button --></div>
<!-- /wp:buttons -->"
`;

exports[`Buttons block color customization sets a text color 1`] = `
"<!-- wp:buttons -->
<div class="wp-block-buttons"><!-- wp:button {"textColor":"pale-pink"} /--></div>
<div class="wp-block-buttons"><!-- wp:button {"textColor":"pale-pink"} -->
<div class="wp-block-button"><a class="wp-block-button__link has-pale-pink-color has-text-color wp-element-button" href=""></a></div>
<!-- /wp:button --></div>
<!-- /wp:buttons -->"
`;

exports[`Buttons block justify content sets Justify items center option 1`] = `
"<!-- wp:buttons {"layout":{"type":"flex","justifyContent":"center"}} -->
<div class="wp-block-buttons"><!-- wp:button /--></div>
<div class="wp-block-buttons"><!-- wp:button -->
<div class="wp-block-button"><a class="wp-block-button__link wp-element-button"></a></div>
<!-- /wp:button --></div>
<!-- /wp:buttons -->"
`;

exports[`Buttons block justify content sets Justify items left option 1`] = `
"<!-- wp:buttons {"layout":{"type":"flex","justifyContent":"left"}} -->
<div class="wp-block-buttons"><!-- wp:button /--></div>
<div class="wp-block-buttons"><!-- wp:button -->
<div class="wp-block-button"><a class="wp-block-button__link wp-element-button"></a></div>
<!-- /wp:button --></div>
<!-- /wp:buttons -->"
`;

exports[`Buttons block justify content sets Justify items right option 1`] = `
"<!-- wp:buttons {"layout":{"type":"flex","justifyContent":"right"}} -->
<div class="wp-block-buttons"><!-- wp:button /--></div>
<div class="wp-block-buttons"><!-- wp:button -->
<div class="wp-block-button"><a class="wp-block-button__link wp-element-button"></a></div>
<!-- /wp:button --></div>
<!-- /wp:buttons -->"
`;

exports[`Buttons block when a button is shown adds another button using the inline appender 1`] = `
"<!-- wp:buttons -->
<div class="wp-block-buttons"><!-- wp:button /-->
<div class="wp-block-buttons"><!-- wp:button -->
<div class="wp-block-button"><a class="wp-block-button__link wp-element-button" href=""></a></div>
<!-- /wp:button -->
<!-- wp:button /--></div>
<!-- wp:button -->
<div class="wp-block-button"><a class="wp-block-button__link wp-element-button" href=""></a></div>
<!-- /wp:button --></div>
<!-- /wp:buttons -->
<!-- wp:paragraph -->
Expand All @@ -56,7 +74,9 @@ exports[`Buttons block when a button is shown adds another button using the inli

exports[`Buttons block when a button is shown adds another button using the inserter 1`] = `
"<!-- wp:buttons -->
<div class="wp-block-buttons"><!-- wp:button /-->
<div class="wp-block-buttons"><!-- wp:button -->
<div class="wp-block-button"><a class="wp-block-button__link wp-element-button" href=""></a></div>
<!-- /wp:button -->
<!-- wp:button -->
<div class="wp-block-button"><a class="wp-block-button__link wp-element-button">Hello!</a></div>
Expand Down
11 changes: 6 additions & 5 deletions packages/block-library/src/buttons/test/edit.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ import { getBlockTypes, unregisterBlockType } from '@wordpress/blocks';
import { registerCoreBlocks } from '@wordpress/block-library';

const BUTTONS_HTML = `<!-- wp:buttons -->
<div class="wp-block-buttons"><!-- wp:button /--></div>
<div class="wp-block-buttons"><!-- wp:button -->
<div class="wp-block-button"><a class="wp-block-button__link wp-element-button"></a></div>
<!-- /wp:button --></div>
<!-- /wp:buttons -->`;

beforeAll( () => {
Expand Down Expand Up @@ -248,10 +250,9 @@ describe( 'Buttons block', () => {
'Justify items right',
].forEach( ( justificationOption ) =>
it( `sets ${ justificationOption } option`, async () => {
const initialHtml = `<!-- wp:buttons -->
<div class="wp-block-buttons"><!-- wp:button /--></div>
<!-- /wp:buttons -->`;
const screen = await initializeEditor( { initialHtml } );
const screen = await initializeEditor( {
initialHtml: BUTTONS_HTML,
} );

const [ block ] = await screen.findAllByLabelText(
/Buttons Block\. Row 1/
Expand Down
Loading

0 comments on commit 383ce4e

Please sign in to comment.