-
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
Add Navigation Links wrapper block #30430
Conversation
Size Change: +265 B (0%) Total Size: 1.3 MB
ℹ️ View Unchanged
|
Adding the 'blocked' status as currently this will break the Navigation editor. We need a way to solve the problem outlined in #30006. |
Thanks for working on this. This is what I see: I understand and support the goal of this PR, but the act of manually building a menu with the added wrapper is very poor Going back to #24644, this seems to be the factor:
Right now the approach of a link wrapper entirely puts the burden on the user, having to learn why there needs to be an additional wrapper, and why manual page links work only inside that wrapper. In addition to this, there's an extra price to pay with the added nesting levels to fiddle with. What alternatives to this approach exist? Can we add the |
I'll look into it! Agree that having to navigate all these nesting levels is suboptimal 😬 |
I quickly put #30551 together to show what that would look like. It does go against the ideal of sharing markup between editor and front end, which feels a bit icky, and will require additional styling to make things look the same in both places. Going back and re-reading all the history that got us to this point 😅 , I'm wondering why something like this hasn't been implemented (Cc. @ellatrix ) |
I think that example was part of the inspiration for const { innerBlocks, innerBlocksWrapperProps } = useInnerBlocks( additionalProps ); The implementation now is a little different, but not massively so: const { children, ...innerBlocksWrapperProps } = useInnerBlocksProps( additionalProps ); The difference (using a |
Ah, just looking and I don't think it would work in the same way. It looks like the main difference is that |
In my mind the path forward here is to think of blocks that add themselves. When a user adds a link it will automatically add a links list block with a link in it. The links list block then only supports adding links as inner blocks. Could we make a think like "required parent" and always wrap a block in the required parent? Another question is if the menu link block should only exist in a links list block? In that case, even the pages block should probably use this links list block ... but that is another discussion. I think adding a hack to fix broken editor html at render time, while looking good at UX level is really poor at implementation level. As we all agree that the main problem UX-wise with this block is the two step of adding a simple link, plus the termite swarm of appenders that one may end up with, this suggestion to have an auto-managed parent seems to fix this. |
Overall, I'm pretty convinced that we do need some wrapper container here and one that users won't interact with. Eg they'd never be able to select the wrapper block, and we'd manage wrapper management (auto-add when needed/auto-remove when last child is deleted). To the user, the appender should be behave like we're adding direct children to the navigation block. Not to blow up scope 😅 , but it feels like we'll probably need to end up taking on an attempt of #7694, with this block and maybe columns as first examples. In terms of UX, we have a lot more options for selecting parents, that we'll need to 🤔 cases for:
In addition to:
Do other folks agree on direction to help move this forward? I'm also happy to collaborate on this one @tellthemachines if that'd be helpful |
#7694 does mention columns, but if we make column a passthrough block won't we lose the ability to set individual widths, as well as to rearrange columns by moving or dragging them? I'm not sure how this would work for Navigation though, as the addition of a passthrough block would have to be conditional on the types of inner blocks in the nav, it would only be rendered around some of those inner blocks and we wouldn't be able to pre-wrap the block appender in a passthrough block as we don't know what type of block the user is going to try to append. I might be missing something, but the problems we have here seem to be unique to Navigation, so the solution will likely have to be a unique one too. |
Not necessarily. The fact that you have to point and select individual columns in order to resize can be considered an aberration to similar interfaces, where I'd expect to see resize handles when the columns block itself is selected, and with input fields for precision or textual control surfaced in the inspector. Now that the columns block supports showing a single column, to an extent at that point it's a group. While I don't think there are any plans for this outlined, I could imagine the transformation from a group to a columns block becoming so transparent as to be imperceptible to users. Specifically for the navigation block, such a group/columns interface could play a part of a future mega-menus interface. This is paused and an incomplete mockup, but it embraces a version of that idea. To support Kerry's notion that this might need a holistic solution, I could see numerous blocks that have complicated markup that needs to be handled:
Ultimately it's about good block design, to surface only the controls and layers necessary to intuitively configure a block, and handling the markup for the user, rather than putting the onus on them. Whether that needs a passthrough block or not, I will defer to you, but the problem will almost certainly resurface outside of just the navigation block. The table block is perhaps the ultimate expression of that, where the notoriously complex markup should be entirely handled by the block, and the user needing only to configure attributes on the table itself, and depending on contextual cell selection inside. |
I'm not tied to columns specifically, just 👀 other non-dynamic blocks that have similar issues. I'm also not sure if my suggestion will work. I do think it's still worth investigating a good timeboxed exploration (maybe a day or two) to sketch out if this is possible, or if we quickly run into some major roadblocks. If we see the latter, we can document those and then I think more folks would be willing to continue with a more specific solution for the navigation block. I'm definitely open to other ideas too if something comes to mind. I think the two two main things to get right are simple UX interactions for folks and more correct markup. Together the requirements makes it really tricky, but there might be a lot of ways to implement that. |
It's been tried by @ZebulanStanphill, but it needs changes to the parser too to be able to do it. |
This is a great point, and would make for a much nicer interface. Thinking out loud a bit here: I'm not sure what the scenario is with List and Quote blocks, or with Table block for that matter - should Tables ever be able to accept nested blocks? That would get us dangerously close to enabling table-based layouts 😬 But the common point I'm seeing between Columns, Navigation and a possible Form block are that, in all of them, we want to be able to group their inner blocks in certain ways. For columns, we want inner blocks in Col A to be separate from those in Col B, and having those intermediate Column blocks gives us a way to do that. It's better for all the intermediate block logic to be invisible in the UI, but users still get to pick which column to nest a block in. For a Form block, we could provide the ability to create semantic groupings of elements, which in the markup would be fieldsets with legends, but users would still get to pick which grouping to drop a particular block in, and name that grouping. For Navigation though, we want particular types of inner blocks - Links and Home block - to be grouped in a specific set, and other types - Search, Social - to be grouped in a different set, but we don't want users to pick which set their block goes in. We want them to be able to add their blocks in whatever order, and then we make sense of which set to put each block in behind the scenes. So these problems are really opposites: for one, we allow users to pick the bucket they want to put whatever block in. For the other, we only give users one bucket, and then we go through and sort the blocks they put in according to type. (With the mega menu we'd potentially have a multi-bucket interface, but we'd still need to sort through each bucket to add the semantics afterwards) Which is why I'm inlined to a different solution for the Navigation (and potentially for any other block that might have a similar single-bucket logic, though I can't think of any offhand) than for Columns/Form/etc. and defining the markup around the blocks after they're added seems simpler than wrapping them in intermediate blocks. Thoughts? |
It wouldn't have to accept every kind of block. It's more about having a cleaner separation of concerns between sections/rows/cells. An example of why it'd be useful is that at the moment a cell can't take advantage of any of the code reuse between blocks (e.g. block supports settings), a feature has to be added in a custom way to the table block and apply to all cells. |
My understanding is that Search/Social shouldn't be in a set, they're just children of the nav block.
I think there's still commonalities between column and links. Quoting from #7694, the passthrough idea is that it 'omits most of the interaction points of a block if it is not intended to be mutated directly, instead serving only as an intermediary for nested block wrapping'. So the block can't be interacted with in a lot of the usual ways. I think it's worth keeping that idea pure and distinct from some of the other ideas for the links block. E.g. that its inner block types are automatically surfaced to the parent navigation block, and are grouped automatically when those inner block types are added. Those things can be distinct from the passthrough idea. Also, just want to mention that I'm not championing this idea, I can see there are potential problems and inconsistencies.
I'm not sure what you mean by 'single-bucket logic'. I think you could still have two or more separate lists of links in a navigation block, potentially separated by a header. I think it's more that consecutive blocks of a certain type get automatically wrapped with HTML list markup. I feel like that needs a technical prototype more than anything to determine how feasible it is.
I remember the gallery had/has the same problem for its switch to inner blocks, not sure whether it was solved there? |
By "set" I mean they are in the group of blocks that are treated as direct children of Nav, as opposed to the group that needs to be wrapped in a list.
By "single-bucket logic" I mean a block that only has one place where users can add blocks, as opposed to e.g. Columns where they can add blocks in each column. The point is we sort through the content of that bucket afterwards, and separate it out into semantic groupings. (That doesn't exclude that we might have more than one list of links, but we have to handle that logic, not the user.) |
Hmm, if we use passthrough blocks this will require seamlessly moving items between blocks. |
Allow my to attempt a 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.
Before we continue down this path, it would be good to have a discussion on lists in the nav block in general (#31827).
Let me first say I'm not at all against this block. I recognise why it might be necessary and it's great to see a PoC 👍 However, reading around the problem space I think we should also consider how adding this block will effect our ability to serialize to the existing Menus. For example, if we use a Link wrapper block then how will this serialize to |
@ellatrix Do you have a PR to allow items to be moved seamlessly across blocks of matching types? That sounds interesting! |
2e17725
to
bec2a78
Compare
@tellthemachines I've rebased the branch as it had accumulated a fair few conflicts. Hopefully that helps a bit? |
Description
Closes #24644.
Adds a new block that is a child of Navigation and parent of Navigation Links. It renders a
<ul>
, removing the need for the<ul>
in the Navigation block.When a Navigation block is created empty, Link List block is added automatically so users can start adding links immediately.
One thing that would benefit from design feedback is the appender situation, which can become confusing because either Links List or Navigation appender will show depending on which block is selected.
It would also be good to have an icon for this block; I used the Navigation Link one for now but it's not ideal.
This also doesn't solve the semantics issue with having Spacer blocks (
<div>
s) inside lists; it's probably best to fix that separately as this changeset is already quite big.How has this been tested?
No automated tests yet; will update fixtures, deprecations etc. once this has been reviewed and we're all agreed on it.
Screenshots
Types of changes
New feature (non-breaking change which adds functionality)
Checklist:
*.native.js
files for terms that need renaming or removal).