Skip to content

Commit

Permalink
Always show the block appender when its parent is selected (#36656)
Browse files Browse the repository at this point in the history
  • Loading branch information
youknowriad committed Nov 24, 2021
1 parent d2d673d commit 3b75f8d
Show file tree
Hide file tree
Showing 16 changed files with 75 additions and 161 deletions.
26 changes: 5 additions & 21 deletions packages/block-editor/src/components/block-list-appender/index.js
@@ -1,7 +1,6 @@
/**
* External dependencies
*/
import { last } from 'lodash';
import classnames from 'classnames';

/**
Expand All @@ -18,7 +17,6 @@ import ButtonBlockAppender from '../button-block-appender';
import { store as blockEditorStore } from '../../store';

function BlockListAppender( {
blockClientIds,
rootClientId,
canInsertDefaultBlock,
isLocked,
Expand All @@ -36,30 +34,18 @@ function BlockListAppender( {
// Prefer custom render prop if provided.
appender = <CustomAppender />;
} else {
const isDocumentAppender = ! rootClientId;
const isParentSelected = selectedBlockClientId === rootClientId;
const isAnotherDefaultAppenderAlreadyDisplayed =
selectedBlockClientId &&
! blockClientIds.includes( selectedBlockClientId );
const isParentSelected =
selectedBlockClientId === rootClientId ||
( ! rootClientId && ! selectedBlockClientId );

if (
! isDocumentAppender &&
! isParentSelected &&
( ! selectedBlockClientId ||
isAnotherDefaultAppenderAlreadyDisplayed )
) {
if ( ! isParentSelected ) {
return null;
}

if ( canInsertDefaultBlock ) {
// Render the default block appender when renderAppender has not been
// provided and the context supports use of the default appender.
appender = (
<DefaultBlockAppender
rootClientId={ rootClientId }
lastBlockClientId={ last( blockClientIds ) }
/>
);
appender = <DefaultBlockAppender rootClientId={ rootClientId } />;
} else {
// Fallback in the case no renderAppender has been provided and the
// default block can't be inserted.
Expand Down Expand Up @@ -103,15 +89,13 @@ function BlockListAppender( {

export default withSelect( ( select, { rootClientId } ) => {
const {
getBlockOrder,
canInsertBlockType,
getTemplateLock,
getSelectedBlockClientId,
} = select( blockEditorStore );

return {
isLocked: !! getTemplateLock( rootClientId ),
blockClientIds: getBlockOrder( rootClientId ),
canInsertDefaultBlock: canInsertBlockType(
getDefaultBlockName(),
rootClientId
Expand Down
Expand Up @@ -8,9 +8,9 @@ import classnames from 'classnames';
*/
import { __ } from '@wordpress/i18n';
import { compose } from '@wordpress/compose';
import { getDefaultBlockName } from '@wordpress/blocks';
import { decodeEntities } from '@wordpress/html-entities';
import { withSelect, withDispatch } from '@wordpress/data';
import { ENTER, SPACE } from '@wordpress/keycodes';

/**
* Internal dependencies
Expand All @@ -26,13 +26,12 @@ export const ZWNBSP = '\ufeff';

export function DefaultBlockAppender( {
isLocked,
isVisible,
onAppend,
showPrompt,
placeholder,
rootClientId,
} ) {
if ( isLocked || ! isVisible ) {
if ( isLocked ) {
return null;
}

Expand All @@ -48,20 +47,23 @@ export function DefaultBlockAppender( {
>
<p
tabIndex="0"
// Only necessary for `useCanvasClickRedirect` to consider it
// as a target. Ideally it should consider any tabbable target,
// but the inserter is rendered in place while it should be
// rendered in a popover, just like it does for an empty
// paragraph block.
contentEditable
suppressContentEditableWarning
// We want this element to be styled as a paragraph by themes.
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-to-interactive-role
role="button"
aria-label={ __( 'Add block' ) }
aria-label={ __( 'Add default block' ) }
// A wrapping container for this one already has the wp-block className.
className="block-editor-default-block-appender__content"
onFocus={ onAppend }
onKeyDown={ ( event ) => {
if ( ENTER === event.keyCode || SPACE === event.keyCode ) {
onAppend();
}
} }
onClick={ () => onAppend() }
onFocus={ () => {
if ( showPrompt ) {
onAppend();
}
} }
>
{ showPrompt ? value : ZWNBSP }
</p>
Expand All @@ -77,23 +79,14 @@ export function DefaultBlockAppender( {

export default compose(
withSelect( ( select, ownProps ) => {
const {
getBlockCount,
getBlockName,
isBlockValid,
getSettings,
getTemplateLock,
} = select( blockEditorStore );
const { getBlockCount, getSettings, getTemplateLock } = select(
blockEditorStore
);

const isEmpty = ! getBlockCount( ownProps.rootClientId );
const isLastBlockDefault =
getBlockName( ownProps.lastBlockClientId ) ===
getDefaultBlockName();
const isLastBlockValid = isBlockValid( ownProps.lastBlockClientId );
const { bodyPlaceholder } = getSettings();

return {
isVisible: isEmpty || ! isLastBlockDefault || ! isLastBlockValid,
showPrompt: isEmpty,
isLocked: !! getTemplateLock( ownProps.rootClientId ),
placeholder: bodyPlaceholder,
Expand Down
Expand Up @@ -126,3 +126,7 @@
display: flex;
}
}

.block-editor-default-block-appender__content {
cursor: text;
}
Expand Up @@ -6,24 +6,12 @@ exports[`DefaultBlockAppender should append a default block when input focused 1
data-root-client-id=""
>
<p
aria-label="Add block"
aria-label="Add default block"
className="block-editor-default-block-appender__content"
contentEditable={true}
onFocus={
[MockFunction] {
"calls": Array [
Array [],
],
"results": Array [
Object {
"type": "return",
"value": undefined,
},
],
}
}
onClick={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
role="button"
suppressContentEditableWarning={true}
tabIndex="0"
>
Type / to choose a block
Expand All @@ -42,12 +30,12 @@ exports[`DefaultBlockAppender should match snapshot 1`] = `
data-root-client-id=""
>
<p
aria-label="Add block"
aria-label="Add default block"
className="block-editor-default-block-appender__content"
contentEditable={true}
onFocus={[MockFunction]}
onClick={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
role="button"
suppressContentEditableWarning={true}
tabIndex="0"
>
Type / to choose a block
Expand All @@ -66,12 +54,12 @@ exports[`DefaultBlockAppender should optionally show without prompt 1`] = `
data-root-client-id=""
>
<p
aria-label="Add block"
aria-label="Add default block"
className="block-editor-default-block-appender__content"
contentEditable={true}
onFocus={[MockFunction]}
onClick={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
role="button"
suppressContentEditableWarning={true}
tabIndex="0"
>

Expand Down
Expand Up @@ -14,16 +14,10 @@ describe( 'DefaultBlockAppender', () => {
expect( onAppend ).toHaveBeenCalledWith();
};

it( 'should render nothing if not visible', () => {
const wrapper = shallow( <DefaultBlockAppender /> );

expect( wrapper.type() ).toBe( null );
} );

it( 'should match snapshot', () => {
const onAppend = jest.fn();
const wrapper = shallow(
<DefaultBlockAppender isVisible onAppend={ onAppend } showPrompt />
<DefaultBlockAppender onAppend={ onAppend } showPrompt />
);

expect( wrapper ).toMatchSnapshot();
Expand All @@ -32,10 +26,10 @@ describe( 'DefaultBlockAppender', () => {
it( 'should append a default block when input focused', () => {
const onAppend = jest.fn();
const wrapper = shallow(
<DefaultBlockAppender isVisible onAppend={ onAppend } showPrompt />
<DefaultBlockAppender onAppend={ onAppend } showPrompt />
);

wrapper.find( 'p' ).simulate( 'focus' );
wrapper.find( 'p' ).simulate( 'click' );

expect( wrapper ).toMatchSnapshot();

Expand All @@ -45,11 +39,7 @@ describe( 'DefaultBlockAppender', () => {
it( 'should optionally show without prompt', () => {
const onAppend = jest.fn();
const wrapper = shallow(
<DefaultBlockAppender
isVisible
onAppend={ onAppend }
showPrompt={ false }
/>
<DefaultBlockAppender onAppend={ onAppend } showPrompt={ false } />
);
const input = wrapper.find( 'p' );

Expand Down
1 change: 0 additions & 1 deletion packages/block-editor/src/components/index.js
Expand Up @@ -138,7 +138,6 @@ export {
} from './typewriter';
export { default as Warning } from './warning';
export { default as WritingFlow } from './writing-flow';
export { useCanvasClickRedirect as __unstableUseCanvasClickRedirect } from './use-canvas-click-redirect';
export { default as useBlockDisplayInformation } from './use-block-display-information';
export { default as __unstableIframe } from './iframe';
export { default as __experimentalUseNoRecursiveRenders } from './use-no-recursive-renders';
Expand Down
Expand Up @@ -16,13 +16,8 @@ import BaseDefaultBlockAppender from '../default-block-appender';
import withClientId from './with-client-id';
import { store as blockEditorStore } from '../../store';

export const DefaultBlockAppender = ( { clientId, lastBlockClientId } ) => {
return (
<BaseDefaultBlockAppender
rootClientId={ clientId }
lastBlockClientId={ lastBlockClientId }
/>
);
export const DefaultBlockAppender = ( { clientId } ) => {
return <BaseDefaultBlockAppender rootClientId={ clientId } />;
};

export default compose( [
Expand Down

This file was deleted.

4 changes: 4 additions & 0 deletions packages/e2e-test-utils/src/click-block-appender.js
Expand Up @@ -2,6 +2,10 @@
* Clicks the default block appender.
*/
export async function clickBlockAppender() {
// The block appender is only visible when there's no selection.
await page.evaluate( () =>
window.wp.data.dispatch( 'core/block-editor' ).clearSelectedBlock()
);
const appender = await page.waitForSelector(
'.block-editor-default-block-appender__content'
);
Expand Down
3 changes: 2 additions & 1 deletion packages/e2e-tests/specs/editor/blocks/preformatted.test.js
Expand Up @@ -7,6 +7,7 @@ import {
getEditedPostContent,
createNewPost,
insertBlock,
clickBlockAppender,
} from '@wordpress/e2e-test-utils';

describe( 'Preformatted', () => {
Expand Down Expand Up @@ -39,7 +40,7 @@ describe( 'Preformatted', () => {
await page.keyboard.press( 'Enter' );
await page.keyboard.type( '2' );
await page.keyboard.press( 'Enter' );
await page.keyboard.press( 'ArrowDown' );
await clickBlockAppender();
await page.keyboard.type( '3' );
await page.keyboard.press( 'ArrowLeft' );
await page.keyboard.press( 'Backspace' );
Expand Down

0 comments on commit 3b75f8d

Please sign in to comment.