Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display Block Information by matching block variations #27469

Merged
merged 32 commits into from
Dec 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
69be2ab
getBlockTypeWithVariationInfo selector, BlockDescription component an…
ntsekouras Dec 4, 2020
20eeea3
revert BlockCard component and make the passed attributes top level w…
ntsekouras Dec 10, 2020
1647ae0
remove BlockDescription
ntsekouras Dec 10, 2020
4d5b176
change InserterPreviewPanel to use BlockCard with passing top level p…
ntsekouras Dec 10, 2020
23d0f61
create new custom hook for block's display information
ntsekouras Dec 10, 2020
93013a8
use new hook in BlockInspector
ntsekouras Dec 10, 2020
5fab0e5
revert BlockIcon and augment BlockTitle
ntsekouras Dec 10, 2020
42271d8
Navigation List View update
ntsekouras Dec 10, 2020
c94f11c
remove previous selector
ntsekouras Dec 10, 2020
9926c72
refactor BlockSwitcher to function component and use the new hook
ntsekouras Dec 10, 2020
ae9f53a
change hook
ntsekouras Dec 10, 2020
1697329
use CreateSelector and declare WPBlockDisplayInformation typedef
ntsekouras Dec 11, 2020
0784acf
revert BlockSwitcher to handle in separate PR
ntsekouras Dec 15, 2020
88fd610
remove getBlockDisplayInformation selector
ntsekouras Dec 15, 2020
6b8169b
add `isActive` API for block variations to use for trying to find a m…
ntsekouras Dec 15, 2020
ec4aa29
doc for `isActive` in block variation
ntsekouras Dec 15, 2020
4b261bb
jsdoc fix
ntsekouras Dec 15, 2020
37949ca
address review feedback part 1
ntsekouras Dec 16, 2020
2f6598e
fix BlockTitle tests
ntsekouras Dec 16, 2020
a8a8302
rename hook to `useBlockDisplayInformation`
ntsekouras Dec 16, 2020
9675f07
fix export
ntsekouras Dec 16, 2020
113f761
useBlockDisplayInformation README
ntsekouras Dec 16, 2020
0f720b6
move login in useSelect
ntsekouras Dec 17, 2020
410fc74
e2e tests
ntsekouras Dec 17, 2020
8501b34
blockTitle extra safeguard that existed before
ntsekouras Dec 17, 2020
1763959
Update docs
ntsekouras Dec 23, 2020
65a8910
Update docs
ntsekouras Dec 23, 2020
9ec01e6
Update docs
ntsekouras Dec 23, 2020
9ec1bee
Update docs
ntsekouras Dec 23, 2020
89c480c
rewordings
ntsekouras Dec 23, 2020
438831a
remove experimental status
ntsekouras Dec 23, 2020
bef032b
small refactoring
ntsekouras Dec 23, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ example: {

#### variations (optional)

- **Type:** `Object[]`
- **Type:** `Object[]`

Similarly to how the block's style variations can be declared, a block type can define block variations that the user can pick from. The difference is that, rather than changing only the visual appearance, this field provides a way to apply initial custom attributes and inner blocks at the time when a block is inserted.

Expand Down Expand Up @@ -256,19 +256,20 @@ variations: [

An object describing a variation defined for the block type can contain the following 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 `WPBlockVariationScope[]`) - the list of scopes where the variation is applicable. When not provided, it defaults to `block` and `inserter`. Available options:
- `inserter` - Block Variation is shown on the inserter.
- `block` - Used by blocks to filter specific block variations. Mostly used in Placeholder patterns like `Columns` block.
- `transform` - Block Variation will be shown in the component for Block Variations transformations.
- `keywords` (optional, type `string[]`) - An array of terms (which can be translated) that help users discover the variation while searching.
- `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 `WPBlockVariationScope[]`) - the list of scopes where the variation is applicable. When not provided, it defaults to `block` and `inserter`. Available options:
- `inserter` - Block Variation is shown on the inserter.
- `block` - Used by blocks to filter specific block variations. Mostly used in Placeholder patterns like `Columns` block.
- `transform` - Block Variation will be shown in the component for Block Variations transformations.
- `keywords` (optional, type `string[]`) - An array of terms (which can be translated) that help users discover the variation while searching.
- `isActive` (optional, type `Function`) - A function that accepts a block's attributes and the variation's attributes and determines if a variation is active. This function doesn't try to find a match dynamically based on all block's attributes, as in many cases some attributes are irrelevant. An example would be for `embed` block where we only care about `providerNameSlug` attribute's value.

It's also possible to override the default block style variation using the `className` attribute when defining block variations.

Expand All @@ -278,15 +279,17 @@ variations: [
name: 'blue',
title: __( 'Blue Quote' ),
isDefault: true,
attributes: { className: 'is-style-blue-quote' },
attributes: { color: 'blue', className: 'is-style-blue-quote' },
icon: 'format-quote',
isActive: ( blockAttributes, variationAttributes ) =>
blockAttributes.color === variationAttributes.color
},
],
```

#### supports (optional)

- ***Type:*** `Object`
- **_Type:_** `Object`

Supports contains as set of options to control features used in the editor. See the [the supports documentation](/docs/designers-developers/developers/block-api/block-supports.md) for more details.

Expand Down
24 changes: 22 additions & 2 deletions packages/block-editor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ import {
BlockEditorProvider,
BlockList,
WritingFlow,
ObserveTyping
ObserveTyping,
} from '@wordpress/block-editor';
import { SlotFillProvider, Popover } from '@wordpress/components';
import { useState } from '@wordpress/element';

function MyEditorComponent () {
function MyEditorComponent() {
const [ blocks, updateBlocks ] = useState( [] );

return (
Expand Down Expand Up @@ -569,6 +569,26 @@ _Related_

- <https://github.com/WordPress/gutenberg/blob/master/packages/block-editor/src/components/url-popover/README.md>

<a name="useBlockDisplayInformation" href="#useBlockDisplayInformation">#</a> **useBlockDisplayInformation**

Hook used to try to find a matching block variation and return
the appropriate information for display reasons. In order to
to try to find a match we need to things:
1\. Block's client id to extract it's current attributes.
2\. A block variation should have set `isActive` prop to a proper function.

If for any reason a block variaton match cannot be found,
the returned information come from the Block Type.
If no blockType is found with the provided clientId, returns null.

_Parameters_

- _clientId_ `string`: Block's client id.

_Returns_

- `?WPBlockDisplayInformation`: Block's display information, or `null` when the block or its type not found.

<a name="useBlockEditContext" href="#useBlockEditContext">#</a> **useBlockEditContext**

Undocumented declaration.
Expand Down
13 changes: 12 additions & 1 deletion packages/block-editor/src/components/block-card/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
/**
* WordPress dependencies
*/
import deprecated from '@wordpress/deprecated';

/**
* Internal dependencies
*/
import BlockIcon from '../block-icon';

function BlockCard( { blockType: { icon, title, description } } ) {
function BlockCard( { title, icon, description, blockType } ) {
if ( blockType ) {
deprecated( '`blockType` property in `BlockCard component`', {
alternative: '`title, icon and description` properties',
} );
( { title, icon, description } = blockType );
}
return (
<div className="block-editor-block-card">
<BlockIcon icon={ icon } showColors />
Expand Down
30 changes: 23 additions & 7 deletions packages/block-editor/src/components/block-inspector/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import BlockStyles from '../block-styles';
import MultiSelectionInspector from '../multi-selection-inspector';
import DefaultStylePicker from '../default-style-picker';
import BlockVariationTransforms from '../block-variation-transforms';
import useBlockDisplayInformation from '../use-block-display-information';

const BlockInspector = ( {
blockType,
count,
Expand Down Expand Up @@ -64,22 +66,36 @@ const BlockInspector = ( {
}
return null;
}
return (
<BlockInspectorSingleBlock
clientId={ selectedBlockClientId }
blockName={ blockType.name }
hasBlockStyles={ hasBlockStyles }
bubblesVirtually={ bubblesVirtually }
/>
);
};

const BlockInspectorSingleBlock = ( {
clientId,
blockName,
hasBlockStyles,
bubblesVirtually,
} ) => {
const blockInformation = useBlockDisplayInformation( clientId );
return (
<div className="block-editor-block-inspector">
<BlockCard blockType={ blockType } />
<BlockVariationTransforms blockClientId={ selectedBlockClientId } />
<BlockCard { ...blockInformation } />
<BlockVariationTransforms blockClientId={ clientId } />
{ hasBlockStyles && (
<div>
<PanelBody title={ __( 'Styles' ) }>
<BlockStyles clientId={ selectedBlockClientId } />
<BlockStyles clientId={ clientId } />
{ hasBlockSupport(
blockType.name,
blockName,
'defaultStylePicker',
true
) && (
<DefaultStylePicker blockName={ blockType.name } />
) }
) && <DefaultStylePicker blockName={ blockName } /> }
</PanelBody>
</div>
) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ import { __ } from '@wordpress/i18n';
* Internal dependencies
*/
import BlockIcon from '../block-icon';
import useBlockDisplayInformation from '../use-block-display-information';
import { getBlockPositionDescription } from './utils';

function BlockNavigationBlockSelectButton(
{
className,
block,
block: { clientId, name, attributes },
isSelected,
onClick,
position,
Expand All @@ -38,12 +39,15 @@ function BlockNavigationBlockSelectButton(
},
ref
) {
const { name, attributes } = block;

const blockType = getBlockType( name );
const blockDisplayName = getBlockLabel( blockType, attributes );
const blockInformation = useBlockDisplayInformation( clientId );
const instanceId = useInstanceId( BlockNavigationBlockSelectButton );
const descriptionId = `block-navigation-block-select-button__${ instanceId }`;
const blockType = getBlockType( name );
const blockLabel = getBlockLabel( blockType, attributes );
// If label is defined we prioritize it over possible possible
// block variation match title.
const blockDisplayName =
blockLabel !== blockType.title ? blockLabel : blockInformation?.title;
const blockPositionDescription = getBlockPositionDescription(
position,
siblingBlockCount,
Expand All @@ -66,7 +70,7 @@ function BlockNavigationBlockSelectButton(
onDragEnd={ onDragEnd }
draggable={ draggable }
>
<BlockIcon icon={ blockType.icon } showColors />
<BlockIcon icon={ blockInformation.icon } showColors />
{ blockDisplayName }
{ isSelected && (
<VisuallyHidden>
Expand Down
27 changes: 13 additions & 14 deletions packages/block-editor/src/components/block-title/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ import {
__experimentalGetBlockLabel as getBlockLabel,
} from '@wordpress/blocks';

/**
* Internal dependencies
*/
import useBlockDisplayInformation from '../use-block-display-information';

/**
* Renders the block's configured title as a string, or empty if the title
* cannot be determined.
Expand Down Expand Up @@ -44,22 +49,16 @@ export default function BlockTitle( { clientId } ) {
[ clientId ]
);

if ( ! name ) {
return null;
}

const blockInformation = useBlockDisplayInformation( clientId );
if ( ! name || ! blockInformation ) return null;
const blockType = getBlockType( name );
if ( ! blockType ) {
return null;
}

const { title } = blockType;
const label = getBlockLabel( blockType, attributes );

// Label will often fall back to the title if no label is defined for the
// Label will fallback to the title if no label is defined for the
// current label context. We do not want "Paragraph: Paragraph".
if ( label !== title ) {
return `${ title }: ${ truncate( label, { length: 15 } ) }`;
// If label is defined we prioritize it over possible possible
// block variation match title.
if ( label !== blockType.title ) {
return `${ blockType.title }: ${ truncate( label, { length: 15 } ) }`;
gziolo marked this conversation as resolved.
Show resolved Hide resolved
}
return title;
return blockInformation.title;
}
19 changes: 12 additions & 7 deletions packages/block-editor/src/components/block-title/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ jest.mock( '@wordpress/blocks', () => {
};
} );

jest.mock( '../../use-block-display-information', () => {
const resultsMap = {
'id-name-exists': { title: 'Block Title' },
'id-name-with-label': { title: 'Block With Label' },
'id-name-with-long-label': { title: 'Block With Long Label' },
};
return jest.fn( ( clientId ) => resultsMap[ clientId ] );
} );

jest.mock( '@wordpress/data/src/components/use-select', () => {
// This allows us to tweak the returned value on each test
const mock = jest.fn();
Expand Down Expand Up @@ -81,9 +90,7 @@ describe( 'BlockTitle', () => {
attributes: null,
} ) );

const wrapper = shallow(
<BlockTitle clientId="afd1cb17-2c08-4e7a-91be-007ba7ddc3a1" />
);
const wrapper = shallow( <BlockTitle clientId="id-name-exists" /> );

expect( wrapper.text() ).toBe( 'Block Title' );
} );
Expand All @@ -94,9 +101,7 @@ describe( 'BlockTitle', () => {
attributes: null,
} ) );

const wrapper = shallow(
<BlockTitle clientId="afd1cb17-2c08-4e7a-91be-007ba7ddc3a1" />
);
const wrapper = shallow( <BlockTitle clientId="id-name-with-label" /> );

expect( wrapper.text() ).toBe( 'Block With Label: Test Label' );
} );
Expand All @@ -108,7 +113,7 @@ describe( 'BlockTitle', () => {
} ) );

const wrapper = shallow(
<BlockTitle clientId="afd1cb17-2c08-4e7a-91be-007ba7ddc3a1" />
<BlockTitle clientId="id-name-with-long-label" />
);

expect( wrapper.text() ).toBe(
Expand Down
1 change: 1 addition & 0 deletions packages/block-editor/src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ export {
export { default as Warning } from './warning';
export { default as WritingFlow } from './writing-flow';
export { useCanvasClickRedirect as __unstableUseCanvasClickRedirect } from './use-canvas-click-redirect';
export { default as useBlockDisplayInformation } from './use-block-display-information';

/*
* State Related Components
Expand Down
21 changes: 13 additions & 8 deletions packages/block-editor/src/components/inserter/preview-panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ import BlockCard from '../block-card';
import BlockPreview from '../block-preview';

function InserterPreviewPanel( { item } ) {
const hoveredItemBlockType = getBlockType( item.name );
const { name, title, icon, description, initialAttributes } = item;
const hoveredItemBlockType = getBlockType( name );
const isReusable = isReusableBlock( item );
return (
<div className="block-editor-inserter__preview-container">
<div className="block-editor-inserter__preview">
{ isReusableBlock( item ) || hoveredItemBlockType.example ? (
{ isReusable || hoveredItemBlockType.example ? (
<div className="block-editor-inserter__preview-content">
<BlockPreview
__experimentalPadding={ 16 }
Expand All @@ -34,16 +36,13 @@ function InserterPreviewPanel( { item } ) {
attributes: {
...hoveredItemBlockType.example
.attributes,
...item.initialAttributes,
...initialAttributes,
},
innerBlocks:
hoveredItemBlockType.example
.innerBlocks,
} )
: createBlock(
item.name,
item.initialAttributes
)
: createBlock( name, initialAttributes )
}
/>
</div>
Expand All @@ -53,7 +52,13 @@ function InserterPreviewPanel( { item } ) {
</div>
) }
</div>
{ ! isReusableBlock( item ) && <BlockCard blockType={ item } /> }
{ ! isReusable && (
<BlockCard
title={ title }
icon={ icon }
description={ description }
/>
) }
</div>
);
}
Expand Down
Loading