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

Block Editor: Tips feature #22109

Closed
wants to merge 19 commits into from
Closed

Conversation

retrofox
Copy link
Contributor

@retrofox retrofox commented May 5, 2020

Description

This PR tries to tackle how to deal with Tips in a comprehensive way, using the store in order to decentralize access to the API. The goals to achieve are:

  • Register Tips globally through the actions.
  • Pick up tips from different points of the app, being as specific as possible in order to get the proper ones to show.

Related issues:

API

Actions and selectors are prefixed with __experimental. All data is stored in the core/block-editor subtree, under the tips key.

Register Tips (Actions)

__experimentalRegisterBlockTip( scope, description )

When registers a tip we need to define its scope and description as a minimum. The simpler case is when we register a Tip for a block type. For instance...

import { dispatch } from '@wordpress/data';

// Register Tip.
const { __experimentalRegisterBlockTip } = dispatch( 'core/block-editor' );

// Register a core/video tip
__experimentalRegisterBlockTip(
	'core/video',
	__( 'The video block accepts uploads in the MP4, M4V, WebM, OGV, WMV, and FLV formats.' )
);

It will populate the store where, in this case, the scope is the block type. We can store more than one tip per scope. For instance, adding three tips to core/image block:

import { dispatch } from '@wordpress/data';

// Register Tips.
const { __experimentalRegisterBlockTip } = dispatch( 'core/block-editor' );
const tips = [
	__( 'Add alternative text to your images to make them more accessible.' ),
	__( 'Use a Cover block to add text on top of your image.' ),
	__( 'To place two images side by side, convert them to a Gallery.' ),
];

tips.forEach( ( desc ) => __experimentalRegisterBlockTip('core/image', desc ) );

__experimentalRegisterBlockInserterTip( context, keywords, description )

It registers Tips related to the Block Inserter. In #20196, we'd like to show some contextual tips when the user types specific words, such as CSS, header, theme, etc. In this case, the scope is a constant value: blockInserter. And also, we can define a set of keywords that will be used to pick up the tip. For instance, we do something like the following:

import { dispatch } from '@wordpress/data';

__experimentalRegisterBlockInserterTip(
	'CSS',
	[ 'css', 'style' ],
	__( 'CSS - You can visit the the Customizer to edit the CSS on your site.' )
);

Get Tips (Selectors)

__experimentalGetBlockInserterTipByContext( state, type, random );

Use this selector when you'd like to get all tips about a specific block type:

import { select } from '@wordpress/data';

// ...
const { __experimentalGetBlockTipsByType } = select( 'core/block-editor' );

// get tips
const blockTypeTips = __experimentalGetBlockTipsByType( 'core/image', true );

It will return the tip description, or null if there isn't any tip registered for the block type. Also, if there is more than one tip, and the random parameter is true, it will return one of those tips randomly. if random is false, it will return the first tip from the tips list.

__experimentalGetBlockInserterTipsByContext( state, searchTerm, random )

Use this selector to get block inserter contextual tips. It will return a tip according to the given search term. It also supports the random mode whether there is more than one tip for the search term:

import { select } from '@wordpress/data';

// ...
const { __experimentalGetBlockInserterTipsByContext } = select( 'core/block-editor' );

// get tips
const contextualTip = __experimentalGetBlockInserterTipsByContext( 'css', true );

Adding tips to the interface

Block Inserter

This PR registers five tips to the block inserter component, in tips.js file of the edit-post package. The following is one item of the tips array:

[
		'css',
		[ 'css', __( 'css' ), 'style', __( 'style' ) ],
		createInterpolateElement(
			__(
				'CSS - You can visit the <a>the Customizer</a> to edit the CSS on your site.'
			),
			{
				a: <a href="/customize.php?autofocus[section]=custom_css" target="_blank"/>
			}
		),
	],

The first element is the context used to register the tip. The second one defines the tip keywords, used to compare and show it where/when it's appropriated. And the third one is the Tip description. It worths noticing that it could be a component. In this case, we'd like to translate the tip description.

These tips are registered in the constructor of the Editor class.

In another hand, the block inserter will try to pick the tip when the user types a search term in the searcher input box. If it matches, it will show one of the registered tips.

Screen Shot 2020-05-06 at 5 04 39 PM

This approach defines more than a keyword for the tip. in the case of the css, it will be shown with the style term as well:

Screen Shot 2020-05-06 at 5 05 29 PM

Finally, we are translating some keywords in order to make it work in other languages. For instance, in the following screenshot I typed cabecera which is the translation of header to Spanish:

Screen Shot 2020-05-06 at 5 08 35 PM

Block Preview

This PR also shows a tip in the block preview of the block inserter whether the block type has some tips registered. In this PR we've registered three tips for the core/image block, and one for the core/video block, picked from this list.

Screen Shot 2020-05-06 at 5 10 49 PM

Since core/image has three tips registered and the selector pass random as true, it will change the tip every time that the preview is re-rendered:

Screen Shot 2020-05-06 at 5 11 21 PM

How has this been tested?

TBD

Checklist:

  • My code is tested.
  • My code follows the WordPress code style.
  • My code has proper inline documentation.
@retrofox
Copy link
Contributor Author

retrofox commented May 5, 2020

Totally related to #21080

@retrofox retrofox added the [Feature] Inserter The main way to insert blocks using the + button in the editing interface label May 5, 2020
@github-actions
Copy link

github-actions bot commented May 5, 2020

Size Change: +1.44 kB (0%)

Total Size: 823 kB

Filename Size Change
build/block-directory/index.js 6.61 kB +7 B (0%)
build/block-editor/index.js 102 kB +729 B (0%)
build/block-editor/style-rtl.css 10.2 kB +13 B (0%)
build/block-editor/style.css 10.2 kB +13 B (0%)
build/block-library/index.js 116 kB +237 B (0%)
build/blocks/index.js 48.1 kB +1 B
build/components/index.js 179 kB +79 B (0%)
build/components/style-rtl.css 16.9 kB +2 B (0%)
build/components/style.css 16.9 kB +1 B
build/core-data/index.js 11.4 kB +14 B (0%)
build/edit-post/index.js 28.5 kB +347 B (1%)
build/edit-site/index.js 12.3 kB -2 B (0%)
build/editor/editor-styles-rtl.css 425 B -3 B (0%)
build/editor/editor-styles.css 428 B -3 B (0%)
build/hooks/index.js 2.14 kB +7 B (0%)
build/media-utils/index.js 5.29 kB -1 B
build/rich-text/index.js 14.8 kB -2 B (0%)
ℹ️ View Unchanged
Filename Size Change
build/a11y/index.js 1.02 kB 0 B
build/annotations/index.js 3.62 kB 0 B
build/api-fetch/index.js 4.08 kB 0 B
build/autop/index.js 2.82 kB 0 B
build/blob/index.js 620 B 0 B
build/block-directory/style-rtl.css 760 B 0 B
build/block-directory/style.css 761 B 0 B
build/block-library/editor-rtl.css 7.08 kB 0 B
build/block-library/editor.css 7.08 kB 0 B
build/block-library/style-rtl.css 7.28 kB 0 B
build/block-library/style.css 7.29 kB 0 B
build/block-library/theme-rtl.css 683 B 0 B
build/block-library/theme.css 685 B 0 B
build/block-serialization-default-parser/index.js 1.88 kB 0 B
build/block-serialization-spec-parser/index.js 3.1 kB 0 B
build/compose/index.js 6.66 kB 0 B
build/data-controls/index.js 1.29 kB 0 B
build/data/index.js 8.44 kB 0 B
build/date/index.js 5.47 kB 0 B
build/deprecated/index.js 772 B 0 B
build/dom-ready/index.js 568 B 0 B
build/dom/index.js 3.1 kB 0 B
build/edit-navigation/index.js 4.07 kB 0 B
build/edit-navigation/style-rtl.css 485 B 0 B
build/edit-navigation/style.css 485 B 0 B
build/edit-post/style-rtl.css 12.2 kB 0 B
build/edit-post/style.css 12.2 kB 0 B
build/edit-site/style-rtl.css 5.19 kB 0 B
build/edit-site/style.css 5.2 kB 0 B
build/edit-widgets/index.js 8.37 kB 0 B
build/edit-widgets/style-rtl.css 4.68 kB 0 B
build/edit-widgets/style.css 4.68 kB 0 B
build/editor/index.js 44.3 kB 0 B
build/editor/style-rtl.css 5.07 kB 0 B
build/editor/style.css 5.08 kB 0 B
build/element/index.js 4.65 kB 0 B
build/escape-html/index.js 734 B 0 B
build/format-library/index.js 7.63 kB 0 B
build/format-library/style-rtl.css 502 B 0 B
build/format-library/style.css 502 B 0 B
build/html-entities/index.js 622 B 0 B
build/i18n/index.js 3.56 kB 0 B
build/is-shallow-equal/index.js 710 B 0 B
build/keyboard-shortcuts/index.js 2.51 kB 0 B
build/keycodes/index.js 1.94 kB 0 B
build/list-reusable-blocks/index.js 3.13 kB 0 B
build/list-reusable-blocks/style-rtl.css 226 B 0 B
build/list-reusable-blocks/style.css 226 B 0 B
build/notices/index.js 1.79 kB 0 B
build/nux/index.js 3.4 kB 0 B
build/nux/style-rtl.css 616 B 0 B
build/nux/style.css 613 B 0 B
build/plugins/index.js 2.56 kB 0 B
build/primitives/index.js 1.5 kB 0 B
build/priority-queue/index.js 789 B 0 B
build/redux-routine/index.js 2.85 kB 0 B
build/server-side-render/index.js 2.67 kB 0 B
build/shortcode/index.js 1.7 kB 0 B
build/token-list/index.js 1.28 kB 0 B
build/url/index.js 4.02 kB 0 B
build/viewport/index.js 1.84 kB 0 B
build/warning/index.js 1.14 kB 0 B
build/wordcount/index.js 1.18 kB 0 B

compressed-size-action

@retrofox
Copy link
Contributor Author

retrofox commented May 5, 2020

Wondering if it's a good moment to add a Slot here. Do you have an opinion about this, @mtias?

a: <a href="/customize.php?autofocus[section]=colors" target="_blank"/>
}
),
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I like the PR, I think most of these contexts and tips are WP-specific while the block-editor package is not. (Imagine an editor used to write comments, or outside WP entirely).

We'd have to find a way to "register" these tips on "edit-post" maybe.

Copy link
Contributor Author

@retrofox retrofox May 5, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what do you think about adding a slot there?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel this is more something for a "registration APi". We also have an issue about the possibility to register block-specific tips, so it can scale to absorb that too.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@davemart-in FYI, as this will increase the scope of #20196

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also have an issue about the possibility to register block-specific tips, so it can scale to absorb that too.

This one #17091?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree this should be on a register based API. It also needs to handle user permissions, since access to many of those admin views is not a given for all roles.

@enriquesanchez
Copy link
Contributor

theme - You can visit the theme directory to select a different design for your site.

I wonder if we need to repeat the search query (i.e. theme) in the tip?

@marekhrabe
Copy link
Contributor

Just fiddling with it, I think I would prefer to replace the random tip selection with something more deterministic - like always showing the first matched of something like that. It feels too busy to me when things change as you type.

@retrofox retrofox changed the title Inserter Menu: implement contextual tips May 6, 2020
@obenland
Copy link
Member

obenland commented May 8, 2020

@youknowriad When you get a chance, would you mind taking this on another round of reviews?

</div>
</div>
{ tip && (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding this here means potentially, the tip could show up in the inspector too. Did you really mean to add it to the BlockCard or more to the InserterPreviewPanel?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added it as an example of showing the scope of this approach, where it isn't limited only to the block inserter menu. There a handful of issues about Tips. Here, we'd like to show a block tip if its defined. This PR tackles it as well, allowing us registering tips by block type:

import { dispatch } from '@wordpress/data';

// Register Tips.
const { __experimentalRegisterBlockTip } = dispatch( 'core/block-editor' );
const tips = [
	__( 'Add alternative text to your images to make them more accessible.' ),
	__( 'Use a Cover block to add text on top of your image.' ),
	__( 'To place two images side by side, convert them to a Gallery.' ),
];

tips.forEach( ( desc ) => __experimentalRegisterBlockTip('core/image', desc ) );
@@ -1,9 +1,11 @@

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useless empty line :P

@@ -8,6 +8,7 @@ import {
getBlockType,
} from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';
import { select } from '@wordpress/data';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the usage of the global 'select' or 'dispatch' in Gutenberg should be limited as much as possible because they are singletons and not aware of the parent registries (nested contexts). They are also not reactive. So prefer useSelect and useDispatch instead.

keywords,
description,
};
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The more I think about this, the more I lean towards a dedicated package to register and retrieve tips across screens (and not in block-editor directly). A package similar to the keyboard-shortcuts one.

I'd like @aduth's opinion here too if possible.

It would also be cool to clarify the meaning of each argument (maybe using typing).
I assume:

  • scope means the tips "location" (inserter here for example)
  • context I don't know what it is
  • keywords, potential keywords to filter the tips
  • description (or content) is the actual content of the tip

Should we use an object in order to have a more extensible API?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The more I think about this, the more I lean towards a dedicated package to register and retrieve tips across screens (and not in block-editor directly). A package similar to the keyboard-shortcuts one.

Sounds good to me too as long as we agree that the Redux approach could fit well for the Tips feature.
Glad to move it to a dedicated package.

Should we use an object in order to have a more extensible API?

Probably, yes. Does it mean we could add arbitrary data into the state tree? Or maybe we could an extra field in order to store additional data.

context I don't know what it is

It's a good example of additional data required only for some tips. In this case, I used it as a way to define tip context in the block inserter menu. Its values could be CSS, header, theme, plugin and color. Not totally needed to be honest. We can get rid of it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could the @wordpress/notices package serve as prior art for this sort of requirement? Notices are somewhat similar in being data which represents a text-like representation somewhere in the page. Notices were even modeled to support multiple "groupings" / "areas" where they could be assigned (context), though we don't currently leverage it as far as I'm aware.

@zdenys
Copy link

zdenys commented Apr 20, 2021

I wanted to share some feedback about the visibility of such tips. The tips may be very unlikely to be seen if one just clicks the + button without typing anything. In this scenario, they are at the very bottom of the very long list of blocks. It may be better to show them in the block inserter in the editor itself (just above or below Browse all) or another more visible place. Tips are helpful but are not getting the deserved visibility IMHO.

block-inserter-low-visibility.mov
@retrofox retrofox closed this Apr 11, 2024
@ellatrix ellatrix deleted the update/inserter-menu-contextual-tips branch April 11, 2024 17:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Inserter The main way to insert blocks using the + button in the editing interface
10 participants