Skip to content

Commit

Permalink
Add new keyboard shortcuts help modal (#8316)
Browse files Browse the repository at this point in the history
Pressing ctl+option+h (shift+alt+h on windows/linux) displays a modal detailing keyboard shortcuts.

* Create a simple modal for showing keyboard shortcuts that displays when pressing cmd + /

* Add more shortcuts and place them in sections with a title and description

* Add styles for shortcut modal

* Add missing shortctuts

* Remove unecessary shortcut section descriptions

* Display shortcut keys in a kbd element

* Styling changes

- Position shortcut to the right of description
- Adjust margin/padding
- Make section titles default font size

* Regroup shortcuts

* Fix invalid style rule

* Change copy for slash inserter shortcut

* Map over config to produce ShortcutSections

* Change where keyboard shortcut help modal is rendered

Move modal so that it's rendered in edit-post/layout component. This ensures
the modal is available in both the text and visual editor, and the shortcut
for launching the modal can be used on first load of the editor.

* Move keyboard-shortcut-help-modal to edit-post from editor package

* Add some border between rows in the keyboard shortcuts list

* Add reduxy things for opening and closing a modal

* Use actions to open/close modal and selector to determine current state

* Migrate the activeModal state from preferences to normal state so that its value is not persisted

* Add a menu item tot he more menu for toggling keyboard shortcut help

* Modify some shortcuts and description text

* Add snapshot tests for help modal

* Destructure props

* Modify header styling

* Rename class name to reflect component is now in edit-post, and reorder shortcuts

* Display shortcut for more menu menu item

* Disable WP_Help TinyMCE command for classic block

* Change keyboard shortcut for triggering help to access + h, the same as the classic editor

* Add utility to keycodes for returning key combinations in an array

* Avoid ugly regular expression to split key combination into array

Using newly introduced displayShortcutList function results in cleaner, better tested code

* Add e2e test for shortcut help modal

* Vertically center shortcut text (if adjacent label wraps onto multiple lines)

* Close more menu when keyboard shortcuts modal is opened using the menu item

* Use castArray over lengthy ternary

* Styling linter fixes

* JSDoc fixes

* Group activeModal unit tests in a describe

* Add test for initial activeModal state

* Fix incorrect state used in test

* Update list of key shortcuts for the help modal

* Remove unecessary return

* Make KeyboardShortcutsHelpMenuItem only open the help modal
  • Loading branch information
talldan authored Aug 10, 2018
1 parent 2b4bc5b commit 0a21147
Show file tree
Hide file tree
Showing 26 changed files with 1,005 additions and 64 deletions.
7 changes: 7 additions & 0 deletions core-blocks/freeform/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,13 @@ export default class FreeformEdit extends Component {

this.editor = editor;

// Disable TinyMCE's keyboard shortcut help.
editor.on( 'BeforeExecCommand', ( event ) => {
if ( event.command === 'WP_Help' ) {
event.preventDefault();
}
} );

if ( content ) {
editor.on( 'loadContent', () => editor.setContent( content ) );
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* WordPress Dependencies
*/
import { withDispatch } from '@wordpress/data';
import { displayShortcut } from '@wordpress/keycodes';

/**
* WordPress Dependencies
*/
import { __ } from '@wordpress/i18n';
import { MenuItem } from '@wordpress/components';

export function KeyboardShortcutsHelpMenuItem( { openModal, onSelect } ) {
return (
<MenuItem
onClick={ () => {
onSelect();
openModal( 'edit-post/keyboard-shortcut-help' );
} }
shortcut={ displayShortcut.access( 'h' ) }
>
{ __( 'Keyboard Shortcuts' ) }
</MenuItem>
);
}

export default withDispatch( ( dispatch, ) => {
const {
openModal,
} = dispatch( 'core/edit-post' );

return {
openModal,
};
} )( KeyboardShortcutsHelpMenuItem );
5 changes: 4 additions & 1 deletion edit-post/components/header/more-menu/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import ModeSwitcher from '../mode-switcher';
import FixedToolbarToggle from '../fixed-toolbar-toggle';
import PluginMoreMenuGroup from '../plugins-more-menu-group';
import TipsToggle from '../tips-toggle';
import KeyboardShortcutsHelpMenuItem from '../keyboard-shortcuts-help-menu-item';

const MoreMenu = () => (
<Dropdown
Expand Down Expand Up @@ -39,7 +40,9 @@ const MoreMenu = () => (
<MenuGroup
label={ __( 'Tools' ) }
filterName="editPost.MoreMenu.tools"
/>
>
<KeyboardShortcutsHelpMenuItem onSelect={ onClose } />
</MenuGroup>
</div>
) }
/>
Expand Down
134 changes: 134 additions & 0 deletions edit-post/components/keyboard-shortcut-help-modal/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/**
* WordPress dependencies
*/
import { displayShortcutList } from '@wordpress/keycodes';
import { __ } from '@wordpress/i18n';

const {
// Cmd+<key> on a mac, Ctrl+<key> elsewhere
primary,
// Shift+Cmd+<key> on a mac, Ctrl+Shift+<key> elsewhere
primaryShift,
// Shift+Alt+Cmd+<key> on a mac, Ctrl+Shift+Akt+<key> elsewhere
secondary,
// Ctrl+Alt+<key> on a mac, Shift+Alt+<key> elsewhere
access,
ctrl,
ctrlShift,
shiftAlt,
} = displayShortcutList;

const globalShortcuts = {
title: __( 'Global shortcuts' ),
shortcuts: [
{
keyCombination: access( 'h' ),
description: __( 'Display this help.' ),
},
{
keyCombination: primary( 's' ),
description: __( 'Save your changes.' ),
},
{
keyCombination: primary( 'z' ),
description: __( 'Undo your last changes.' ),
},
{
keyCombination: primaryShift( 'z' ),
description: __( 'Redo your last undo.' ),
},
{
keyCombination: primaryShift( ',' ),
description: __( 'Show or hide the settings sidebar.' ),
},
{
keyCombination: ctrl( '`' ),
description: __( 'Navigate to a the next part of the editor.' ),
},
{
keyCombination: ctrlShift( '`' ),
description: __( 'Navigate to the previous part of the editor.' ),
},
{
keyCombination: shiftAlt( 'n' ),
description: __( 'Navigate to a the next part of the editor (alternative).' ),
},
{
keyCombination: shiftAlt( 'p' ),
description: __( 'Navigate to the previous part of the editor (alternative).' ),
},
{
keyCombination: secondary( 'm' ),
description: __( 'Switch between Visual Editor and Code Editor.' ),
},
],
};

const selectionShortcuts = {
title: __( 'Selection shortcuts' ),
shortcuts: [
{
keyCombination: primary( 'a' ),
description: __( 'Select all text when typing. Press again to select all blocks.' ),
},
{
keyCombination: 'Esc',
description: __( 'Clear selection.' ),
},
],
};

const blockShortcuts = {
title: __( 'Block shortcuts' ),
shortcuts: [
{
keyCombination: primaryShift( 'd' ),
description: __( 'Duplicate the selected block(s).' ),
},
{
keyCombination: '/',
description: __( `Change the block type after adding a new paragraph.` ),
},
],
};

const textFormattingShortcuts = {
title: __( 'Text formatting' ),
shortcuts: [
{
keyCombination: primary( 'b' ),
description: __( 'Make the selected text bold.' ),
},
{
keyCombination: primary( 'i' ),
description: __( 'Make the selected text italic.' ),
},
{
keyCombination: primary( 'u' ),
description: __( 'Underline the selected text.' ),
},
{
keyCombination: primary( 'k' ),
description: __( 'Convert the selected text into a link.' ),
},
{
keyCombination: access( 's' ),
description: __( 'Remove a link.' ),
},
{
keyCombination: access( 'd' ),
description: __( 'Add a strikethrough to the selected text.' ),
},
{
keyCombination: access( 'x' ),
description: __( 'Display the selected text in a monospaced font.' ),
},
],
};

export default [
globalShortcuts,
selectionShortcuts,
blockShortcuts,
textFormattingShortcuts,
];
119 changes: 119 additions & 0 deletions edit-post/components/keyboard-shortcut-help-modal/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/**
* External dependencies
*/
import { castArray } from 'lodash';

/**
* WordPress dependencies
*/
import { Fragment } from '@wordpress/element';
import { Modal, KeyboardShortcuts } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { rawShortcut } from '@wordpress/keycodes';
import { withSelect, withDispatch } from '@wordpress/data';
import { compose } from '@wordpress/compose';

/**
* Internal dependencies
*/
import shortcutConfig from './config';
import './style.scss';

const MODAL_NAME = 'edit-post/keyboard-shortcut-help';

const mapKeyCombination = ( keyCombination ) => keyCombination.map( ( character, index ) => {
if ( character === '+' ) {
return (
<Fragment key={ index }>
{ character }
</Fragment>
);
}

return (
<kbd
key={ index }
className="edit-post-keyboard-shortcut-help__shortcut-key"
>
{ character }
</kbd>
);
} );

const ShortcutList = ( { shortcuts } ) => (
<dl className="edit-post-keyboard-shortcut-help__shortcut-list">
{ shortcuts.map( ( { keyCombination, description }, index ) => (
<div
className="edit-post-keyboard-shortcut-help__shortcut"
key={ index }
>
<dt className="edit-post-keyboard-shortcut-help__shortcut-term">
<kbd className="edit-post-keyboard-shortcut-help__shortcut-key-combination">
{ mapKeyCombination( castArray( keyCombination ) ) }
</kbd>
</dt>
<dd className="edit-post-keyboard-shortcut-help__shortcut-description">
{ description }
</dd>
</div>
) ) }
</dl>
);

const ShortcutSection = ( { title, shortcuts } ) => (
<section className="edit-post-keyboard-shortcut-help__section">
<h2 className="edit-post-keyboard-shortcut-help__section-title">
{ title }
</h2>
<ShortcutList shortcuts={ shortcuts } />
</section>
);

export function KeyboardShortcutHelpModal( { isModalActive, toggleModal } ) {
const title = (
<span className="edit-post-keyboard-shortcut-help__title">
{ __( 'Keyboard Shortcuts' ) }
</span>
);

return (
<Fragment>
<KeyboardShortcuts
bindGlobal
shortcuts={ {
[ rawShortcut.access( 'h' ) ]: toggleModal,
} }
/>
{ isModalActive && (
<Modal
className="edit-post-keyboard-shortcut-help"
title={ title }
closeLabel={ __( 'Close' ) }
onRequestClose={ toggleModal }
>

{ shortcutConfig.map( ( config, index ) => (
<ShortcutSection key={ index } { ...config } />
) ) }

</Modal>
) }
</Fragment>
);
}

export default compose( [
withSelect( ( select ) => ( {
isModalActive: select( 'core/edit-post' ).isModalActive( MODAL_NAME ),
} ) ),
withDispatch( ( dispatch, { isModalActive } ) => {
const {
openModal,
closeModal,
} = dispatch( 'core/edit-post' );

return {
toggleModal: () => isModalActive ? closeModal() : openModal( MODAL_NAME ),
};
} ),
] )( KeyboardShortcutHelpModal );
56 changes: 56 additions & 0 deletions edit-post/components/keyboard-shortcut-help-modal/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
.edit-post-keyboard-shortcut-help {
&__title {
font-size: 1rem;
font-weight: bold;
}

&__section {
margin: 0 0 2rem 0;
}


&__section-title {
font-size: 0.9rem;
font-weight: bold;
}

&__shortcut {
display: flex;
align-items: center;
padding: 0.6rem 0;
border-top: 1px solid $light-gray-500;

&:last-child {
border-bottom: 1px solid $light-gray-500;
}
}

&__shortcut-term {
flex: 1;
order: 1;
text-align: right;
font-weight: bold;
margin: 0 0 0 1rem;
}

&__shortcut-description {
order: 0;
margin: 0;
}

&__shortcut-key-combination {
background: none;
margin: 0;
padding: 0;
}

&__shortcut-key {
padding: 0.25rem 0.5rem;
border-radius: 8%;
margin: 0 0.2rem 0 0.2rem;

&:last-child {
margin: 0 0 0 0.2rem;
}
}
}
Loading

0 comments on commit 0a21147

Please sign in to comment.