-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Add shortcut tooltips for main toolbar #6605
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we'll need to tweak the redo shortcut for Mac. That'll at least mess with some Safari folks.
components/icon-button/index.js
Outdated
const showTooltip = !! tooltip || | ||
// Should show the tooltip... | ||
const showTooltip = ( | ||
// if an explicit tooltip is passed or... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find this style of commenting each conditional really useful, especially after working on a patch around https://github.com/WordPress/gutenberg/blob/master/editor/components/block-list/block.js#L425 👍🏻
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A nitpick is moving the "if" above might make more sense, eg:
// Should show the tooltip if...
const showTooltip = (
// an explicit tooltip is passed or...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So move all "if"s? "Or if..."?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think moving the if to the top and ending each line with or...
or and...
, along with the indentation, would make sense.
But what you have already makes sense, I just think the wording could be tidied up a bit. If my suggestion is less clear than I could be wrong and should be ignored 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd say it could be:
// Should show the tooltip if...
const showTooltip = (
// an explicit tooltip is passed or...
tooltip ||
// there's a shortcut or...
shortcut ||
(
// there's a label and...
label &&
// the children are empty and...
( ! children || ( isArray( children ) && ! children.length ) ) &&
// the tooltip is not explicitely disabled.
false !== tooltip
)
);
(Includes the lack of !!
prefixes.)
components/icon-button/index.js
Outdated
// Should show the tooltip... | ||
const showTooltip = ( | ||
// if an explicit tooltip is passed or... | ||
!! tooltip || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason to use !! tooltip ||
rather than just the regular test for truthiness with tooltip ||
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. I copied the previous code.
components/icon-button/index.js
Outdated
( ! children || ( isArray( children ) && ! children.length ) ) && | ||
// the tooltip is not explicitely disabled. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"explicitely" should be "explicitly" 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ugh yes, I just copied from the previous comment. :)
function EditorHistoryRedo( { hasRedo, redo } ) { | ||
return ( | ||
<IconButton | ||
icon="redo" | ||
label={ __( 'Redo' ) } | ||
shortcut={ primaryShortcut( 'Y' ) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shift+Command+Z
is the convention for "Redo" on Mac, so I wonder if we need yet another conditional helper here 😧
Command+Y
in Safari will actually change the current page to the History page, even when a textarea is focused:
So this probably needs to be Shift+Command+Y
or Shift+Command+Z
, at least on MacOS.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sublime is probably an outlier because it's cross-platform and I think cares less about OS-specific stuff? Browsers are definitely all Shift+Command+Z
:
Makes sense Sublime does Primary+Y
as that's the Windows/Linux default. I checked in Edge and Primary+Y
is redo there. Firefox in Windows uses Primary+Shift+Z
. It's sort of a mess. Maybe we need a helper that does UA sniffing for this one? 😭
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I spoke too soon. Edge also supports Primary+Shift+Z
for redo in Gutenberg. Primary+Y
is the default but it seems Edge (and all other browsers) also work with Primary+Shift+Z
. I'm just testing Linux now but it works for Mac+Win...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Linux works with Primary+Shift+Z
too, so let's just use that one everywhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. Wondering if we should still keep Primary+Y
then as we are blocking the browser shortcuts on Mac.
I added a bit to the scope of this PR... It would be good if "raw" shortcodes can be used for both the I wanted to try to do this a bit more dynamically, but maybe it'd be just better to explicitly create all functions? Not sure. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
blocks/rich-text/index.js
Outdated
editor.shortcuts.add( 'access+d', '', () => this.changeFormats( { strikethrough: ! this.state.formats.strikethrough } ) ); | ||
editor.shortcuts.add( 'access+x', '', () => this.changeFormats( { code: ! this.state.formats.code } ) ); | ||
editor.shortcuts.add( rawShortcut.primary( 'k' ), '', () => this.changeFormats( { link: { isAdding: true } } ) ); | ||
editor.shortcuts.add( rawShortcut.access( 'a' ), '', () => this.changeFormats( { link: { isAdding: true } } ) ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yay, when I saw these I thought "this could be refactored". This is great 👍
value: secondaryKeyCode( 'm' ), | ||
label: secondaryShortcut( 'M' ), | ||
value: rawShortcut.secondary( 'm' ), | ||
label: displayShortcut.secondary( 'm' ), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, the consistency here is better 👍
return `${ keyCombo }+${ character }`; | ||
} | ||
const modifiers = { | ||
primary: ( _isMac ) => _isMac() ? [ COMMAND ] : [ CTRL ], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is much more immediately understandable than my old way. ✨
export function secondaryShortcut( character, _isMacOS = isMacOS ) { | ||
return keyboardShortcut( secondaryKeyCode( character.toUpperCase(), _isMacOS ), _isMacOS ); | ||
} | ||
export const displayShortcut = mapValues( modifiers, ( modifier ) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, cool. Sorry I didn't think to use this, I'm not used to having lodash around.
} ); | ||
} ); | ||
|
||
describe( 'accessKeyCode', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like there are only tests for the rawShortcut
s are gone. I guess the logic is really basic now so it matters less that there are no tests. 🤷♂️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, good catch, forgot to add tests for rawShortcode...
I think it's fine to just create all the functions this way. It's not much code and it's very easy to trace and figure out. |
Thanks for the review @tofumatt! Wasn't sure if you'd like it. :) Added some of the tests back that I forgot. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New tests and changes looks good too! 🚢
Hm, on last thing to figure out: shift+command+z is not actually working with Mousetrap, neither in this branch nor in master. The callback is never called... (mod+z: this.undoOrRedo) |
Strange, here it works: https://codepen.io/iseulde/pen/BxwvBB |
Can't figure this one out immediately. In Codepen it works. |
In Gutenberg: In windows Ctrl+Shift+Z is working in master for me on Edge. On Mac Meta+Shift+Z is working in master for me on Firefox. 🤷♂️ |
Confirmed. Firefox and Safari work, it's just Chrome that is broken. Actually the Codepen is also broken there, I was just testing that in Safari instead of Chrome... Let's address this separately as this is also broken in master. |
return `${ keyCombo }+${ character }`; | ||
} | ||
const modifiers = { | ||
primary: ( _isMac ) => _isMac() ? [ COMMAND ] : [ CTRL ], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do these need to be run as functions? Will they ever change over the lifetime of the app?
Edit: And if the answer is for testing, it shouldn't really impact the implementation so much. Can be "good" for it to be made generic, though ideally we have some caching along the way in runtime use, so we're not running _window.navigator.platform.indexOf( 'Mac' ) !== -1;
hundreds of times per page session.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's all for testing; previously this was run once and stored in a constant, but it was also entirely untested. It could probably be cached somehow as a perf-versus-readability tradeoff. 😄
It shouldn't change in regular usage though, so yeah it's worth doing.
[ SHIFT ]: isMac ? '⇧shift' : 'Shift', | ||
}; | ||
const shortcut = [ | ||
...modifier( _isMac ).map( ( key ) => get( replacementKeyMap, key, key ) ), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You defeated my new ESLint custom rule! (#6247)
Which is to say, I should make this rule more strict 😛
const showTooltip = ( | ||
// an explicit tooltip is passed or... | ||
tooltip || | ||
// there's a shortcut or... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I mentioned elsewhere, but conceptually shortcut has nothing to do with IconButton
and I wish it wasn't included here.
Description
This branch adds some shortcuts to tooltips in the main toolbar:
Questions:
How has this been tested?
Hover over the above mentioned buttons in the main toolbar.
Screenshots
Types of changes
Checklist: