-
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
[RNMobile] Inner Block Navigate down through hierarchy #17547
[RNMobile] Inner Block Navigate down through hierarchy #17547
Conversation
Thanks a lot for the update @jbinda At this point I'd like to also invite @Tug to give this a look as well as he introduced the InnerBlocks solution on mobile side and this is the next big iteration on top of it.
Correct. This is how it works on develop as well. It is about how modals interact with the block editor on iOS currently, i don't think we should try to solve this within this PR. |
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.
Approach looks good, I only had a few comments about code clarity. But generally, I would be fine going with this and iterate on the code and UX in a follow up PR.
I'll spend more time reviewing it see if there are other details I missed, would be nice to see the improvements I talked about addressed in the meantime :)
packages/block-editor/src/components/block-list/block.native.js
Outdated
Show resolved
Hide resolved
const isDescendantSelected = selectedBlockClientId && getBlockParents( selectedBlockClientId ).includes( clientId ); | ||
const isDescendantOfParentSelected = selectedBlockClientId && getBlockParents( selectedBlockClientId ).includes( parentId ); | ||
const isTouchable = isSelected || isDescendantSelected || isDescendantOfParentSelected || isParentSelected || parentId === ''; | ||
const isDimmed = ! isSelected && selectionIsNested && ! isAncestorSelected && ! isDescendantSelected && ( isDescendantOfParentSelected || rootBlockId === clientId ); |
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.
Those conditions looks quite hard to understand! Could we try to make them more readable? I haven't spent that much time trying to understand it yet so I might have omitted some edge cases, but from the few cases I can think of, the following conditions would be more readable imo:
const isBlockHighlighted = selectionIsNested && ( isSelected || isParentSelected );
const isDimmed = ! isBlockHighlighted;
I'm not sure how isDescendantOfParentSelected
could play a role here, is there a case where a component is highlighted when a "sibling" is selected?
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.
As I understand, isDimmed
should only be true for blocks that are outside the selection and its descendants, right? There was a suggestion to do a different think, but as far as I understand we didn't decide to go that way. It's not clear to me if we want to dim other blocks when a top level one is selected (even if it has children), or just when we start going 1+ level deep into nested blocks.
There are some redundant checks:
- If
isDescendantSelected
⇒isDescendantOfParentSelected
. SoisDescendantSelected || isDescendantOfParentSelected == isDescendantSelected
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'm not sure how isDescendantOfParentSelected could play a role here, is there a case where a component is highlighted when a "sibling" is selected?
In my version it's the case when you select first child of root block. Without this check the rest of the components stays highlighted.
Next thing is that I need to dim only the bottom most descendant in each branch which should be dimmed to avoid multiplication of opacity applied to block in hierarchy. In other words if I apply opacity to block parent which fits criteria to be dimmed and them apply opacity for the block itself the block will have opacity 0.4 instead of desire 0.2. This opacity increased depending of nesting level. I hope that make sense
There is also edge case that do not dim when RootList block is selected as well.
I gave a shot for what you proposed and it does not works as expected but I will try to refactor original checks to increase clarity and write some comments in the code
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.
@koke I have noticed your comment now so I want to refer to what you wrote as well
There are some redundant checks:
If isDescendantSelected ⇒ isDescendantOfParentSelected. So isDescendantSelected || isDescendantOfParentSelected == isDescendantSelected
That's true according to same branch.
The case for check 'isDescendantOfParentSelected' according to below image is when we have 1-4
selected (red) and isTouchable
should be set to true for 1-2
, 1-5
. Also 1-4-5
,1-4-3
should be touchable(green). The blue one circle represents block that should be dimmed.
I agree that we can simplify this:
const isTouchable = isSelected || isDescendantSelected || isDescendantOfParentSelected || isParentSelected || parentId === '';
to this:
const isTouchable = isSelected || isDescendantOfParentSelected || isParentSelected || parentId === '';
1-5
should have isDescendantOfParentSelected
true and isDescendantSelected
false because 1-4
is not
descendant of 1-5
but is
descendant of 1-5
parent
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.
That's right, I knew one of them was redundant but I got my logic backwards 😅
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'm still not sure about isDimmed
and try to check if we can simplify
packages/block-editor/src/components/block-list/block.native.js
Outdated
Show resolved
Hide resolved
Hi @Tug Thanks for review. I response on comments you gave and make updates |
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.
Thank you @jbinda comments really help in that case I think.
I find the dimmed/highlighted condition is still a bit complicated. As you discussed with Koke there are probably simplifications that could be made in that area.
Regarding the general UX I think this is an improvement from what we currently have so even if it could benefit some refinements, I'm all for merging it as it is now!
💯 🎉
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 think this is looking pretty good and I'd be happy to merge after addressing the few minor things I commented. 👏 👏 So happy to see this one being ready, it's been quite the effort 😅
Co-Authored-By: Jorge Bernal <jbernal@gmail.com>
Co-Authored-By: Jorge Bernal <jbernal@gmail.com>
Co-Authored-By: Jorge Bernal <jbernal@gmail.com>
5a456c9
to
6414b89
Compare
@koke thank you for approval. I fixed thing you have pointed |
gutenberg repoCI pass, but still have some issue with passing gutenberg-mobile PR and will open thread on Slack to solve it |
packages/block-editor/src/components/block-list/block.native.js
Outdated
Show resolved
Hide resolved
packages/block-editor/src/components/block-list/block.native.js
Outdated
Show resolved
Hide resolved
packages/block-editor/src/components/block-list/block.native.js
Outdated
Show resolved
Hide resolved
packages/block-editor/src/components/block-list/block.native.js
Outdated
Show resolved
Hide resolved
const isSelectedBlockNested = !! getBlockRootClientId( selectedBlockClientId ); | ||
|
||
const isDescendantSelected = selectedBlockClientId && getBlockParents( selectedBlockClientId ).includes( clientId ); | ||
const isDescendantOfParentSelected = selectedBlockClientId && getBlockParents( selectedBlockClientId ).includes( parentId ); |
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.
WDYT about create const with getBlockParents( selectedBlockClientId )
and use it instead of calling it 2 times?
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.
After reading this comment, it did look a bit related to the firstToSelect
search, so I think we could have the equivalent (please double check my logic here 😉):
isDescendantSelected
: if the selection is one of the descendants, then this must be a parent of the selection, which also means it will be the lowest common ancestor. SoisDescendantSelected = commonAncestor === clientId
isDescendantOfParentSelected
: similar to the previous one, if the parent of this block is an ancestor of the selection, but the selection is not one of this block's descendants, then the lowest common ancestor if this block's parent:isDescendantOfParentSelected = commonAncestor === parentId
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.
@koke I temporary go with @dratwas suggest.
However I agree with this one isDescendantSelected = commonAncestor === clientId
but not sure about this
isDescendantOfParentSelected = commonAncestor === parentId
Shouldn't we check the common ancestor with parent of selected block ?
Then it will look like this:
const commonAncestorParent = getLowestCommonAncestorWithSelectedBlock( parentId );
const isDescendantOfParentSelected = commonAncestorParent === parentId;
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.
Right, I think that would change the behavior a bit. The commonAncestor == parentId
would not include the case where isDescendantSelected == true
. It would be more accurate to say isDescendantOfSiblingSelected
, which might not be what you had in mind when doing the calculations. I think we can combine both:
const isDescendantSelected = commonAncestor === clientId;
const isDescendantOfParentSelected = isDescendantSelected || commonAncestor === parentId;
But at this stage, this feels more like nitpicking, so I'm happy with either approach, we shouldn't block on this one to merge.
Description
PR is connected with #1314 in gutenberg-mobile.
Please also refer to:
Related gutenberg-mobile PR
merge this PR first [RNMobile] FloatingToolbar and [RNMobile] Inner Block Navigate upward through hierarchy
It presents ability to select all parents in cascade way (according to the way how selecting in groups works on web version)
Please also refer to below description of the logic behind the styles which is applied to the blocks
Details
During selection the main rules are:
not selected
gets dimmed if selection is nested (selected block is a child of other block)1. Blocks on RootListLevel
when a block
is selected
and do not have inner blockswhen a block
is selected
and have or could have inner blockswhen a block is
not selected
and do not have inner blockswhen a block is
not selected
and have or could have inner blocks2. Blocks that renders InnerBlock inside (a component that can have inner block inside e.g.
Group
orMediaText
)InnerBlock is the only one child of component (e.g.
Group
)InnerBlock is not the only one child of component (e.g.
MediaText
)3. Block that is a descendant of InnerBlock component
when a parent
is selected
:when ancestor
is selected
when a block
is selected
LEGEND:
_variables.scss
$block-edge-to-content: 16px;
$block-selected-margin: 3px;
$block-selected-border-width: 1px;
$block-selected-padding: 0;
$block-selected-child-margin: 5px;
$block-selected-child-border-width: 1px;
$block-selected-child-padding: 0;
$block-selected-to-content: $block-edge-to-content - $block-selected-margin - $block-selected-border-width;
$block-selected-child-to-content: $block-selected-to-content - $block-selected-child-margin - $block-selected-child-border-width;
$block-custom-appender-to-content: $block-edge-to-content - $block-selected-margin - $block-selected-child-margin + $block-selected-border-width;
block.native.scss
semi-border:
fully-border:
dashed-border:
neutral:
full:
selectedLeaf:
selectedRootLeaf:
selectedParent:
dimmed:
dimmed:
dimmed:
dimmed:
How has this been tested?
initial-html
to test nested grouping with applied border styling`initial-html`
Screenshots
Initial GIF
Previous state:
2:
Current state:
Types of changes
getLowestCommonAncestorWithSelectedBlock
selector to get blockId that is common ancestor of given block and currently selected blockonFocus
handler to select block in parent hierarchy firstChecklist: