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

Use rich text hook for post title #31569

Merged
merged 5 commits into from
Aug 19, 2021
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
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
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' );
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The post title has become bigger, so we have to test with less blocks.


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"]'
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw that this test is unstable. This should stabilise it.

);
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