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

NUX: Move first tip to the toolbar #9223

Merged
merged 3 commits into from
Aug 24, 2018
Merged
Show file tree
Hide file tree
Changes from 2 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
7 changes: 6 additions & 1 deletion edit-post/components/header/header-toolbar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { compose } from '@wordpress/compose';
import { withSelect } from '@wordpress/data';
import { withViewportMatch } from '@wordpress/viewport';
import { DotTip } from '@wordpress/nux';

/**
* WordPress dependencies
Expand All @@ -29,7 +30,11 @@ function HeaderToolbar( { hasFixedToolbar, isLargeViewport } ) {
className="edit-post-header-toolbar"
aria-label={ __( 'Editor Toolbar' ) }
>
<Inserter position="bottom right" />
<Inserter position="bottom right">
<DotTip id="core/editor.inserter">
{ __( 'Welcome to the wonderful world of blocks! Click the “+” (“Add block”) button to add a new block. There are blocks available for all kind of content: you can insert text, headings, images, lists, and lots more!' ) }
</DotTip>
</Inserter>
<EditorHistoryUndo />
<EditorHistoryRedo />
<TableOfContents />
Expand Down
8 changes: 5 additions & 3 deletions packages/components/src/popover/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,7 @@ class Popover extends Component {
window.console.warn( `<Popover> component: focusOnMount argument "${ focusOnMount }" not recognized.` );
}

getAnchorRect() {
const anchor = this.anchorNode.current;
getAnchorRect( anchor ) {
if ( ! anchor || ! anchor.parentNode ) {
return;
}
Expand Down Expand Up @@ -185,7 +184,10 @@ class Popover extends Component {
computePopoverPosition( popoverSize ) {
const { getAnchorRect = this.getAnchorRect, position = 'top', expandOnMobile } = this.props;
const newPopoverPosition = computePopoverPosition(
getAnchorRect(), popoverSize || this.state.popoverSize, position, expandOnMobile
getAnchorRect( this.anchorNode.current ),
popoverSize || this.state.popoverSize,
position,
expandOnMobile
);

if (
Expand Down
25 changes: 3 additions & 22 deletions packages/editor/src/components/default-block-appender/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/**
* External dependencies
*/
import classnames from 'classnames';
import { get } from 'lodash';

/**
Expand All @@ -12,7 +11,6 @@ import { compose } from '@wordpress/compose';
import { getDefaultBlockName } from '@wordpress/blocks';
import { decodeEntities } from '@wordpress/html-entities';
import { withSelect, withDispatch } from '@wordpress/data';
import { DotTip } from '@wordpress/nux';

/**
* Internal dependencies
Expand All @@ -29,7 +27,6 @@ export function DefaultBlockAppender( {
placeholder,
layout,
rootClientId,
hasTip,
} ) {
if ( isLocked || ! isVisible ) {
return null;
Expand All @@ -51,11 +48,7 @@ export function DefaultBlockAppender( {
// See: https://gist.github.com/cvrebert/68659d0333a578d75372

return (
<div
data-root-client-id={ rootClientId || '' }
className={ classnames( 'editor-default-block-appender', {
'has-tip': hasTip,
} ) }>
<div data-root-client-id={ rootClientId || '' } className="editor-default-block-appender">
<BlockDropZone rootClientId={ rootClientId } layout={ layout } />
<input
role="button"
Expand All @@ -67,18 +60,13 @@ export function DefaultBlockAppender( {
value={ showPrompt ? value : '' }
/>
<InserterWithShortcuts rootClientId={ rootClientId } layout={ layout } />
<Inserter position="top right">
<DotTip id="core/editor.inserter">
{ __( 'Welcome to the wonderful world of blocks! Click the “+” (“Add block”) button to add a new block. There are blocks available for all kind of content: you can insert text, headings, images, lists, and lots more!' ) }
</DotTip>
</Inserter>
<Inserter position="top right" />
</div>
);
}
export default compose(
withSelect( ( select, ownProps ) => {
const { getBlockCount, getBlock, getEditorSettings, getTemplateLock } = select( 'core/editor' );
const { isTipVisible } = select( 'core/nux' );

const isEmpty = ! getBlockCount( ownProps.rootClientId );
const lastBlock = getBlock( ownProps.lastBlockClientId );
Expand All @@ -90,7 +78,6 @@ export default compose(
showPrompt: isEmpty,
isLocked: !! getTemplateLock( ownProps.rootClientId ),
placeholder: bodyPlaceholder,
hasTip: isTipVisible( 'core/editor.inserter' ),
};
} ),
withDispatch( ( dispatch, ownProps ) => {
Expand All @@ -99,11 +86,9 @@ export default compose(
startTyping,
} = dispatch( 'core/editor' );

const { dismissTip } = dispatch( 'core/nux' );

return {
onAppend() {
const { layout, rootClientId, hasTip } = ownProps;
const { layout, rootClientId } = ownProps;

let attributes;
if ( layout ) {
Expand All @@ -112,10 +97,6 @@ export default compose(

insertDefaultBlock( attributes, rootClientId );
startTyping();

if ( hasTip ) {
dismissTip( 'core/editor.inserter' );
}
},
};
} ),
Expand Down
16 changes: 7 additions & 9 deletions packages/editor/src/components/default-block-appender/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,15 @@
}
}

&:hover .editor-inserter-with-shortcuts {
opacity: 1;
// Don't show the inserter until mousing over.
.editor-inserter__toggle:not([aria-expanded="true"]) {
opacity: 0;
}

// Show the inserter if mousing over or there is a tip.
&:not(.has-tip) {
.editor-inserter__toggle:not([aria-expanded="true"]) {
opacity: 0;
&:hover {
.editor-inserter-with-shortcuts {
opacity: 1;
}

&:hover .editor-inserter__toggle {
.editor-inserter__toggle {
opacity: 1;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,7 @@ exports[`DefaultBlockAppender should append a default block when input focused 1
<WithSelect(WithDispatch(InserterWithShortcuts)) />
<WithSelect(WithDispatch(Inserter))
position="top right"
>
<WithInstanceId(WithSelect(WithDispatch(DotTip)))
id="core/editor.inserter"
>
Welcome to the wonderful world of blocks! Click the “+” (“Add block”) button to add a new block. There are blocks available for all kind of content: you can insert text, headings, images, lists, and lots more!
</WithInstanceId(WithSelect(WithDispatch(DotTip)))>
</WithSelect(WithDispatch(Inserter))>
/>
</div>
`;

Expand All @@ -53,13 +47,7 @@ exports[`DefaultBlockAppender should match snapshot 1`] = `
<WithSelect(WithDispatch(InserterWithShortcuts)) />
<WithSelect(WithDispatch(Inserter))
position="top right"
>
<WithInstanceId(WithSelect(WithDispatch(DotTip)))
id="core/editor.inserter"
>
Welcome to the wonderful world of blocks! Click the “+” (“Add block”) button to add a new block. There are blocks available for all kind of content: you can insert text, headings, images, lists, and lots more!
</WithInstanceId(WithSelect(WithDispatch(DotTip)))>
</WithSelect(WithDispatch(Inserter))>
/>
</div>
`;

Expand All @@ -81,12 +69,6 @@ exports[`DefaultBlockAppender should optionally show without prompt 1`] = `
<WithSelect(WithDispatch(InserterWithShortcuts)) />
<WithSelect(WithDispatch(Inserter))
position="top right"
>
<WithInstanceId(WithSelect(WithDispatch(DotTip)))
id="core/editor.inserter"
>
Welcome to the wonderful world of blocks! Click the “+” (“Add block”) button to add a new block. There are blocks available for all kind of content: you can insert text, headings, images, lists, and lots more!
</WithInstanceId(WithSelect(WithDispatch(DotTip)))>
</WithSelect(WithDispatch(Inserter))>
/>
</div>
`;
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ exports[`PostPreviewButton render() should match the snapshot 1`] = `
onClick={[Function]}
>
Preview
<WithInstanceId(WithSelect(WithDispatch(DotTip)))
<WithSelect(WithDispatch(DotTip))
id="core/editor.preview"
>
Click “Preview” to load a preview of this page, so you can make sure you’re happy with your blocks.
</WithInstanceId(WithSelect(WithDispatch(DotTip)))>
</WithSelect(WithDispatch(DotTip))>
</Button>
`;
4 changes: 1 addition & 3 deletions packages/nux/src/components/dot-tip/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ DotTip

`DotTip` is a React component that renders a single _tip_ on the screen. The tip will point to the React element that `DotTip` is nested within. Each tip is uniquely identified by a string passed to `id`.

When there are multiple instances of `DotTip` that reference the same tip identifier, only the first instance to have been mounted will be visible.

## Usage

```jsx
Expand All @@ -23,7 +21,7 @@ The component accepts the following props:

### id

A string that uniquely identifies the tip. Identifiers should be prefixed with the name of the plugin, followed by a `/`. For example, `acme/add-to-cart`. Changing the identifier after the component has mounted is not supported.
A string that uniquely identifies the tip. Identifiers should be prefixed with the name of the plugin, followed by a `/`. For example, `acme/add-to-cart`.

- Type: `string`
- Required: Yes
Expand Down
112 changes: 51 additions & 61 deletions packages/nux/src/components/dot-tip/index.js
Original file line number Diff line number Diff line change
@@ -1,84 +1,74 @@
/**
* WordPress dependencies
*/
import { Component } from '@wordpress/element';
import { compose, withInstanceId } from '@wordpress/compose';
import { compose } from '@wordpress/compose';
import { Popover, Button, IconButton } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { withSelect, withDispatch } from '@wordpress/data';

export class DotTip extends Component {
componentDidMount() {
this.props.onRegister();
}

componentWillUnmount() {
this.props.onUnregister();
}

render() {
const { children, isVisible, hasNextTip, onDismiss, onDisable } = this.props;
function getAnchorRect( anchor ) {
// The default getAnchorRect() excludes an element's top and bottom padding
// from its calculation. We want tips to point to the outer margin of an
// element, so we override getAnchorRect() to include all padding.
return anchor.parentNode.getBoundingClientRect();
}

if ( ! isVisible ) {
return null;
}
function onClick( event ) {
// Tips are often nested within buttons. We stop propagation so that clicking
// on a tip doesn't result in the button being clicked.
event.stopPropagation();
}

return (
<Popover
className="nux-dot-tip"
position="middle right"
noArrow
focusOnMount="container"
role="dialog"
aria-label={ __( 'Gutenberg tips' ) }
onClick={ ( event ) => {
// Tips are often nested within buttons. We stop propagation so that clicking
// on a tip doesn't result in the button being clicked.
event.stopPropagation();
} }
>
<p>{ children }</p>
<p>
<Button isLink onClick={ onDismiss }>
{ hasNextTip ? __( 'See next tip' ) : __( 'Got it' ) }
</Button>
</p>
<IconButton
className="nux-dot-tip__disable"
icon="no-alt"
label={ __( 'Disable tips' ) }
onClick={ onDisable }
/>
</Popover>
);
export function DotTip( {
children,
isVisible,
hasNextTip,
onDismiss,
onDisable,
} ) {
if ( ! isVisible ) {
return null;
}

return (
<Popover
className="nux-dot-tip"
position="middle right"
noArrow
focusOnMount="container"
getAnchorRect={ getAnchorRect }
role="dialog"
aria-label={ __( 'Gutenberg tips' ) }
onClick={ onClick }
>
<p>{ children }</p>
<p>
<Button isLink onClick={ onDismiss }>
{ hasNextTip ? __( 'See next tip' ) : __( 'Got it' ) }
</Button>
</p>
<IconButton
className="nux-dot-tip__disable"
icon="no-alt"
label={ __( 'Disable tips' ) }
onClick={ onDisable }
/>
</Popover>
);
}

export default compose(
withInstanceId,
withSelect( ( select, { id, instanceId } ) => {
withSelect( ( select, { id } ) => {
const { isTipVisible, getAssociatedGuide } = select( 'core/nux' );
const associatedGuide = getAssociatedGuide( id );
return {
isVisible: isTipVisible( id, instanceId ),
isVisible: isTipVisible( id ),
hasNextTip: !! ( associatedGuide && associatedGuide.nextTipId ),
};
} ),
withDispatch( ( dispatch, { id, instanceId } ) => {
const {
registerTipInstance,
unregisterTipInstance,
dismissTip,
disableTips,
} = dispatch( 'core/nux' );

withDispatch( ( dispatch, { id } ) => {
const { dismissTip, disableTips } = dispatch( 'core/nux' );
return {
onRegister() {
registerTipInstance( id, instanceId );
},
onUnregister() {
unregisterTipInstance( id, instanceId );
},
onDismiss() {
dismissTip( id );
},
Expand Down
10 changes: 8 additions & 2 deletions packages/nux/src/components/dot-tip/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,16 @@ $dot-scale: 3; // How much the pulse animation should scale up by in size
}

// Position the dot right next to the edge of the button
&.is-left {
&.is-top {
margin-top: -$dot-size / 2;
}
&.is-bottom {
margin-top: $dot-size / 2;
}
&.is-middle.is-left {
margin-left: -$dot-size / 2;
}
&.is-right {
&.is-middle.is-right {
margin-left: $dot-size / 2;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ exports[`DotTip should render correctly 1`] = `
aria-label="Gutenberg tips"
className="nux-dot-tip"
focusOnMount="container"
getAnchorRect={[Function]}
noArrow={true}
onClick={[Function]}
position="middle right"
Expand Down
Loading