-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Selecting Parent Blocks: Try clickthrough #15537
Conversation
🎉 This is an excellent exploration. Like @jasmussen, I originally thought this would seem cumbersome, but in practice it feels really natural. I also agree that it could live alongside a change like #14961: this PR makes it easy to click down the tree of nested blocks, but the other PR would make it easier to click back up the tree as well. I actually tried smashing these PRs together, and in general it seems quite usable to me: That said, I'm not sure the additional borders are totally necessary if we went this route? This does feel fairly natural as-is. I 100% agree that clicking 3 times to get into the columns block is annoying, but that block needs some reworking anyway. I think it'd be fine to build in a special case solution for it in the meantime (like maybe the second click bypasses the individual Aside from the little hiccups Joen noted above there are a couple other aspects of this that need a bit of consideration:
This is obviously remedied by just clicking once, so I'm not sure it's a huge deal though.
|
Also, a quick suggestion: in many design apps, you can directly select a child of a group by holding a modifier key when clicking (often the |
Thanks so much Kjell, your thoughts are much appreciated, and they are all solid. I definitely think the outlines branch and this PR could work well together. It is a very complex UI issue, and multiple approaches are sound. We might even find, if this branch works well, that the outlines branch can become slightly subtler than it is now — thinking about it, it seems perhaps more important to show the outlines when the parent block is selected, given the behavior suggested in this branch. Your observation on full-wide is solid. I would suspect that the outlines suggested right in the previous paragraph is one way in which this can become more visible. Another might be to actually show a color overlay when hovering to indicate the boundaries. But this is probably best explored separately. The 2nd bug you mention, yep I can reproduce it. Great catch, we'll want to fix that for sure. I've asked @gziolo for some help with some of these things, and hopefully we can fix this up together.
That's a killer tip, I love it. In addition to being able to just double-click, that will be a nice detail! |
It's better with effe011 but I still need to further investigate how to make this behavior more consistent: I guess it's fine to optimize it with Column block being the one which intercepts the click as it will have to be covered with nested Group blocks regardless. We can remove the overlay behavior from Column block later. That's probably the easiest part. |
I like this proposal a lot. If you look at my screencast you can see that double-click and triple-click trigger the default browser behavior: selecting a word and a group of text. |
I'm loving this PR! Here's some observations:
The clickthroughs feel right to me. It's so much better than trying to fidget with the cursor to grab just the parent block. Thanks for this exploration! |
In 5ee69d0 I added background colors to make it easier to debug why a single Column block gets selected from time to time: It looks like overlays don't fit properly to the are they should cover. I'm also wondering whether their order shouldn't be reversed. That would explain why deeply nested blocks sometimes get selected instead of Column block. |
Thanks everyone for the feedback. I will look a bit today at some fixes to what you've noted:
@mapk the Edit Image placeholder thing appears to happen in master too! And as far as I can tell, only in Safari: Can you open a new issue for this? It's possible that "double-click" is intended to go to that edit mode, though that feels a bit weird. I would also agree that it's a bit annoying that you have to click three times on columns. But I would also suggest that this is a more fundamental issue with the columns block itself, and something that's worth exploring improvements to separately. If at all possible it'd be nice if individual columns didn't have to be selected individually, but that options for resizing and aligning were available directly in the top level columns block. Much like "Media & Text", in other words. Given a change was recently merged to make the individual column block selectable again, because it can now be resized, I think we should explore reducing the amount of nesting for this block as a separate effort. What do you think? |
In 84a13f7 I fixed the issue where when you try to click the toolbar of a block that's adjacent to a block with the clickthrough overlay, you'd select the overlay. But I'm surfacing it here because it feels a bit wrong to be giving the contextual toolbar such a high z-index... but it has to be higher than the click overlay. @aduth can you recall why the click overlay was given a z-index of 120? Do you think 2 could be sufficient? |
I spent some time investigating whether it was possible to not select words when doubleclicking, and select all text when triple clicking. As it turns out because this is operating system level behavior, it's not really possible to disable that. You can use various Barring a hack I cannot think of, this aspect is not fixable without JavaScript. That is — if we truly loathe that quickly double clicking to edit text inside a nested block also selects that text — we'll have to unset the text selection at the end of the operation. Which we should probably avoid for now, both since it's rare, and because it's a disruptive fix we can explore separately. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks good code-wise. I added most of the JavaScript changes so I would appreciate confirmation from @youknowriad given his expertise around the performance implications related to changes applied. Benchmark results look good but I might miss something important.
useSelect, | ||
} from '@wordpress/data'; | ||
|
||
const BlockAsyncModeProvider = ( { children, clientId, isBlockInSelection } ) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Conceptually speaking and if there's no impact on performance it would be better to avoid the isBlockInSelection
as a prop and compute it here :).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
b0649e1 - I had it before but I assumed it could impact performance. I can try with the previous commit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't thin that benchmark agrees with this idea:
Average time to load: 5724ms
Average time to DOM content load: 5219ms
Average time to type character: 187.28ms 😅
Slowest time to type character: 319ms 🐢
Fastest time to type character: 158ms 🐢
Average time to load: 7533ms 🐢
Average time to DOM content load: 7011ms 🐢
Average time to type character: 177.2ms 🐢
Slowest time to type character: 321ms 🐢
Fastest time to type character: 145ms 🐢
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:)
Hooraay! I see a green button and approvals. I will wait for final sanity checks by Riad, and advice on when it's best to merge. But I'm excited to see this land. It solves numerous ux issues around block nesting, and although it takes a little getting used to first time you use it, the PR that @kjellr has pending shows deftly that it is possible to improve the UX further, with visual feedback. Thanks everyone. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Run the performance tests as well and I have similar results as well.
Thanks everyone for your hard work on this PR 👏 |
Hooray! Thank you all for the help Now that it's in, I will work with Kjell to refine the experience. |
This PR rocks! Thanks for continued push to merge. You all did fantastic here! 🎉 |
nice. i want to use it now. |
@jasmussen Thanks, I hate it :) I can see this feature being useful for the average user, but as a "power user" it slows me down and confuses me immensely. In some instances I need to click up to 5 times just to edit some text. I guess everyone else only tested it with core blocks and 1-2 levels of nesting, in which case it's fine. Additionally now it's hard to select an element with the Dev Tools since it won't let you select it unless your editor focus is in the right place. Definately needs a toggle in my opinion. I would prefer a feature such as holding down |
Thanks for your feedback. There are a number of refinements to this underway, including some outlines to show parent and child elements and their relationship when a block is selected, and it's also been suggested to implement a keyboard shortcut, so when you hold for example ⌘ and click, you click the nested block under your mouse directly. A per-block opt-in or opt-out has also been discussed. This would be set by the block author, to opt in or out of the click overlays. So for example if the author of the Media & Text block might opt out of the overlay because it's not necessary for the operation of the block. However for other blocks such as the Columns block, it's virtually impossible to select the individual columns without this interface, so it's important to have a baseline tool for making that possible even for casual users that don't know about keyboard shortcuts or toolbar buttons. I'm personally excited about the keyboard shortcut. It feels like a good balance between a userfriendly interface for the casual user, and a tool for powerusers to know if they want to click right through it all. @gziolo do you have any thoughts on how easy/hard such a keyboard shortcut would be to build? Essentially the clickthrough layer needs to be aware of whether the button is pressed down, and then simply behave as if it's not there ( |
We use a similar approach for multi-selecting blocks when you hold down |
I did a quick check with the following code: diff --git a/packages/block-editor/src/components/inner-blocks/index.js b/packages/block-editor/src/components/inner-blocks/index.js
index 75a6731f4..bc59bd92f 100644
--- a/packages/block-editor/src/components/inner-blocks/index.js
+++ b/packages/block-editor/src/components/inner-blocks/index.js
@@ -29,9 +29,12 @@ class InnerBlocks extends Component {
constructor() {
super( ...arguments );
this.state = {
+ clickthroughEnabled: true,
templateInProcess: !! this.props.template,
};
this.updateNestedSettings();
+ this.onKeyDown = this.onKeyDown.bind( this );
+ this.onKeyUp = this.onKeyUp.bind( this );
}
getTemplateLock() {
@@ -102,20 +105,42 @@ class InnerBlocks extends Component {
}
}
+ onKeyDown( event ) {
+ if ( event.metaKey ) {
+ console.log( event.metaKey );
+ this.setState( {
+ clickthroughEnabled: false,
+ } );
+ }
+ }
+
+ onKeyUp( event ) {
+ if ( event.metaKey ) {
+ console.log( event.metaKey );
+ this.setState( {
+ clickthroughEnabled: true,
+ } );
+ }
+ }
+
render() {
const {
clientId,
hasOverlay,
renderAppender,
} = this.props;
- const { templateInProcess } = this.state;
+ const { clickthroughEnabled, templateInProcess } = this.state;
const classes = classnames( 'editor-inner-blocks block-editor-inner-blocks', {
- 'has-overlay': hasOverlay,
+ 'has-overlay': hasOverlay && clickthroughEnabled,
} );
return (
- <div className={ classes }>
+ <div
+ className={ classes }
+ onKeyDown={ this.onKeyDown }
+ onKeyUp={ this.onKeyUp }
+ >
{ ! templateInProcess && (
<BlockList
rootClientId={ clientId } I don't think it works as expected, this might need to have to be controlled from |
Awesome, thanks so much for looking. We definitely want to use ⌘ on a Mac, as that's the standard keyboard shortcut for this behavior. Figma, Sketch and Illustator are examples of this behavior, where if you have a group, a single click selects it, but a ⌘ click selects the item inside the group directly. I can't recall what the corresponding Windows shortcut key is, it's probably Alt, but perhaps @kjellr can recall? |
Alt sounds right to me, but I don't have a windows machine around to double check at the moment. |
This reverts commit c5e8784.
This PR takes a stab at using existing code by @aduth that is implemented on mobile, and expanding it to the desktop breakpoint as well. Specifically, it enables what we in #9628 refer to as "click-through".
With "click-through", whenever you interact with a block that has innerblocks, a click first select the parent, and then it selects direct descendants. For example you first click the Cover block, then you click the Paragraph block inside. Or you first click the Columns block, then you get to select the Column (singular) block, and then you can select content inside. GIF:
This branch is a work in progress. There are issues to refine and work out.
Click-through is inspired by how many desktop applications handle "groups". There, you commonly have to double-click a group to be able to select items inside. This PR is the same, except you click only once to "open" the group. There are a great deal of benefits to this approach:
The first thing you might think is: what about situations where you want to edit text quickly?
That specific question is the primary reason it's taken until now to test this out in practice. My assumption was that this would create unnecessary friction to editing text. However:
Issues
This is the code:
! isSelectedBlockInRoot
— we'll likely need an additional variable that is aware of immediate parent and not just the root ancestor.Other considerations
For now this is a draft PR, but I strongly urge you to try it out and not just look at the GIF. It feels better in actual practice, than it looks, and with things like #15499 on the horizon, this could be a good baseline improvement to improve the situation with selecting parent and child blocks.
It also doesn't preclude additional and separate improvements from taking place, such as:
For now, though, I would really appreciate your thoughts on this PR. Please, more than anything, take it for a spin!