Skip to content

Commit

Permalink
feat: Focus title if title is empty (#9608)
Browse files Browse the repository at this point in the history
* feat: Focus title when empty

Fix #3828.
  • Loading branch information
tofumatt authored Sep 7, 2018
1 parent c1cdd95 commit b688d2e
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 45 deletions.
5 changes: 1 addition & 4 deletions docs/data/data-core-editor.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,6 @@ Whether unsaved values exist.
Returns true if there are no unsaved values for the current edit session and
if the currently edited post is new (has never been saved before).

Note: This selector is not currently used by the editor package, but is made
available as an assumed-useful selector for external integrations.

*Parameters*

* state: Global application state.
Expand Down Expand Up @@ -1414,4 +1411,4 @@ Returns an action object used in signalling that the editor settings have been u

*Parameters*

* settings: Updated settings
* settings: Updated settings
10 changes: 5 additions & 5 deletions packages/block-library/src/list/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -244,12 +244,12 @@ export const settings = {
} );
} );

// this checks for languages that do not typically have square brackets on their keyboards
// Check for languages that do not have square brackets on their keyboards.
const lang = window.navigator.browserLanguage || window.navigator.language;
const keyboardHasSqBracket = ! /^(?:fr|nl|sv|ru|de|es|it)/.test( lang );
const keyboardHasSquareBracket = ! /^(?:fr|nl|sv|ru|de|es|it)/.test( lang );

if ( keyboardHasSqBracket ) {
// keycode 219 = '[' and keycode 221 = ']'
if ( keyboardHasSquareBracket ) {
// `[` is keycode 219; `]` is keycode 221.
editor.shortcuts.add( 'meta+219', 'Decrease indent', 'Outdent' );
editor.shortcuts.add( 'meta+221', 'Increase indent', 'Indent' );
} else {
Expand All @@ -265,7 +265,7 @@ export const settings = {
const { setAttributes } = this.props;
const { internalListType } = this.state;
if ( internalListType ) {
// only change list types, don't toggle off internal lists
// Only change list types, don't toggle off internal lists.
if ( internalListType !== type && this.editor ) {
this.editor.execCommand( command );
}
Expand Down
22 changes: 20 additions & 2 deletions packages/editor/src/components/post-title/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,15 @@ class PostTitle extends Component {
}

render() {
const { title, placeholder, instanceId, isPostTypeViewable, isFocusMode, hasFixedToolbar } = this.props;
const {
hasFixedToolbar,
isCleanNewPost,
isFocusMode,
isPostTypeViewable,
instanceId,
placeholder,
title,
} = this.props;
const { isSelected } = this.state;
const className = classnames( 'editor-post-title__block', {
'is-selected': isSelected,
Expand Down Expand Up @@ -119,6 +127,15 @@ class PostTitle extends Component {
onFocus={ this.onSelect }
onKeyDown={ this.onKeyDown }
onKeyPress={ this.onUnselect }
/*
Only autofocus the title when the post is entirely empty.
This should only happen for a new post, which means we
focus the title on new post so the author can start typing
right away, without needing to click anything.
*/
/* eslint-disable jsx-a11y/no-autofocus */
autoFocus={ isCleanNewPost }
/* eslint-enable jsx-a11y/no-autofocus */
/>
</KeyboardShortcuts>
{ isSelected && isPostTypeViewable && <PostPermalink /> }
Expand All @@ -130,12 +147,13 @@ class PostTitle extends Component {
}

const applyWithSelect = withSelect( ( select ) => {
const { getEditedPostAttribute, getEditorSettings } = select( 'core/editor' );
const { getEditedPostAttribute, getEditorSettings, isCleanNewPost } = select( 'core/editor' );
const { getPostType } = select( 'core' );
const postType = getPostType( getEditedPostAttribute( 'type' ) );
const { titlePlaceholder, focusMode, hasFixedToolbar } = getEditorSettings();

return {
isCleanNewPost: isCleanNewPost(),
title: getEditedPostAttribute( 'title' ),
isPostTypeViewable: get( postType, [ 'viewable' ], false ),
placeholder: titlePlaceholder,
Expand Down
3 changes: 0 additions & 3 deletions packages/editor/src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,6 @@ export function isEditedPostDirty( state ) {
* Returns true if there are no unsaved values for the current edit session and
* if the currently edited post is new (has never been saved before).
*
* Note: This selector is not currently used by the editor package, but is made
* available as an assumed-useful selector for external integrations.
*
* @param {Object} state Global application state.
*
* @return {boolean} Whether new post and unsaved values exist.
Expand Down
31 changes: 0 additions & 31 deletions test/e2e/specs/hello.test.js

This file was deleted.

75 changes: 75 additions & 0 deletions test/e2e/specs/new-post.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* Internal dependencies
*/
import { newPost } from '../support/utils';

describe( 'new editor state', () => {
beforeAll( async () => {
await newPost();
} );

it( 'should show the New Post page in Gutenberg', async () => {
expect( page.url() ).toEqual( expect.stringContaining( 'post-new.php' ) );
// Should display the title.
const title = await page.$( '[placeholder="Add title"]' );
expect( title ).not.toBeNull();
// Should display the Preview button.
const postPreviewButton = await page.$( '.editor-post-preview.components-button' );
expect( postPreviewButton ).not.toBeNull();
// Should display the Post Formats UI.
const postFormatsUi = await page.$( '.editor-post-format' );
expect( postFormatsUi ).not.toBeNull();
} );

it( 'should have no history', async () => {
const undoButton = await page.$( '.editor-history__undo:not( :disabled )' );
const redoButton = await page.$( '.editor-history__redo:not( :disabled )' );

expect( undoButton ).toBeNull();
expect( redoButton ).toBeNull();
} );

it( 'should focus the title if the title is empty', async () => {
// We need to remove the tips to make sure they aren't clicked/removed
// during our check of the title `textarea`'s focus.
await page.evaluate( () => {
return wp.data.dispatch( 'core/nux' ).disableTips();
} );

// And then reload the page to ensure we get a new page that should
// autofocus the title, without any NUX tips.
await page.reload();

const activeElementClasses = await page.evaluate( () => {
return Object.values( document.activeElement.classList );
} );
const activeElementTagName = await page.evaluate( () => {
return document.activeElement.tagName.toLowerCase();
} );

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

it( 'should not focus the title if the title exists', async () => {
// Enter a title for this post.
await page.type( '.editor-post-title__input', 'Here is the title' );
// Save the post as a draft.
await page.click( '.editor-post-save-draft' );
await page.waitForSelector( '.editor-post-saved-state.is-saved' );
// Reload the browser so a post is loaded with a title.
await page.reload();

const activeElementClasses = await page.evaluate( () => {
return Object.values( document.activeElement.classList );
} );
const activeElementTagName = await page.evaluate( () => {
return document.activeElement.tagName.toLowerCase();
} );

expect( activeElementClasses ).not.toContain( 'editor-post-title__input' );
// The document `body` should be the `activeElement`, because nothing is
// focused by default when a post already has a title.
expect( activeElementTagName ).toEqual( 'body' );
} );
} );

0 comments on commit b688d2e

Please sign in to comment.