Skip to content
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

Navigation Block: Add submenu chevron w/ setting #19601

Merged
merged 17 commits into from
Jan 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 32 additions & 9 deletions packages/block-library/src/navigation-link/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ import {
ExternalLink,
KeyboardShortcuts,
PanelBody,
Path,
Popover,
SVG,
TextareaControl,
TextControl,
ToggleControl,
Expand All @@ -37,12 +35,18 @@ import {
} from '@wordpress/block-editor';
import { Fragment, useState, useEffect } from '@wordpress/element';

/**
* Internal dependencies
*/
import { toolbarSubmenuIcon, itemSubmenuIcon } from './icons';

function NavigationLinkEdit( {
attributes,
hasDescendants,
isSelected,
isParentOfSelectedBlock,
setAttributes,
showSubmenuIcon,
insertLinkBlock,
} ) {
const { label, opensInNewTab, title, url, nofollow, description } = attributes;
Expand Down Expand Up @@ -93,7 +97,7 @@ function NavigationLinkEdit( {
/>
<ToolbarButton
name="submenu"
icon={ <SVG xmlns="http://www.w3.org/2000/svg" width="24" height="24"><Path d="M14 5h8v2h-8zm0 5.5h8v2h-8zm0 5.5h8v2h-8zM2 11.5C2 15.08 4.92 18 8.5 18H9v2l3-3-3-3v2h-.5C6.02 16 4 13.98 4 11.5S6.02 7 8.5 7H12V5H8.5C4.92 5 2 7.92 2 11.5z" /><Path fill="none" d="M0 0h24v24H0z" /></SVG> }
icon={ toolbarSubmenuIcon }
title={ __( 'Add submenu' ) }
onClick={ insertLinkBlock }
/>
Expand Down Expand Up @@ -150,9 +154,10 @@ function NavigationLinkEdit( {
'has-link': !! url,
} ) }
>
<div>
<div className="wp-block-navigation-link__content">
<RichText
className="wp-block-navigation-link__content"
tagName="span"
className="wp-block-navigation-link__label"
value={ label }
onChange={ ( labelValue ) => setAttributes( { label: labelValue } ) }
placeholder={ itemLabelPlaceholder }
Expand All @@ -164,6 +169,11 @@ function NavigationLinkEdit( {
'core/strikethrough',
] }
/>
{ showSubmenuIcon &&
<span className="wp-block-navigation-link__submenu-icon">
{ itemSubmenuIcon }
</span>
}
{ isLinkOpen && (
<Popover position="bottom center">
<LinkControl
Expand Down Expand Up @@ -208,13 +218,26 @@ function NavigationLinkEdit( {

export default compose( [
withSelect( ( select, ownProps ) => {
const { getClientIdsOfDescendants, hasSelectedInnerBlock } = select( 'core/block-editor' );
const {
getBlockName,
getBlockAttributes,
getBlockParents,
getClientIdsOfDescendants,
hasSelectedInnerBlock,
} = select( 'core/block-editor' );
const { clientId } = ownProps;
const rootBlock = getBlockParents( clientId )[ 0 ];
const parentBlock = getBlockParents( clientId, true )[ 0 ];
const rootBlockAttributes = getBlockAttributes( rootBlock );
const hasDescendants = !! getClientIdsOfDescendants( [ clientId ] ).length;
const isLevelZero = getBlockName( parentBlock ) === 'core/navigation';
const showSubmenuIcon = rootBlockAttributes.showSubmenuIcon && isLevelZero && hasDescendants;
WunderBart marked this conversation as resolved.
Show resolved Hide resolved
const isParentOfSelectedBlock = hasSelectedInnerBlock( clientId, true );

return {
isParentOfSelectedBlock: hasSelectedInnerBlock( clientId, true ),
WunderBart marked this conversation as resolved.
Show resolved Hide resolved
hasDescendants: !! getClientIdsOfDescendants( [ clientId ] ).length,

isParentOfSelectedBlock,
hasDescendants,
showSubmenuIcon,
};
} ),
withDispatch( ( dispatch, ownProps, registry ) => {
Expand Down
42 changes: 10 additions & 32 deletions packages/block-library/src/navigation-link/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,6 @@
min-height: $icon-button-size;
}

.wp-block-navigation-link__edit-container {
display: flex;
white-space: nowrap;

// Compensate for navigation link base padding.
margin-left: -$grid-size;

.wp-block-navigation-link__content {
margin-right: $grid-size;

// This should match the padding of the navigation link.
padding: 0 $grid-size;

// This make it look like an input field.
// We may want to not style this at all, but let's try this.
// We don't use the mixins because they increase the size of the input, which doesn't work with PlainText.
box-shadow: inset 0 0 0 1px $dark-gray-200;
transition: box-shadow 0.1s linear;
border-radius: $radius-round-rectangle;
@include reduce-motion("transition");

&:focus {
color: $dark-gray-900;
box-shadow: inset 0 0 0 2px $blue-medium-focus;

// Windows High Contrast mode will show this outline, but not the box-shadow.
outline: 2px solid transparent;
}
}
}

/*
* Adjust Navigation Item.
*/
Expand Down Expand Up @@ -69,10 +38,19 @@
display: block;
}

&.has-link .wp-block-navigation-link__content {
.wp-block-navigation-link__content {
display: flex;
align-items: center;
}

&.has-link .wp-block-navigation-link__label {
text-decoration: underline;
}

.wp-block-navigation-link__submenu-icon {
margin-left: 4px;
}

.block-editor-rich-text__editable.is-selected:not(.keep-placeholder-on-focus):not(:focus) [data-rich-text-placeholder]::after {
display: inline-block;
}
Expand Down
17 changes: 17 additions & 0 deletions packages/block-library/src/navigation-link/icons.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* WordPress dependencies
*/
import { Polygon, Path, SVG } from '@wordpress/components';

export const toolbarSubmenuIcon = (
<SVG xmlns="http://www.w3.org/2000/svg" width="24" height="24">
<Path d="M14 5h8v2h-8zm0 5.5h8v2h-8zm0 5.5h8v2h-8zM2 11.5C2 15.08 4.92 18 8.5 18H9v2l3-3-3-3v2h-.5C6.02 16 4 13.98 4 11.5S6.02 7 8.5 7H12V5H8.5C4.92 5 2 7.92 2 11.5z" />
<Path fill="none" d="M0 0h24v24H0z" />
</SVG>
);

export const itemSubmenuIcon = (
<SVG width="18" height="18" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 18">
<Polygon points="9,13.5 14.7,7.9 13.2,6.5 9,10.7 4.8,6.5 3.3,7.9 " />
</SVG>
);
14 changes: 14 additions & 0 deletions packages/block-library/src/navigation/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
PanelBody,
Placeholder,
Spinner,
ToggleControl,
Toolbar,
ToolbarGroup,
} from '@wordpress/components';
Expand Down Expand Up @@ -216,6 +217,19 @@ function Navigation( {
</PanelBody>
</InspectorControls>
{ InspectorControlsColorPanel }
<InspectorControls>
<PanelBody
title={ __( 'Display Settings' ) }
>
<ToggleControl
checked={ attributes.showSubmenuIcon }
onChange={ ( value ) => {
setAttributes( { showSubmenuIcon: value } );
} }
label={ __( 'Show submenu icon for top-level items' ) }
/>
</PanelBody>
</InspectorControls>
<TextColor>
<BackgroundColor>
<div
Expand Down
48 changes: 37 additions & 11 deletions packages/block-library/src/navigation/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,15 @@ function( $block ) {
return $blocks;
}

/**
* Returns the top-level submenu SVG chevron icon.
*
* @return string
*/
function render_submenu_icon() {
return '<svg width="18" height="18" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 18" role="img" aria-hidden="true" focusable="false"><polygon points="9,13.5 14.7,7.9 13.2,6.5 9,10.7 4.8,6.5 3.3,7.9 "></polygon></svg>';
}

/**
* Renders the `core/navigation` block on server.
*
Expand Down Expand Up @@ -145,21 +154,22 @@ function render_block_navigation( $attributes, $content, $block ) {
'<nav %1$s %2$s>%3$s</nav>',
$class_attribute,
$style_attribute,
build_navigation_html( $block, $colors, $font_sizes )
build_navigation_html( $attributes, $block, $colors, $font_sizes, true )
);
}

/**
* Walks the inner block structure and returns an HTML list for it.
*
* @param array $block The block.
* @param array $colors Contains inline styles and CSS classes to apply to navigation item.
* @param array $font_sizes Contains inline styles and CSS classes to apply to navigation item.
* @param bool $level_zero True whether is main menu (level zero). Otherwise, False.
* @param array $attributes The Navigation block attributes.
* @param array $block The NavigationItem block.
* @param array $colors Contains inline styles and CSS classes to apply to navigation item.
* @param array $font_sizes Contains inline styles and CSS classes to apply to navigation item.
* @param bool $is_level_zero True whether is main menu (level zero). Otherwise, False.
*
* @return string Returns an HTML list from innerBlocks.
*/
function build_navigation_html( $block, $colors, $font_sizes, $level_zero = true ) {
function build_navigation_html( $attributes, $block, $colors, $font_sizes, $is_level_zero = true ) {
$html = '';
$classes = array_merge(
$colors['css_classes'],
Expand All @@ -172,11 +182,12 @@ function build_navigation_html( $block, $colors, $font_sizes, $level_zero = true
: '';

foreach ( (array) $block['innerBlocks'] as $key => $block ) {
$has_submenu = count( (array) $block['innerBlocks'] ) > 0;

$html .= '<li class="wp-block-navigation-link">' .
$html .= '<li class="wp-block-navigation-link' . ( $has_submenu ? ' has-submenu' : '' ) . '">' .
'<a';

if ( $level_zero ) {
if ( $is_level_zero ) {
$html .= $class_attribute . $style_attribute;
}

Expand All @@ -194,7 +205,10 @@ function build_navigation_html( $block, $colors, $font_sizes, $level_zero = true
// End appending HTML attributes to anchor tag.

// Start anchor tag content.
$html .= '>';
$html .= '>' .
// Wrap title with span to isolate it from submenu icon.
'<span class="wp-block-navigation-link__label">';

if ( isset( $block['attrs']['label'] ) ) {
$html .= wp_kses(
$block['attrs']['label'],
Expand All @@ -216,11 +230,19 @@ function build_navigation_html( $block, $colors, $font_sizes, $level_zero = true
)
);
}

$html .= '</span>';

// Append submenu icon to top-level item.
if ( $attributes['showSubmenuIcon'] && $is_level_zero && $has_submenu ) {
$html .= '<span class="wp-block-navigation-link__submenu-icon">' . render_submenu_icon() . '</span>';
WunderBart marked this conversation as resolved.
Show resolved Hide resolved
}

$html .= '</a>';
// End anchor tag content.

if ( count( (array) $block['innerBlocks'] ) > 0 ) {
$html .= build_navigation_html( $block, $colors, $font_sizes, false );
if ( $has_submenu ) {
$html .= build_navigation_html( $attributes, $block, $colors, $font_sizes, false );
}

$html .= '</li>';
Expand Down Expand Up @@ -264,6 +286,10 @@ function register_block_core_navigation() {
'itemsJustification' => array(
'type' => 'string',
),
'showSubmenuIcon' => array(
'type' => 'boolean',
'default' => false,
),
),

'render_callback' => 'render_block_navigation',
Expand Down
23 changes: 11 additions & 12 deletions packages/block-library/src/navigation/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,12 @@
}
}

// ToDo: move navigation-link styles to navigation-link/style.scss
& > li {

& > a {
display: flex;
align-items: center;
padding-left: 0;

@include break-small {
Expand All @@ -54,6 +57,14 @@
&:last-of-type > a {
padding-right: 0;
}

.wp-block-navigation-link__submenu-icon {
margin-left: 4px;

svg {
fill: currentColor;
}
}
}

// Sub-menus Flyout
Expand Down Expand Up @@ -149,18 +160,6 @@
}
}

// Top-level sub-menu indicators
& .has-sub-menu > a {

&::after {
content: "\00a0\25BC";
display: inline-block;
font-size: 0.6rem;
height: inherit;
width: inherit;
}
}

&.items-justified-left > ul {
justify-content: flex-start;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

exports[`Navigation allows a navigation menu to be created from an empty menu using a mixture of internal and external links 1`] = `
"<!-- wp:navigation -->
<!-- wp:navigation-link {\\"label\\":\\"WP\\",\\"title\\":\\"https://wordpress.org\\",\\"url\\":\\"https://wordpress.org\\"} /-->
<!-- wp:navigation-link {\\"label\\":\\"WP\\",\\"title\\":\\"https://wordpress.org\\",\\"id\\":\\"-1\\",\\"url\\":\\"https://wordpress.org\\"} /-->

<!-- wp:navigation-link {\\"label\\":\\"Get in touch\\",\\"title\\":\\"Contact Us\\",\\"url\\":\\"https://this/is/a/test/url/contact-us\\"} /-->
<!-- wp:navigation-link {\\"label\\":\\"Get in touch\\",\\"title\\":\\"Contact Us\\",\\"id\\":1,\\"url\\":\\"https://this/is/a/test/url/contact-us\\"} /-->
<!-- /wp:navigation -->"
`;

Expand Down
2 changes: 1 addition & 1 deletion packages/e2e-tests/specs/editor/blocks/navigation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ async function updateActiveNavigationLink( { url, label } ) {
}

if ( label ) {
await page.click( '.wp-block-navigation-link__content.is-selected' );
await page.click( '.wp-block-navigation-link__label.is-selected' );

// Ideally this would be `await pressKeyWithModifier( 'primary', 'a' )`
// to select all text like other tests do.
Expand Down