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

Add hovered block store and show hovered template part's label in edit site header component. #25348

Closed
wants to merge 38 commits into from

Conversation

Addison-Stavlo
Copy link
Contributor

@Addison-Stavlo Addison-Stavlo commented Sep 15, 2020

Description

Adds a way to track hovered blocks by adding them as an array of clientIds in the block-editor store. This information is then used to show the hovered template part's label in the component added in #25320 (alternative approaches discussed in #25469).

hovered-template-part-label

The first approach to implement this store tried to add/remove blocks individually by clientId. However, this ran into a blocker with the inserter triggering removal for all blocks that it appeared to be within the bounds of. Parsing the blocks found under the cursor and setting the full list solves this problem, and the hovered name is no longer disrupted by the inserter as shown in the gif above.

How has this been tested?

  • Tested in the Site Editor
    • hover over a template part and verify its label is displayed in the middle of the top toolbar.
    • hover over a block inserter within the template part and verify the label in the top toolbar does not disappear.
  • Smoke tested in Post Editor.

Screenshots

Types of changes

New feature (non-breaking change which adds functionality)

Checklist:

  • My code is tested.
  • My code follows the WordPress code style.
  • My code follows the accessibility standards.
  • My code has proper inline documentation.
  • I've included developer documentation if appropriate.
  • I've updated all React Native files affected by any refactorings/renamings in this PR.

@github-actions
Copy link

github-actions bot commented Sep 15, 2020

Size Change: +303 B (0%)

Total Size: 1.21 MB

Filename Size Change
build/annotations/index.js 3.78 kB -2 B (0%)
build/block-editor/index.js 133 kB +256 B (0%)
build/block-library/index.js 147 kB +1 B
build/components/index.js 172 kB +2 B (0%)
build/core-data/index.js 12.5 kB +1 B
build/edit-site/index.js 22.6 kB +42 B (0%)
build/nux/index.js 3.42 kB +1 B
build/rich-text/index.js 13.2 kB +2 B (0%)
ℹ️ View Unchanged
Filename Size Change
build/a11y/index.js 1.14 kB 0 B
build/api-fetch/index.js 3.45 kB 0 B
build/autop/index.js 2.84 kB 0 B
build/blob/index.js 665 B 0 B
build/block-directory/index.js 8.72 kB 0 B
build/block-directory/style-rtl.css 943 B 0 B
build/block-directory/style.css 942 B 0 B
build/block-editor/style-rtl.css 11.2 kB 0 B
build/block-editor/style.css 11.2 kB 0 B
build/block-library/editor-rtl.css 8.96 kB 0 B
build/block-library/editor.css 8.96 kB 0 B
build/block-library/style-rtl.css 8.03 kB 0 B
build/block-library/style.css 8.03 kB 0 B
build/block-library/theme-rtl.css 792 B 0 B
build/block-library/theme.css 793 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/blocks/index.js 48.1 kB 0 B
build/components/style-rtl.css 15.3 kB 0 B
build/components/style.css 15.3 kB 0 B
build/compose/index.js 9.81 kB 0 B
build/data-controls/index.js 772 B 0 B
build/data/index.js 8.8 kB 0 B
build/date/index.js 31.8 kB 0 B
build/deprecated/index.js 768 B 0 B
build/dom-ready/index.js 571 B 0 B
build/dom/index.js 4.46 kB 0 B
build/edit-navigation/index.js 11.2 kB 0 B
build/edit-navigation/style-rtl.css 881 B 0 B
build/edit-navigation/style.css 885 B 0 B
build/edit-post/index.js 306 kB 0 B
build/edit-post/style-rtl.css 6.41 kB 0 B
build/edit-post/style.css 6.39 kB 0 B
build/edit-site/style-rtl.css 3.91 kB 0 B
build/edit-site/style.css 3.91 kB 0 B
build/edit-widgets/index.js 26.3 kB 0 B
build/edit-widgets/style-rtl.css 3.12 kB 0 B
build/edit-widgets/style.css 3.12 kB 0 B
build/editor/editor-styles-rtl.css 480 B 0 B
build/editor/editor-styles.css 482 B 0 B
build/editor/index.js 42.8 kB 0 B
build/editor/style-rtl.css 3.85 kB 0 B
build/editor/style.css 3.85 kB 0 B
build/element/index.js 4.65 kB 0 B
build/escape-html/index.js 735 B 0 B
build/format-library/index.js 6.76 kB 0 B
build/format-library/style-rtl.css 547 B 0 B
build/format-library/style.css 548 B 0 B
build/hooks/index.js 2.16 kB 0 B
build/html-entities/index.js 623 B 0 B
build/i18n/index.js 3.57 kB 0 B
build/is-shallow-equal/index.js 712 B 0 B
build/keyboard-shortcuts/index.js 2.52 kB 0 B
build/keycodes/index.js 1.94 kB 0 B
build/list-reusable-blocks/index.js 3.11 kB 0 B
build/list-reusable-blocks/style-rtl.css 476 B 0 B
build/list-reusable-blocks/style.css 476 B 0 B
build/media-utils/index.js 5.34 kB 0 B
build/notices/index.js 1.79 kB 0 B
build/nux/style-rtl.css 671 B 0 B
build/nux/style.css 668 B 0 B
build/plugins/index.js 2.56 kB 0 B
build/primitives/index.js 1.43 kB 0 B
build/priority-queue/index.js 791 B 0 B
build/redux-routine/index.js 2.85 kB 0 B
build/reusable-blocks/index.js 3.06 kB 0 B
build/server-side-render/index.js 2.77 kB 0 B
build/shortcode/index.js 1.69 kB 0 B
build/token-list/index.js 1.27 kB 0 B
build/url/index.js 4.06 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.22 kB 0 B

compressed-size-action

Copy link
Member

@noahtallen noahtallen left a comment

Choose a reason for hiding this comment

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

pretty cool stuff! I'm excited to see where this takes us.

packages/block-editor/src/store/reducer.js Outdated Show resolved Hide resolved
packages/edit-site/src/components/header/index.js Outdated Show resolved Hide resolved
@Addison-Stavlo
Copy link
Contributor Author

Pausing this here briefly to implement a rough idea of another approach so we can compare before moving forward.

Copy link
Contributor Author

@Addison-Stavlo Addison-Stavlo left a comment

Choose a reason for hiding this comment

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

Could use some eyes and thoughts on this. Will update jsdocs/tests/comments etc. if we solidify that this is the way to go.

@Addison-Stavlo Addison-Stavlo changed the title WIP - Try/hovered block tracking Add hovered block store and show hovered template part's label in edit site header component. Sep 23, 2020
@Addison-Stavlo Addison-Stavlo removed the Needs Accessibility Feedback Need input from accessibility label Sep 23, 2020
@Addison-Stavlo
Copy link
Contributor Author

Instead of limiting by timestamps, a better option could be to limit on mouse position of the last evaluation. While simultaneous events may have slightly different timestamps in some browsers, it seems the mouse positions are always the same.

However, we would need to account for scrolling. Otherwise, when the mouse is in the same position and we scroll down the document it would never re-evaluate what is hovered.

event.pageX and event.pageY would normally work, however since the editor and its scrollbar are internal to the actual document this essentially works the same as event.clientX / event.clientY. Similarly, we cannot combine this with scroll location like window.scrollY since the scrollbar in the editor is internal to the document.

We could:

  • do a combination of pointer location and timestamp - Only re-evaluate if the pointer position is different OR some deltaT has passed since the last calculation.
  • Find a non-hacky way of determining the editors scroll location and combine this with pointer location (no timestamp necessary).
  • Just limit on pointer location alone and be fine with the fact that the hovered entities wont update scrolling down the page until the mouse is moved again.

Number 2 would be good if there is already a way to do this. 🤔 Kind of a shame pageX/pageY won't work on their own.

@jeyip
Copy link
Contributor

jeyip commented Oct 2, 2020

Find a non-hacky way of determining the editors scroll location and combine this with pointer location

To clarify, I'm not the most familiar with scroll attributes, but couldn't we evaluate scrollTop and scrollLeft on the editor?

To be more specific, I tested this in the chrome dev console. document.querySelector('div.interface-interface-skeleton__content').scrollTop

@Addison-Stavlo
Copy link
Contributor Author

but couldn't we evaluate scrollTop and scrollLeft on the editor?

Yeah we could do that. I was hoping there was a better way to get ahold of that info without querySelector but haven't been having much luck. That interface skeleton is from a different package so it might be a bit odd to have something from the block-editor rely on it as well.

@Addison-Stavlo
Copy link
Contributor Author

do a combination of pointer location and timestamp - Only re-evaluate if the pointer position is different OR some deltaT has passed since the last calculation.

Tried this for now. Although it would be nice to get rid of that timestamp, we will need some way to detect scroll position in combination of mouseCoords for that. The timestamp is now just used to allow scrolling over blocks with the cursor in the same position to re-trigger the evaluation.

Comment on lines 36 to 40
// event firing from multiple nested blocks. Checking the time allows us to re-evaluate
// even when mouseCoords have not changed, such as when scrolling via mouse-wheel.
// However, this deltaTime checked must be sufficiently long to ensure slow CPUs do not
// trigger unnecessary recalculations for events triggered simultaneously.
const { time, mouseCoords } =
Copy link
Contributor Author

@Addison-Stavlo Addison-Stavlo Oct 6, 2020

Choose a reason for hiding this comment

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

Scroll location would be much better to check than the last timeStamp to ensure this works on scrolling as well. However, the scroll location corresponds to the interface-interface-skeleteton__content which is contained in the interface package. Whether we found a way to reference this element or querySelector'd for it here, we would make this functionality dependent on a separate package which is also not ideal. The time check will work, but fast mouse-wheel scrolls may not always re-trigger the evaluation (not the end of the world 🤷‍♀️ , I figure it is better to try to be safer with performance).

@Addison-Stavlo
Copy link
Contributor Author

Im thinking this should be more or less 'ready to go' at this point.

Copy link
Member

@noahtallen noahtallen left a comment

Choose a reason for hiding this comment

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

I'm in favor of merging this to try it out. The code looks good, and it tests well locally. Thanks for all the iterations @Addison-Stavlo!

I don't think we should spend any more time optimizing it though. So if folks don't agree that we should merge and try out, I think we should move on from this for now.

Copy link
Member

@vindl vindl left a comment

Choose a reason for hiding this comment

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

I'm also in favor of trying this out, we can always revise the approach later if we come up with a better way to resolve the underlying issue. It tests well for me and the code is looking good. Nice work @Addison-Stavlo! ✨

eventCoords
);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if there might be something in common with the multi-selection hook where we do similar things. cc @ellatrix

const { hoveredBlockIds, timeStamp, mouseCoords } = action;
return {
hoveredBlockIds,
eventData: {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we need thisi information in state?

Copy link
Member

Choose a reason for hiding this comment

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

the scenario is: "move mouse over a block which is deeply nested". This will trigger N hover events for N nested blocks. If we have a ton of those blocks, we'll be dispatching to the store N times, which caused performance issues. To avoid updating the store that often, we need to compare the timestamp of an event with the timestamp of another event. So we track the timestamp here. I think the other option would be storing it in a global variable in the file where it's used

Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a way to "stop propagation" somehow on the event?

Copy link
Member

Choose a reason for hiding this comment

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

i'm unsure, I'll leave that for @Addison-Stavlo to answer

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is there a way to "stop propagation" somehow on the event?

I didn't have any luck. It's not one event bubbling, but many events being triggered simultaneously.

I think we can get around requiring this information and extra complexity by debouncing. e41e82d

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That said, while having a way to track which blocks are hovered is neat, given the comments from design below it doesn't seem like we have a consensus on where we should use this information yet (probably not in the document actions header from the sounds of it 😆 ). This could prove useful in implementing something similar in the future (such as closer to the cursor #25348 (comment)), but until we figure out the right place to utilize this there is no rush for adding the handlers and store either.

@vindl vindl added the Needs Design Feedback Needs general design feedback. label Oct 16, 2020
@shaunandrews
Copy link
Contributor

I have mixed feelings here. One side of me likes the interactivity and the ability to quickly see what template parts make up my document; But the other side of me things maybe there's too much changing as I move my mouse pointer around the screen.

As is, the transition doesn't handle nested template parts well; I'd expect the label to animate even for nested template parts.

--

I think for the normal edit mode, this might be too much motion on the screen. However, maybe it could make sense as part of select mode, which already shows block borders on hover.

@jameskoster
Copy link
Contributor

I'd agree that the visual feedback can be helpful, but if we want to add something I'd like for it to be closer to the cursor. Trying to mouse over my Footer template part, but having to look at the top of my screen to understand when I've hit the target is kind of uncomfortable.

Base automatically changed from master to trunk March 1, 2021 15:44
@Addison-Stavlo
Copy link
Contributor Author

a bit old and stale, past due for a close button click.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Design Feedback Needs general design feedback. [Type] Performance Related to performance efforts
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants