Skip to content

Commit

Permalink
Use rich text hook for post title (#31569)
Browse files Browse the repository at this point in the history
  • Loading branch information
ellatrix authored Aug 19, 2021
1 parent d453ea7 commit 647547a
Show file tree
Hide file tree
Showing 13 changed files with 87 additions and 128 deletions.
12 changes: 7 additions & 5 deletions packages/block-editor/src/components/rich-text/style.scss
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
.block-editor-rich-text__editable {
> p:first-child {
margin-top: 0;
}

.rich-text {
[data-rich-text-placeholder] {
pointer-events: none;
}
Expand All @@ -24,6 +20,12 @@
}
}

.block-editor-rich-text__editable {
> p:first-child {
margin-top: 0;
}
}

// Captions may have lighter (gray) text, or be shown on a range of different background luminosites.
// To ensure legibility, we increase the default placeholder opacity to ensure contrast.
figcaption.block-editor-rich-text__editable [data-rich-text-placeholder]::before {
Expand Down
2 changes: 1 addition & 1 deletion packages/e2e-tests/specs/editor/blocks/post-title.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ describe( 'Post Title block', () => {
await page.waitForSelector( '.edit-post-layout' );
const title = await page.$eval(
'.editor-post-title__input',
( element ) => element.value
( element ) => element.textContent
);
expect( title ).toEqual( 'Just tweaking the post title' );
} );
Expand Down
6 changes: 3 additions & 3 deletions packages/e2e-tests/specs/editor/plugins/annotations.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ describe( 'Using Plugins API', () => {
)[ 0 ];
await addAnnotationButton.click();
await page.evaluate( () =>
document.querySelector( '[contenteditable]' ).focus()
document.querySelector( '.wp-block-paragraph' ).focus()
);
}

Expand Down Expand Up @@ -91,7 +91,7 @@ describe( 'Using Plugins API', () => {
* @return {Promise<string>} Inner HTML.
*/
async function getRichTextInnerHTML() {
const htmlContent = await page.$$( '*[contenteditable]' );
const htmlContent = await page.$$( '.wp-block-paragraph' );
return await page.evaluate( ( el ) => {
return el.innerHTML;
}, htmlContent[ 0 ] );
Expand Down Expand Up @@ -139,7 +139,7 @@ describe( 'Using Plugins API', () => {
await page.keyboard.type( 'D' );

await removeAnnotations();
const htmlContent = await page.$$( '*[contenteditable]' );
const htmlContent = await page.$$( '.wp-block-paragraph' );
const html = await page.evaluate( ( el ) => {
return el.innerHTML;
}, htmlContent[ 0 ] );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,8 @@ describe( 'Change detection', () => {
// Verify that the title is empty.
const title = await page.$eval(
'.editor-post-title__input',
( element ) => element.innerHTML
// Trim padding non-breaking space
( element ) => element.textContent.trim()
);
expect( title ).toBe( '' );

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ describe( 'Order of block keyboard navigation', () => {
await page.keyboard.press( 'Tab' );
await expect(
await page.evaluate( () => {
return document.activeElement.placeholder;
return document.activeElement.getAttribute( 'aria-label' );
} )
).toBe( 'Add title' );

Expand Down Expand Up @@ -168,7 +168,7 @@ describe( 'Order of block keyboard navigation', () => {
await pressKeyWithModifier( 'shift', 'Tab' );
await expect(
await page.evaluate( () => {
return document.activeElement.placeholder;
return document.activeElement.getAttribute( 'aria-label' );
} )
).toBe( 'Add title' );
} );
Expand Down
9 changes: 6 additions & 3 deletions packages/e2e-tests/specs/editor/various/new-post.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,12 @@ describe( 'new editor state', () => {
expect.stringContaining( 'post-new.php' )
);
// Should display the blank title.
const title = await page.$( '[placeholder="Add title"]' );
const title = await page.$( '[aria-label="Add title"]' );
expect( title ).not.toBeNull();
expect( title.innerHTML ).toBeFalsy();
// Trim padding non-breaking space
expect(
await title.evaluate( ( el ) => el.textContent.trim() )
).toBeFalsy();
// Should display the Preview button.
const postPreviewButton = await page.$(
'.editor-post-preview.components-button'
Expand Down Expand Up @@ -59,7 +62,7 @@ describe( 'new editor state', () => {
} );

expect( activeElementClasses ).toContain( 'editor-post-title__input' );
expect( activeElementTagName ).toEqual( 'textarea' );
expect( activeElementTagName ).toEqual( 'h1' );
} );

it( 'should not focus the title if the title exists', async () => {
Expand Down
6 changes: 5 additions & 1 deletion packages/e2e-tests/specs/editor/various/preview.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
publishPost,
saveDraft,
openPreviewPage,
pressKeyWithModifier,
} from '@wordpress/e2e-test-utils';

/** @typedef {import('puppeteer').Page} Page */
Expand Down Expand Up @@ -216,7 +217,10 @@ describe( 'Preview', () => {
await editorPage.bringToFront();

// Append bbbbb to the title, and tab away from the title so blur event is triggered.
await editorPage.type( '.editor-post-title__input', 'bbbbb' );
await editorPage.focus( '.editor-post-title__input' );
await pressKeyWithModifier( 'primary', 'a' );
await editorPage.keyboard.press( 'ArrowRight' );
await editorPage.keyboard.type( 'bbbbb' );
await editorPage.keyboard.press( 'Tab' );

// Save draft and open the preview page right after.
Expand Down
3 changes: 0 additions & 3 deletions packages/e2e-tests/specs/editor/various/typewriter.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ describe( 'TypeWriter', () => {
// Create first block.
await page.keyboard.press( 'Enter' );

// Create second block.
await page.keyboard.press( 'Enter' );

const initialPosition = await getCaretPosition();

// The page shouldn't be scrolled when it's being filled.
Expand Down
21 changes: 10 additions & 11 deletions packages/e2e-tests/specs/editor/various/writing-flow.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -289,29 +289,28 @@ describe( 'Writing Flow', () => {
it( 'should navigate native inputs vertically, not horizontally', async () => {
// See: https://github.com/WordPress/gutenberg/issues/9626

// Title is within the editor's writing flow, and is a <textarea>
await page.click( '.editor-post-title' );
await insertBlock( 'Shortcode' );

// Should remain in title upon ArrowRight:
await page.keyboard.press( 'ArrowRight' );
let isInTitle = await page.evaluate(
() => !! document.activeElement.closest( '.editor-post-title' )
let isInShortcodeBlock = await page.evaluate(
() => !! document.activeElement.closest( '.wp-block-shortcode' )
);
expect( isInTitle ).toBe( true );
expect( isInShortcodeBlock ).toBe( true );

// Should remain in title upon modifier + ArrowDown:
await pressKeyWithModifier( 'primary', 'ArrowDown' );
isInTitle = await page.evaluate(
() => !! document.activeElement.closest( '.editor-post-title' )
isInShortcodeBlock = await page.evaluate(
() => !! document.activeElement.closest( '.wp-block-shortcode' )
);
expect( isInTitle ).toBe( true );
expect( isInShortcodeBlock ).toBe( true );

// Should navigate into blocks list upon ArrowDown:
await page.keyboard.press( 'ArrowDown' );
const isInBlock = await page.evaluate(
() => !! document.activeElement.closest( '[data-type]' )
const isInParagraphBlock = await page.evaluate(
() => !! document.activeElement.closest( '.wp-block-paragraph' )
);
expect( isInBlock ).toBe( true );
expect( isInParagraphBlock ).toBe( true );
} );

it( 'should not delete surrounding space when deleting a word with Backspace', async () => {
Expand Down
7 changes: 4 additions & 3 deletions packages/e2e-tests/specs/experiments/template-part.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,9 @@ describe( 'Template Part', () => {
const confirmTitleButton = await page.waitForSelector(
confirmTitleButtonSelector
);
await page.keyboard.press( 'Tab' );
await page.keyboard.press( 'Tab' );
await page.keyboard.type( 'Create New' );
await confirmTitleButton.click();

const newTemplatePart = await page.waitForSelector(
Expand All @@ -314,10 +317,8 @@ describe( 'Template Part', () => {
);
await chooseExistingButton.click();
const preview = await page.waitForSelector(
'.block-editor-block-preview__content iframe'
'[aria-label="Create New"]'
);
expect( preview ).toBeTruthy();

await preview.click();
await page.waitForSelector( activatedTemplatePartSelector );
const templatePartContent = await page.waitForXPath(
Expand Down
57 changes: 37 additions & 20 deletions packages/editor/src/components/post-title/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/**
* External dependencies
*/
import TextareaAutosize from 'react-autosize-textarea';
import classnames from 'classnames';

/**
Expand All @@ -12,10 +11,10 @@ import { useEffect, useRef, useState } from '@wordpress/element';
import { decodeEntities } from '@wordpress/html-entities';
import { ENTER } from '@wordpress/keycodes';
import { useSelect, useDispatch } from '@wordpress/data';
import { VisuallyHidden } from '@wordpress/components';
import { useInstanceId } from '@wordpress/compose';
import { pasteHandler } from '@wordpress/blocks';
import { store as blockEditorStore } from '@wordpress/block-editor';
import { __unstableUseRichText as useRichText } from '@wordpress/rich-text';
import { useMergeRefs } from '@wordpress/compose';

/**
* Internal dependencies
Expand All @@ -29,7 +28,6 @@ import { store as editorStore } from '../../store';
const REGEXP_NEWLINES = /[\r\n]+/g;

export default function PostTitle() {
const instanceId = useInstanceId( PostTitle );
const ref = useRef();
const [ isSelected, setIsSelected ] = useState( false );
const { editPost } = useDispatch( editorStore );
Expand Down Expand Up @@ -94,17 +92,20 @@ export default function PostTitle() {
editPost( { title: newTitle } );
}

const [ selection, setSelection ] = useState( {} );

function onSelect() {
setIsSelected( true );
clearSelectedBlock();
}

function onUnselect() {
setIsSelected( false );
setSelection( {} );
}

function onChange( event ) {
onUpdate( event.target.value.replace( REGEXP_NEWLINES, ' ' ) );
function onChange( value ) {
onUpdate( value.replace( REGEXP_NEWLINES, ' ' ) );
}

function onKeyDown( event ) {
Expand Down Expand Up @@ -174,24 +175,39 @@ export default function PostTitle() {
'has-fixed-toolbar': hasFixedToolbar,
}
);
const decodedPlaceholder = decodeEntities( placeholder );
const decodedPlaceholder =
decodeEntities( placeholder ) || __( 'Add title' );
const { ref: richTextRef } = useRichText( {
value: title,
onChange,
placeholder: decodedPlaceholder,
selectionStart: selection.start,
selectionEnd: selection.end,
onSelectionChange( newStart, newEnd ) {
setSelection( ( sel ) => {
const { start, end } = sel;
if ( start === newStart && end === newEnd ) {
return sel;
}
return {
start: newStart,
end: newEnd,
};
} );
},
__unstableDisableFormats: true,
preserveWhiteSpace: true,
} );

/* eslint-disable jsx-a11y/heading-has-content, jsx-a11y/no-noninteractive-element-interactions */
return (
<PostTypeSupportCheck supportKeys="title">
<div className={ className }>
<VisuallyHidden
as="label"
htmlFor={ `post-title-${ instanceId }` }
>
{ decodedPlaceholder || __( 'Add title' ) }
</VisuallyHidden>
<TextareaAutosize
ref={ ref }
id={ `post-title-${ instanceId }` }
className="editor-post-title__input"
value={ title }
onChange={ onChange }
placeholder={ decodedPlaceholder || __( 'Add title' ) }
<h1
ref={ useMergeRefs( [ richTextRef, ref ] ) }
contentEditable
className="editor-post-title__input rich-text"
aria-label={ decodedPlaceholder }
onFocus={ onSelect }
onBlur={ onUnselect }
onKeyDown={ onKeyDown }
Expand All @@ -201,4 +217,5 @@ export default function PostTitle() {
</div>
</PostTypeSupportCheck>
);
/* eslint-enable jsx-a11y/heading-has-content, jsx-a11y/no-noninteractive-element-interactions */
}
69 changes: 0 additions & 69 deletions packages/editor/src/components/post-title/style.scss
Original file line number Diff line number Diff line change
@@ -1,75 +1,6 @@
.editor-post-title {
position: relative;

.editor-post-title__input {
display: block;
width: 100%;
margin: 0;
box-shadow: none;
background: transparent;
transition: border 0.1s ease-out, box-shadow 0.1s linear;
@include reduce-motion("transition");
padding: #{ $block-padding + 5px } 0;
word-break: keep-all;

// Inherit the styles set by the theme.
font-family: inherit;
color: inherit;

// Stack borders on mobile.
border: $border-width solid transparent;
border-left-width: 0;
border-right-width: 0;
border-radius: 0;

// Include transparent outline for Windows High Contrast mode.
outline: $border-width solid transparent;

@include break-small() {
border-width: $border-width;
}

// Match h1 heading.
font-size: 2.44em;
font-weight: 800;
line-height: 1.4;

&::-webkit-input-placeholder {
color: $dark-gray-placeholder;
}

&::-moz-placeholder {
color: $dark-gray-placeholder;
// Override Firefox default.
opacity: 1;
}

&:-ms-input-placeholder {
color: $dark-gray-placeholder;
}

.is-dark-theme & {
&::-webkit-input-placeholder {
color: $light-gray-placeholder;
}

&::-moz-placeholder {
opacity: 1; // Necessary because Firefox reduces this from 1.
color: $light-gray-placeholder;
}

&:-ms-input-placeholder {
color: $light-gray-placeholder;
}
}

&:focus {
border: $border-width solid transparent;
outline: $border-width solid transparent;
box-shadow: none;
}
}

&.is-focus-mode .editor-post-title__input {
opacity: 0.5;
transition: opacity 0.1s linear;
Expand Down
Loading

0 comments on commit 647547a

Please sign in to comment.