-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Augment and improve Nav Editor (and block) documentation #31891
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
0de466c
Document different editor save and render modes
getdave ec06356
Add code references and correct grammar
getdave e2dfc0b
Tidy unrequired sentances
getdave 04f049d
Document menu item to block attribute mapping
getdave 164314c
Bring mappings adjacent to each other. Improve documenting inconsiste…
getdave 24e92b7
Add helpful links
getdave 9be12e7
Quick ref to the block
getdave b7441f4
Seperate out the colophon
getdave File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,103 @@ import blockEditorSettings from './block-editor-settings'; | |
initialize( '#navigation-editor-root', blockEditorSettings ); | ||
``` | ||
|
||
## Purpose | ||
|
||
By default, the Navigation Editor screen allows users to create and edit complex navigations using a block-based UI. The aim is to supercede [the current Menus screen](https://codex.wordpress.org/WordPress_Menu_User_Guide) by providing a superior experience whilst retaining backwards compatibility. | ||
|
||
The editing experience is provided as a block editor wrapper around the core functionality of the **Navigation _block_**. Features of the block are disabled/enhanced as necessary to provide an experience appropriate to editing a navigation outside of a Full Site Editing context. | ||
|
||
## Modes | ||
|
||
The Navigation Editor has two "modes" for _persistence_ ("saving" navigations) and _rendering_: | ||
|
||
1. **Default** - navigations are saved to the _existing_ (post type powered) Menus system and rendered using standard Walker classes. | ||
2. **Block-based** (opt _in_) - navigations continue to be _saved_ using the existing post type system, but non-link blocks are saved (see technical implementation) and _rendered_ as blocks to provide access to the full power of the Navigation block (with some tradeoffs in terms of backwards compatibility). | ||
|
||
### Default Mode | ||
|
||
In this mode, navigations created in the Navigation Editor are stored using the _existing Menu post type_ (`nav_menu_item`) system. As this method matches that used in the _existing_ Menus screen, there is a smooth upgrade path to using new Navigation Editor screen to edit navigations. | ||
|
||
Moreover, when the navigation is rendered on the front of the site the system continues to use [the classic Navigation "Walker" class](https://developer.wordpress.org/reference/classes/walker_nav_menu/), thereby ensuring the HTML markup remains the same when using a classic Theme. | ||
|
||
### Block-based Mode | ||
|
||
If desired, themes are able to opt into _rendering_ complete block-based menus using the Navigation Editor. This allows for arbitrarily complex navigation block structures to be used in an existing theme whilst still ensuring the navigation data is still _saved_ to the existing (post type powered) Menus system. | ||
|
||
Themes can opt into this behaviour by declaring: | ||
|
||
```php | ||
add_theme_support( 'block-nav-menus' ); | ||
``` | ||
|
||
This unlocks significant additional capabilities in the Navigation Editor. For example, by default, [the Navigation Editor screen only allows _link_ (`core/navigation-link`) blocks to be inserted into a navigation](https://github.com/WordPress/gutenberg/blob/7fcd57c9a62c232899e287f6d96416477d810d5e/packages/edit-navigation/src/filters/disable-inserting-non-navigation-blocks.js). When a theme opts into `block-nav-menus` however, users are able to add non-link blocks to a navigation using the Navigation Editor screen, including: | ||
|
||
- `core/navigation-link`. | ||
- `core/social`. | ||
- `core/search`. | ||
|
||
#### Technical Implementation details | ||
|
||
By default, `core/navigation-link` items are serialized and persisted as `nav_menu_item` posts. No serialized block HTML is stored for these standard link blocks. | ||
|
||
_Non_-link navigation items however, are [persisted as `nav_menu_items` with a special `type` of `block`](https://github.com/WordPress/gutenberg/blob/7fcd57c9a62c232899e287f6d96416477d810d5e/packages/edit-navigation/src/store/utils.js#L159-L166). These items have an [_additional_ `content` field which is used to store the serialized block markup](https://github.com/WordPress/gutenberg/blob/7fcd57c9a62c232899e287f6d96416477d810d5e/lib/navigation.php#L71-L101). | ||
|
||
When rendered on the front-end, the blocks are [`parse`d from the `content` field](https://github.com/WordPress/gutenberg/blob/7fcd57c9a62c232899e287f6d96416477d810d5e/lib/navigation.php#L191-L203) and [rendered as blocks](https://github.com/WordPress/gutenberg/blob/7fcd57c9a62c232899e287f6d96416477d810d5e/lib/navigation.php#L103-L135). | ||
|
||
If the user switches to a theme that does not support block menus, or disables this functionality, non-link blocks are no longer rendered on the frontend. Care is taken, however, to ensure that users can still see their data on the existing Menus screen. | ||
|
||
## Block to Menu Item mapping | ||
|
||
The Navigation Editor needs to be able to map navigation items in two directions: | ||
|
||
1. `nav_menu_item`s to Blocks - when displaying an existing navigation. | ||
2. Blocks to `nav_menu_item`s - when _saving_ an navigation being editing in the Navigation screen. | ||
|
||
The Navigation Editor has two dedicated methods for handling mapping between these two expressions of the data: | ||
|
||
- [`menuItemToBlockAttributes()`](https://github.com/WordPress/gutenberg/blob/7fcd57c9a62c232899e287f6d96416477d810d5e/packages/edit-navigation/src/store/utils.js#L261-L313). | ||
- [`blockAttributestoMenuItem()`](https://github.com/WordPress/gutenberg/blob/7fcd57c9a62c232899e287f6d96416477d810d5e/packages/edit-navigation/src/store/utils.js#L184-L253) | ||
|
||
To understand these fully, one must appreciate that WordPress maps raw `nav_menu_item` posts to [Menu item _objects_](https://core.trac.wordpress.org/browser/tags/5.7.1/src/wp-includes/nav-menu.php#L786). These have various properties which map as follows: | ||
|
||
| Menu Item object property | Equivalent Block Attribute | Description | | ||
| :------------------------ | :----------------------------------------------------: | :-------------------------------------------------------------------------------------------------------: | | ||
| `ID` | Not mapped. | The term_id if the menu item represents a taxonomy term. | | ||
| `attr_title` | `title` | The title attribute of the link element for this menu item. | | ||
| `classes` | `classNames` | The array of class attribute values for the link element of this menu item. | | ||
| `db_id` | Not mapped. | The DB ID of this item as a nav_menu_item object, if it exists (0 if it doesn't exist). | | ||
| `description` | `description` | The description of this menu item. | | ||
| `menu_item_parent` | Not mapped.<sup>[1](#menu_item_menu_item_parent)</sup> | The DB ID of the nav_menu_item that is this item's menu parent, if any. 0 otherwise. | | ||
| `object` | `type` | The type of object originally represented, such as 'category', 'post', or 'attachment'. | | ||
| `object_id` | `id` | The DB ID of the original object this menu item represents, e.g. ID for posts and term_id for categories. | | ||
| `post_parent` | Not mapped. | The DB ID of the original object's parent object, if any (0 otherwise). | | ||
| `post_title` | Not mapped. | A "no title" label if menu item represents a post that lacks a title. | | ||
| `target` | `opensInNewTab`<sup>[2](#menu_item_target)</sup> | The target attribute of the link element for this menu item. | | ||
| `title` | `label` | The title of this menu item. | | ||
| `type` | `kind` | The family of objects originally represented, such as 'post_type' or 'taxonomy'. | | ||
| `type_label` | Not mapped. | The singular label used to describe this type of menu item. | | ||
| `url` | `url` | The URL to which this menu item points. | | ||
| `xfn` | `rel` | The XFN relationship expressed in the link of this menu item. | | ||
| `\_invalid` | Not mapped. | Whether the menu item represents an object that no longer exists. | | ||
|
||
- [<a name="menu_item_menu_item_parent">1</a>] - the parent -> child relationship is expressed in block via the `innerBlocks` attribute and is therefore not required as a explicit block attribute. | ||
- [<a name="menu_item_target">2</a>] - applies only if the value of the `target` field is `_blank`. | ||
|
||
### Inconsistencies | ||
|
||
#### Mapping | ||
|
||
For historical reasons, the following properties display some inconsistency in their mapping from Menu Item Object to Block attribute: | ||
|
||
- `type` -> `kind` - the family of objects is stored as `kind` on the block and so must be mapped accordingly. | ||
- `object` -> `type` - the type of object is stored as `type` on the block and so must be mapped accordingly. | ||
- `object_id` -> `id` - the block stores a reference to the original object's ID as the `id` _attribute_. This should not be confused with the block's `clientId` which is unrelated. | ||
- `attr_title` -> `title` - the HTML `title` attribute is stored as `title` on the block and so must be mapped accordingly. | ||
|
||
#### Object Types | ||
|
||
- Menu Item objects which represent "Tags" are stored in WordPress as `post_tag` but the block expects their `type` attribute to be `tag` (omiting the `post_` suffix). This inconsistency is accounted for in [the mapping utilities methods](https://github.com/WordPress/gutenberg/blob/7fcd57c9a62c232899e287f6d96416477d810d5e/packages/edit-navigation/src/store/utils.js#L279-L281). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As an aside, I think we can still change this to prefer |
||
|
||
## Hooks | ||
|
||
`useMenuItems` and `useNavigationBlock` hooks are the central part of this package. They bridge the gap between the API and the block editor interface: | ||
|
@@ -59,6 +156,13 @@ return ( | |
); | ||
``` | ||
|
||
## Glossary | ||
|
||
- **Link block** - the basic `core/navigation-link` block which is the standard block used to add links within navigations. | ||
- **Navigation block** - the root `core/navigation` block which can be used both with the Navigation Editor and outside (eg: Post / Site Editor). | ||
- **Navigation editor / screen** - the new screen provided by Gutenberg to allow the user to edit navigations using a block-based UI. | ||
- **Menus screen** - the current/existing [interface/screen for managing Menus](https://codex.wordpress.org/WordPress_Menu_User_Guide) in WordPress WPAdmin. | ||
|
||
_This package assumes that your code will run in an **ES2015+** environment. If you're using an environment that has limited or no support for ES2015+ such as IE browsers then using [core-js](https://github.com/zloirock/core-js) will add polyfills for these methods._ | ||
|
||
<br/><br/><p align="center"><img src="https://s.w.org/style/images/codeispoetry.png?1" alt="Code is Poetry." /></p> |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Non-blocking note: I think this is useful to walk through, along with the table below, but I also wanted to note that docs here are pretty likely to get out of sync over time. Probably not worth automating, until things are more finalized for navigation but just something to keep in mind 🤔
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.
One other thing that might help might be some sort of diagram/table of the backing stores, rather than pointing to the conversion code.