Convert navigation sections to blocks and use the menu system

Created on 26 October 2023, 8 months ago
Updated 11 January 2024, 5 months ago

This is very much a draft, and may not be the right approach. However, what I started at the Lille code sprint is now working, and in the process I was able to become familiar with much of the current navigation module code.

Problem/Motivation

Site builders need to be able to customize the Navigation toolbar menu through the user interface, as they can today with the toolbar module.

Currently, the navigation module implements new plugin types for navigation sections. It also directly interacts with routes to build many links, which makes it harder for site builders to customize.

Proposed resolution

First, instead of implementing a brand-new plugin type, we add a NavigationBlock type that overlaps and extends the Block plugin definition. This gives us some flexibility in that:

  • We can easily generate blocks for all system menus (included in this MR).
  • We can in a future issue add a "developer mode" option or submodule that derives all regular blocks into navigation blocks for placement in the navigation menu. For example, if environment indicator exposes a block, then a developer will be able test out their module, or adventurous site builders can play with unsupported blocks.
  • We can choose later to derive regular block plugins from all navigation block plugins. Since they implement a superset of the Block annotation attributes, and the same interface methods, they should work reasonably well.

Second, we ship and generate the links for a new Content menu. That way, site builders can turn off specific entity bundle links for the "add" links, or add their own. They could even add an external link if key content is actually managed outside of Drupal. This MR implements this dynamically (similar to some existing code) so things don't break if a module (like media) doesn't exist or a view is deleted.

Third, we place the blocks into the navigation menu with a few hardcoded calls. In a future issue, this would be replaced with a UI that allows users to select from all exposed NavigationBlocks and place them in the content or footer sections.

Remaining tasks

Discuss!

User interface changes

We add a new top-level Content menu: Here's an example of the current menu in Umami:

And part of the Content menu:

๐Ÿ“Œ Task
Status

Fixed

Version

1.0

Component

Code

Created by

๐Ÿ‡จ๐Ÿ‡ฆCanada deviantintegral

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @deviantintegral
  • ๐Ÿ‡จ๐Ÿ‡ฆCanada deviantintegral

    Yesterday, we had a call reviewing this with @ckrina, @laurii, @ted.bowman, @tim.plunkett, and myself, along with some followup chats.

    This is from my own notes on the call, feel free to comment if I misrepresent anything!

    In terms of functionality, site builders:

    • Should be able to customize the links in menus, just like they can today.
    • Should be able to add brand-new menus that they create from scratch, or menus from other modules.
    • Should be able to reorder menu blocks themselves.
    • Should be able to add non-menu blocks to the green content area in this screenshot, as long as those blocks have been explicitly tagged somehow as being navigation menu compatible. For example, we could easily imagine site builders wanting to somehow put a list of recently edited content int the menu. While we wouldn't want to expose all Views blocks by default, once we have a way to mark those blocks as good in the nav menu we want site builders, and not developers to be able to manage them.

    Developers:

    • Should be able to customize the top region and the bottom region, for modules like Workspaces or Environment Indicator.

    From a technical perspective, this is actually the first time plugin implementations have been subclassed in core. @tim.plunkett pointed out that there's real dragons as far as backwards compatibility goes, especially with constructors. There are instances of contrib modules doing this (like superfish), but in practice we may make things simpler and just ditch the whole aspect of subclassing. As well, it may be easier to alter in additional block annotation properties than to try and do an entirely separate annotation type.

    For next steps, I would like to:

    • Implement an example integration for a core module like Announcements or Workspaces.
    • Use that to learn what makes sense as far as the existing "as block plugins" approach goes.
  • ๐Ÿ‡ซ๐Ÿ‡ฎFinland lauriii Finland
  • ๐Ÿ‡จ๐Ÿ‡ฆCanada deviantintegral

    I've redone how the plugins are handled and I'm much happier with the approach. IMO it's simpler and more robust.

    Instead of a separate annotation, we now look for navigation on the normal Block annotation. I've defined it as an array, so we can add keys like default_region, weight, and so on. To do this, we add our own plugin manager that wraps the block manager (it's not really decoration because we don't swap the service). It handles filtering available plugins and validating the additional keys.

    Then, I implemented the announcements feed as a demo block. An interesting side effect is that the Announcements menu item works as is, showing the dialog of announcements on the left hand side.

    For next steps, it would be great for someone else to look at what I've done with the navigation block manager and share any compatibility concerns or similar I may have missed.

  • Pipeline finished with Success
    7 months ago
    Total: 188s
    #52134
  • Pipeline finished with Success
    7 months ago
    Total: 189s
    #52139
  • Pipeline finished with Success
    7 months ago
    Total: 401s
    #52205
  • Pipeline finished with Success
    7 months ago
    #52298
  • Pipeline finished with Success
    7 months ago
    Total: 286s
    #52303
  • ๐Ÿ‡จ๐Ÿ‡ฆCanada deviantintegral

    To followup and summarize on next steps for this:

    There's some skepticism that it will be possible to have a single block implementation that can ever work in both a navigation and non-navigation context.
    The block system has intentionally been designed to not include any sort of real rendering context in the `build()` method.
    There's also some worry that if there are separate blocks implemented to handle these cases, that the regular block admin could have duplicate blocks.
    While Blocks have a context system (\Drupal\layout_builder\Plugin\Block\ExtraFieldBlock does this to associate an entity object), in practice they are best used for data and not theme or rendering information.

    A good next step would be to walk this back to having a separate plugin implementation, _but_ still have Navigation blocks implement or extend \Drupal\Core\Block\BlockPluginInterface. That interface already defines most of what we need for navigation blocks, and would provide a familiar pattern for contrib modules to implement navigation support, or to more easily extend and share code for existing blocks if it does make sense.

  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia Prashant.c Dharamshala

    Prashant.c โ†’ made their first commit to this issueโ€™s fork.

  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia Prashant.c Dharamshala

    @deviantintegral,

    Your handling of blocks and menus in this implementation is exceptionally elegant.

    @ckrina,
    The following tasks have been completed by @deviantintegral; please correct me if I've missed anything:

    1. Created a menu named "Content" using the config file.
    2. Developed two new plugin types: one for "Navigation Block" and the other for "Navigation Section."
    3. src/Plugin/Block/NavigationMenuBlock.php renders the menu links from the "Content" menu.

    While there are various other changes made, for now, I suggest focusing on incorporating the Navigation Block and related code to display "Content" menu links in the sidebar from the backend.

    I am ready to commence integrating the necessary modifications into https://www.drupal.org/project/navigation/issues/3408298 ๐Ÿ“Œ Create the Content menu Needs review

    Thanks!

  • ๐Ÿ‡จ๐Ÿ‡ฆCanada deviantintegral

    Thanks Prashant! I see two next steps depending on your comfort and interest.

    1. Create an issue that does nothing other than create the Content menu, and pull the related code out into that. Don't even worry about displaying the menu; let's just get a menu for Content in that we can reference in future work.
    2. Change the current plugin implementation back to having a totally separate plugin manager from Blocks. Our plugin type should still require that they implement or extend \Drupal\Core\Block\BlockPluginInterface. But, the discovery, namespace, and directory should be separated out again.

    I've had some things come up that will limit my availability for this, so I'm really glad to see you here offering to help. Thanks!

  • ๐Ÿ‡ช๐Ÿ‡ธSpain ckrina Barcelona

    Thanks @deviantintegral for the directions!

    Then work from 1 can be addressed in ๐Ÿ“Œ Create the Content menu Needs review , and this issue can focus on 2.

  • Assigned to m4olivei
  • ๐Ÿ‡จ๐Ÿ‡ฆCanada m4olivei Grimsby, ON

    Will be working on this early next week. I have some things done locally, will aim to get a more complete MR ready.

  • Issue was unassigned.
  • Status changed to Needs review 6 months ago
  • ๐Ÿ‡จ๐Ÿ‡ฆCanada m4olivei Grimsby, ON

    I've pushed up my work. I'm not totally convinced this is done, would appretiate thoughts / opinions. In summary, I have:

    • Brought changes from ๐Ÿ“Œ Create the Content menu Needs review so we have the Content menu created, able to use
    • Converted from Annotations to Attributes, per [#3395582]
    • Adjusted core requirement in info.yml to be ^10.2 for plugin type PHP attribute support
    • As per @deviantintegral, we now have a separate plugin manager, but we use BlockPluginInterface. Our NavigationSection attribute extends from the Block attribute. We also directly use BlockPluginInterface in the NavigationSectionManager. I'm not sure we want this tight coupling? Interested in thoughts around this.
    • Changes required from a plugin usage and implementation standpoint as a result of moving to be Block-like
    • Updated the NavigationContent plugin to use the actual Content menu. It functions similar to NavigationAdmin plugin
  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia Prashant.c Dharamshala

    @m4olivei I tested it manually and seems to be working fine and changes are reflecting properly in the frontend for the following:

    1. Rearrange menu items.
    2. Disabling menu items.
    3. Adding menu items.

  • Status changed to Needs work 6 months ago
  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia Prashant.c Dharamshala

    @m4olivei,

    It appears that the merge request has conflicts. Would you mind checking and resolving them at your convenience?
    Changing the issue status to NW.

    Thank you.

  • ๐Ÿ‡จ๐Ÿ‡ฆCanada m4olivei Grimsby, ON

    Thanks @Prashant.c. I'm expecting more merge conflicts when ๐Ÿ“Œ Create the Content menu Needs review is merged, which feels like it will be soon. Once that lands, I'll sort it all out here.

  • Status changed to Needs review 6 months ago
  • ๐Ÿ‡จ๐Ÿ‡ฆCanada m4olivei Grimsby, ON

    I've resolved the conflicts that the recent merges to 1.x brought.

  • ๐Ÿ‡จ๐Ÿ‡ฆCanada m4olivei Grimsby, ON

    Just to note, Tugboat is not happy ATM b/c I bumped the core_version_requirement to ^10.2. It fails on trying to enable the module b/c of that.

    This shouldn't be an issue b/c we're declaring a tag of q0rban/tugboat-drupal:10 for the Tugboat image. Per the docs that should net us the latest 10.x release (at time of writing 10.2.0). Looks like the images live on DockerHub, and the last tagged images were posted 6 months ago. Latest 10.1.x is 10.1.0 (despite latest being 10.1.7) and there are no 10.2.x tagged images. I've reached out to the Tugboat support folks on this.

  • Status changed to RTBC 6 months ago
  • ๐Ÿ‡จ๐Ÿ‡ฆCanada m4olivei Grimsby, ON

    Thanks @deviantintegral. I've made all the suggested changes.

    I think I could go further here, but it's as good a place as any to stop. I'm thinking that when we start to tackle an admin UI for placing Navigation Sections, we're going to need a new config entity type that is like the block config entity type in order to store config for each instance of a Navigation Section placed. Just like Blocks. The next step in my mind is to create that config entity, and then arrange for navigation module to be installed with the default instances of Navigation Section config entity in the navigation side bar that we have now. But I think that's distinct enough that we're at a good stopping point.

    @ckrina I've marked all threads in the MR with โœ… indicating they are resolved. I don't see any pending feedback from @Prashant.c. Also as a bonus, Tugboat is back in action for this MR! The Tugboat support folks fixed an issue where the Drupal 10.2 images were missing in action.

    Given @deviantintegral's thumbs up, I'll go ahead and mark this as RTBC. Feel free to adjust if I'm overstepping.

  • Status changed to Fixed 6 months ago
  • ๐Ÿ‡ช๐Ÿ‡ธSpain ckrina Barcelona

    Seeing this as RTBC is great news! I understand this can go further but it can happen in follow-ups, so merging this to be sure the follow-ups are easier to address.

    Thanks all!

  • ๐Ÿ‡จ๐Ÿ‡ฆCanada m4olivei Grimsby, ON

    Yay! Thansk @ckrina!

  • Automatically closed - issue fixed for 2 weeks with no activity.

  • Pipeline finished with Success
    4 months ago
    Total: 33s
    #93118
  • Pipeline finished with Success
    4 months ago
    Total: 63s
    #93139
  • Pipeline finished with Success
    4 months ago
    Total: 33s
    #93143
  • Pipeline finished with Success
    4 months ago
    Total: 33s
    #96510
  • Pipeline finished with Success
    4 months ago
    Total: 300s
    #96514
  • Pipeline finished with Success
    3 months ago
    Total: 139s
    #111901
  • Pipeline finished with Success
    3 months ago
    Total: 139s
    #111914
  • Pipeline finished with Failed
    3 months ago
    Total: 609s
    #112048
  • Pipeline finished with Failed
    3 months ago
    Total: 144s
    #112065
  • Pipeline finished with Success
    3 months ago
    Total: 143s
    #112088
  • Pipeline finished with Success
    3 months ago
    Total: 560s
    #112100
Production build 0.69.0 2024