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

Add navigation menu blocks #14856

Merged
merged 2 commits into from Jun 18, 2019
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/block-library/src/editor.scss
Expand Up @@ -18,6 +18,8 @@
@import "./media-text/editor.scss";
@import "./list/editor.scss";
@import "./more/editor.scss";
@import "./navigation-menu/editor.scss";
@import "./navigation-menu-item/editor.scss";
@import "./nextpage/editor.scss";
@import "./paragraph/editor.scss";
@import "./preformatted/editor.scss";
Expand Down
4 changes: 4 additions & 0 deletions packages/block-library/src/index.js
Expand Up @@ -33,6 +33,8 @@ import * as embed from './embed';
import * as file from './file';
import * as html from './html';
import * as mediaText from './media-text';
import * as navigationMenu from './navigation-menu';
import * as navigationMenuItem from './navigation-menu-item';
import * as latestComments from './latest-comments';
import * as latestPosts from './latest-posts';
import * as legacyWidget from './legacy-widget';
Expand Down Expand Up @@ -104,6 +106,8 @@ export const registerCoreBlocks = () => {
process.env.GUTENBERG_PHASE === 2 ? legacyWidget : null,
missing,
more,
process.env.GUTENBERG_PHASE === 2 ? navigationMenu : null,
process.env.GUTENBERG_PHASE === 2 ? navigationMenuItem : null,
nextpage,
preformatted,
pullquote,
Expand Down
26 changes: 26 additions & 0 deletions packages/block-library/src/navigation-menu-item/block.json
@@ -0,0 +1,26 @@
{
"name": "core/navigation-menu-item",
"category": "layout",
"attributes": {
"label": {
"type": "string"
},
"destination": {
"type": "string"
},
"nofollow": {
"type": "boolean",
"default": false
},
"title": {
"type": "string"
},
"description": {
"type": "string"
},
"opensInNewTab": {
"type": "boolean",
"default": false
}
}
}
145 changes: 145 additions & 0 deletions packages/block-library/src/navigation-menu-item/edit.js
@@ -0,0 +1,145 @@
/**
* External dependencies
*/
import { invoke } from 'lodash';

/**
* WordPress dependencies
*/
import {
Dropdown,
ExternalLink,
IconButton,
PanelBody,
TextareaControl,
TextControl,
ToggleControl,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import {
InspectorControls,
PlainText,
} from '@wordpress/block-editor';
import {
Fragment,
useCallback,
useRef,
} from '@wordpress/element';

/**
* Internal dependencies
*/
import MenuItemActions from './menu-item-actions';
const POPOVER_PROPS = { noArrow: true };

function NavigationMenuItemEdit( {
attributes,
clientId,
isSelected,
setAttributes,
} ) {
const plainTextRef = useRef( null );
const onEditLableClicked = useCallback(
( onClose ) => () => {
onClose();
invoke( plainTextRef, [ 'current', 'textarea', 'focus' ] );
},
[ plainTextRef ]
);
let content;
if ( isSelected ) {
content = (
<div className="wp-block-navigation-menu-item__edit-container">
<PlainText
ref={ plainTextRef }
className="wp-block-navigation-menu-item__field"
value={ attributes.label }
onChange={ ( label ) => setAttributes( { label } ) }
aria-label={ __( 'Navigation Label' ) }
maxRows={ 1 }
/>
<Dropdown
contentClassName="wp-block-navigation-menu-item__dropdown-content"
position="bottom left"
popoverProps={ POPOVER_PROPS }
renderToggle={ ( { isOpen, onToggle } ) => (
<IconButton
icon={ isOpen ? 'arrow-up-alt2' : 'arrow-down-alt2' }
label={ __( 'More options' ) }
onClick={ onToggle }
aria-expanded={ isOpen }
/>
) }
renderContent={ ( { onClose } ) => (
<MenuItemActions
clientId={ clientId }
destination={ attributes.destination }
onEditLableClicked={ onEditLableClicked( onClose ) }
/>
) }
/>
</div>
);
} else {
content = attributes.label;
}
return (
<Fragment>
<InspectorControls>
<PanelBody
title={ __( 'Menu Settings' ) }
>
<ToggleControl
checked={ attributes.opensInNewTab }
onChange={ ( opensInNewTab ) => {
setAttributes( { opensInNewTab } );
} }
label={ __( 'Open in new tab' ) }
/>
<TextareaControl
value={ attributes.description || '' }
onChange={ ( description ) => {
setAttributes( { description } );
} }
label={ __( 'Description' ) }
/>
</PanelBody>
<PanelBody
title={ __( 'SEO Settings' ) }
>
<TextControl
value={ attributes.title || '' }
onChange={ ( title ) => {
setAttributes( { title } );
} }
label={ __( 'Title Attribute' ) }
help={ __( 'Provide more context about where the link goes.' ) }
/>
<ToggleControl
checked={ attributes.nofollow }
onChange={ ( nofollow ) => {
setAttributes( { nofollow } );
} }
label={ __( 'Add nofollow to menu item' ) }
help={ (
<Fragment>
{ __( 'Don\'t let search engines follow this link.' ) }
<ExternalLink
className="wp-block-navigation-menu-item__nofollow-external-link"
href={ __( 'https://codex.wordpress.org/Nofollow' ) }
>
{ __( 'What\'s this?' ) }
</ExternalLink>
</Fragment>
) }
/>
</PanelBody>
</InspectorControls>
<div className="wp-block-navigation-menu-item">
{ content }
</div>
</Fragment>
);
}

export default NavigationMenuItemEdit;
72 changes: 72 additions & 0 deletions packages/block-library/src/navigation-menu-item/editor.scss
@@ -0,0 +1,72 @@
.wp-block-navigation-menu-item__edit-container {
display: grid;
grid-auto-columns: min-content;
grid-auto-flow: column;
align-items: center;
white-space: nowrap;
}

$menu-label-field-width: 140px;
.wp-block-navigation-menu-item__edit-container {
border: 1px solid $light-gray-500;
// two pixes comes from two times one pixel border
width: $menu-label-field-width + $icon-button-size + 2px;
padding-left: 1px;
}

.wp-block-navigation-menu-item__edit-container .wp-block-navigation-menu-item__field {
border-right: 1px solid $light-gray-500 !important;
width: $menu-label-field-width;
border: none;
border-radius: 0;
padding-left: $grid-size-large;

min-height: $icon-button-size - 1px;
line-height: $icon-button-size - 1px;

&,
&:focus {
color: $dark-gray-500;
}
}


.wp-block-navigation-menu-item {
font-family: $editor-font;
color: #0073af;
font-weight: bold;
font-size: $text-editor-font-size;
}

.wp-block-navigation-menu-item__nofollow-external-link {
display: block;
}

// Separator
.wp-block-navigation-menu-item__separator {
margin-top: $grid-size;
margin-bottom: $grid-size;
margin-left: 0;
margin-right: 0;
border-top: $border-width solid $light-gray-500;
}

// Popover styles
.components-popover:not(.is-mobile).wp-block-navigation-menu-item__dropdown-content {
margin-top: -1px;
margin-left: -4px;
}

.wp-block-navigation-menu-item__dropdown-content .components-popover__content {
padding: $grid-size 0;
}

.wp-block-navigation-menu .block-editor-block-list__block[data-type="core/navigation-menu-item"] {
& > .block-editor-block-list__block-edit > div[role="toolbar"] {
display: none;
}

& > .block-editor-block-list__insertion-point {
display: none;
}
}
28 changes: 28 additions & 0 deletions packages/block-library/src/navigation-menu-item/index.js
@@ -0,0 +1,28 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import metadata from './block.json';
import edit from './edit';
import save from './save';

const { name } = metadata;
export { metadata, name };

export const settings = {
title: __( 'Menu Item (Experimental)' ),

parent: [ 'core/navigation-menu' ],

icon: 'admin-links',

description: __( 'Add a page, link, or other item to your Navigation Menu.' ),

edit,
save,
};