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 List: Display inserter button after block on hover, focus #2890

Merged
merged 4 commits into from
Oct 9, 2017

Conversation

aduth
Copy link
Member

@aduth aduth commented Oct 5, 2017

Closes #2752
Related: #833

This pull request seeks to display a block inserter after a hovered or focused block, enabling a user to easily insert between blocks. This is a first step toward eventually dropping the header global inserter (#2755).

image

Design notes:

This is a best-attempt design. Iterations or suggestions are welcome. In particular, the specifics of the clickable/tappable area and hover bounds may need some improvement.

Testing instructions:

Verify that you can insert after a block which is focused or hovered, and that regressions do not otherwise occur with the global inserter or end-of-content inserters.

  1. Navigate to Gutenberg > New Post
  2. Insert a paragraph
  3. Note that hovering this paragraph exposes no inserter, since it's the last block (expected to use end-of-content inserter)
  4. Insert a second block
  5. Hover and/or focus the first paragraph inserted in step 2
  6. Note that an inserter is shown, enabling you to insert a new block after the paragraph

@aduth aduth added the [Feature] Inserter The main way to insert blocks using the + button in the editing interface label Oct 5, 2017
@codecov
Copy link

codecov bot commented Oct 5, 2017

Codecov Report

Merging #2890 into master will increase coverage by 0.03%.
The diff coverage is 36.73%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2890      +/-   ##
==========================================
+ Coverage   34.07%   34.11%   +0.03%     
==========================================
  Files         192      192              
  Lines        5675     5710      +35     
  Branches      996     1004       +8     
==========================================
+ Hits         1934     1948      +14     
- Misses       3165     3181      +16     
- Partials      576      581       +5
Impacted Files Coverage Δ
editor/actions.js 38.88% <0%> (-2.29%) ⬇️
editor/modes/visual-editor/block.js 0% <0%> (ø) ⬆️
editor/inserter/index.js 0% <0%> (ø) ⬆️
editor/reducer.js 89.18% <100%> (+0.22%) ⬆️
editor/selectors.js 96.89% <100%> (+0.14%) ⬆️
editor/inserter/menu.js 49.19% <25%> (-0.4%) ⬇️
components/dropdown/index.js 69.56% <37.5%> (-17.11%) ⬇️
editor/modes/visual-editor/inserter.js 92.85% <50%> (-7.15%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 1400611...e3e0741. Read the comment docs.

Copy link
Contributor

@youknowriad youknowriad left a comment

Choose a reason for hiding this comment

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

Great job so far.

I noticed a small "glitch" which is not totally related but I think we this change, we have to update the inserter at the bottom of the editor to always insert at the end of the post instead of after the selected block.

const { opened } = nextState;
if (
( this.state.opened !== opened || this.props.insertIndex !== insertIndex ) &&
Number.isInteger( insertIndex )
Copy link
Contributor

Choose a reason for hiding this comment

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

When is this second check necessary?

Copy link
Member Author

Choose a reason for hiding this comment

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

The global and end-of-content inserters don't specify the insertIndex prop, so this ensures the sibling insertion point is only set for the between-inserters. It might be the case that insertIndex !== undefined could work well here. I used Number.isInteger elsewhere to capture 0 but not null (since JavaScript is a very sensible language where null >= 0 evaluates to true 😆 )

@@ -51,11 +51,11 @@ export class InserterMenu extends Component {
}

componentDidMount() {
document.addEventListener( 'keydown', this.onKeyDown );
document.addEventListener( 'keydown', this.onKeyDown, true );
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you explain why this change is necessary?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is a similar issue to the one discussed at #2706: Namely, WritingFlow is handling the arrow presses and moving between blocks. The true argument allows us to handle the key press earlier during the capture phase. I might take another pass at this, and I wonder why we need to bind to the document at all instead of using React events (since I expect bubbling would work better in the latter case). If I keep it as-is, I'll add a clarifying comment.


if ( isHovered || isSelected || isMultiSelected ) {
if ( isHovered || isSelected || isMultiSelected || isInserterOpen ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess this check is to avoid "removing" the inserter when we hover out of the block?
Maybe we can handle this in a simpler way: select the block when we open its inserter.
I'm just trying to avoid this dependency between the inserter and this component.

Copy link
Member Author

Choose a reason for hiding this comment

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

Maybe we can handle this in a simpler way: select the block when we open its inserter.

That sounds like a good idea! I'll give it a try.

@gziolo
Copy link
Member

gziolo commented Oct 6, 2017

@aduth, thank you for working on this one. In my opinion, this was the biggest UX issues I discovered so far in Gutenberg 🥇

@aduth
Copy link
Member Author

aduth commented Oct 6, 2017

I noticed a small "glitch" which is not totally related but I think we this change, we have to update the inserter at the bottom of the editor to always insert at the end of the post instead of after the selected block.

Yep, makes sense. I'll change this.

@aduth aduth force-pushed the update/between-inserter branch from 5bc749e to e3e0741 Compare October 6, 2017 15:58
@gziolo
Copy link
Member

gziolo commented Oct 9, 2017

I tested this PR. I love the changes introduced ❤️

Just saying that this toolbar doesn't play well with this change. I think that the toolbar needs some rethinking, because it also makes it harder to read the previous paragraph /cc @jasmussen

screen shot 2017-10-09 at 10 27 20

The last block looks a bit different, but I think it makes a lot of sense:

screen shot 2017-10-09 at 10 30 54

I can confirm that the last commit fixes issue mentioned by @youknowriad and the add code itself look good to me.

@gziolo
Copy link
Member

gziolo commented Oct 9, 2017

@jasmussen what if we would move the very last + button to be rendered the same way as all other icons, but it would be always visible? We could also mirror the behavior of the existing + button and show on hover the following:

screen shot 2017-10-09 at 10 35 11

name,
insertionPoint
);
class Inserter extends Component {
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess we don't need this to be a class component, but probably the same discussion for/against inline props.

Copy link
Member

Choose a reason for hiding this comment

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

I hope we will see the day where there is only one supported way of creating components in React. I feel like some components are converted back and forth whenever requirements change.

Copy link
Contributor

@youknowriad youknowriad left a comment

Choose a reason for hiding this comment

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

For me, this is good to ship. There are some UI concerns like pointed out by @gziolo but worth a try. Also, I'll explore the fixed toolbar switch soon which could solve the toolbar issue.

@gziolo
Copy link
Member

gziolo commented Oct 9, 2017

Yes, totally agree we should ship it as it is and continue the discussion here.

@gziolo gziolo merged commit b6480da into master Oct 9, 2017
@gziolo gziolo deleted the update/between-inserter branch October 9, 2017 08:47
@jasmussen
Copy link
Contributor

Designwise, I'd like to echo @gziolo's comments, this isn't ideal and it adds some visual load to the block silhuette.

I don't want to block this from moving forward — nice work — but it does seem like a half-step.

I understand the moving parts — it has to be accessible, it has to be fairly simple codewise, and the previous solution wasn't great either. But interface wise, we are at a point where we should be extremely careful to introduce visual regressions, especially since this is one of the critiques that is (fairly so) leveraged on Gutenberg these days.

One of the design patterns of Gutenberg is that it's possible to show further block options when a block is selected. A common editor pattern when you want to insert content in between paragraphs or other elements, is to make a linebreak.

Perhaps we could show the inserter when a block is selected? Perhaps we could show an empty line when a block is selected, and have the Enter button put the cursor there? Perhaps both? It seems like it is worth looking at how desktop publishing apps solve this.

Either way it's important we strike a balance between something that is easy to implement and solves the problem, with the cognitive load that it adds. In this case it feels like there's an imbalance. This implementation also doesn't solve the inserting images inline (#2043), and it seems like this inserter pattern would've been a good opportunity to look at that.

@gziolo
Copy link
Member

gziolo commented Oct 9, 2017

As I mentioned above, not having such button available next to each block caused me the biggest struggle when I opened Gutenberg for the first time.

I must admit, I got to easily tempted to click Merge button in here :) I will be more cautious next time and wait for a wider feedback whenever we introduce UI/UX changes.

Perhaps we could show the inserter when a block is selected? Perhaps we could show an empty line when a block is selected, and have the Enter button put the cursor there? Perhaps both? It seems like it is worth looking at how desktop publishing apps solve this.

At the moment when you hover over one of the existing blocks you can see arrows which allow moving the block up or down in the document hierarchy:

screen shot 2017-10-09 at 11 30 01

In that context add block button plays a similar function, but as you observed it adds another visual element to the block. Let's continue the discussion in #2925.

@mtias
Copy link
Member

mtias commented Oct 9, 2017

Adding a bit more context as I discussed this one with @aduth in person. The point was to add functionality that allowed the user to insert blocks in between other blocks easily and without hidden interactions.

Implementation wise I think we should treat this inserter as a separate element—or at least, visually separate. It should show when we hover the limit area between two blocks. Additionally, it can show up when a block is selected. Something more like this:

image

This is also in anticipation of nested blocks, which would use the pattern of the bottom inserter.

@gziolo gziolo restored the update/between-inserter branch October 9, 2017 11:23
@gziolo gziolo deleted the update/between-inserter branch October 9, 2017 11:23
@aduth
Copy link
Member Author

aduth commented Oct 9, 2017

Implementation wise I think we should treat this inserter as a separate element—or at least, visually separate. It should show when we hover the limit area between two blocks.

In trying to imagine how this would operate in practice, I get the sense that it might be frustrating to find the sweet spot between hovering and individual block and hovering between blocks to reveal the inserter. It was already not-great in the implementation which was proposed here.

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
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants