Windows application menu take two #991

Merged
merged 116 commits into from Mar 28, 2017

Conversation

Projects
None yet
3 participants
Contributor

niik commented Mar 1, 2017 edited

This implements a custom menu bar component on Windows, see #836 for more details on why.

Navigating with mouse

menubar

Navigating with keyboard

This shows me hitting Alt+F to open the file menu and then O to open Options.

menubar-access-key

Things this does not do / known limitations

Full screen

The menu bar is currently not accessible when running the app in full-screen. I plan to tackle that in a separate PR rather than drag this out any longer.

Submenus

Sub menus are not handled with any grace at the moment. They work but they do not position themselves as one would expect. We currently don't have any sub menus for top level menus so I don't plan to tackle that until it becomes a problem as it is non-trivial to implement well.

image

Fixes #836

niik added some commits Feb 28, 2017

@niik niik Initial menu bar component f54243e
@niik niik Support disabling decorators in menu item 564cd6f
@niik niik Use menu item in app menu bar 7b220db
@niik niik Allow optional title for toolbar buttons 263231d
@niik niik Style the menu bar buttons 01eaab2
@niik niik Render app menu component 2fb4a2e
@niik niik Style access keys in toolbar menu buttons
3d89bc5
@niik niik Merge remote-tracking branch 'origin/master' into app-menu-take-two ad36578
@niik niik Merge remote-tracking branch 'origin/master' into app-menu-take-two 7f178ba
@niik niik Don't show app menu in welcome flow 7b6df5c
@niik niik Remove the app title
We're not using it for anything
56065f9
@niik niik Add in an app icon on windows 69623f2
@niik niik Bump the title bar height on windows
To accomodate for icon and menu bar
d1526b6
@niik niik Rudimentary styling for app menu bar
9a083b5
@niik niik Refactor menu bar buttons into separate component 6ccff31
@niik niik Don't style the menu bar icon on hover if open
591b5b9
@niik niik 🔥 debug log b1d9922
@niik niik Open and close menus properly
9386805
@niik niik Extract rectEquals function from dropdown 6c275f6
@niik niik Rudimentary menu height
b03365b
@niik niik Move app menu bar styles into app menu bar scss 50a869e
@niik niik Remove the old app menu icon 7306bec
@niik niik Move preferences into file menu on windows
3191afd
@niik niik Merge remote-tracking branch 'origin/master' into app-menu-take-two
ea40e18
@niik niik Switch menus when hovered
Only when some menu is open
c3cf8bb
@niik niik Keyboard left/right navigation between menus
e8a55c3
@niik niik Capture unhandled keypresses on toolbar button instead
This allows us to capture arrow keys even though no menu items have focus
5424f82
@niik niik Make sure we never extend beyond the confines of the window fa68572
@niik niik 🔥 debug log
4aeedba
@niik niik Merge remote-tracking branch 'origin/master' into app-menu-take-two bab2000
@niik niik Merge branch 'bump-keytar-types' into app-menu-take-two
e281d98

niik referenced this pull request Mar 14, 2017

Merged

Add an add menu #1018

niik added some commits Mar 14, 2017

@niik niik Merge remote-tracking branch 'origin/master' into app-menu-take-two cbad403
@niik niik Merge remote-tracking branch 'origin/add-this-again' into app-menu-ta…
…ke-two
e3ffb32
@niik niik Trailing comma 9e62afb
@niik niik Wire up menu bar to old foldout model 4e90a25
@niik niik 🎨 whitespace a951fa1
@niik niik Fix kerning issue when highlighting access keys 85f014b
@niik niik Merge remote-tracking branch 'origin/master' into app-menu-take-two
07212bc
@niik niik Merge remote-tracking branch 'origin/master' into app-menu-take-two
8f13477

niik added some commits Mar 16, 2017

@niik niik Work around faulty type signature in MenuItem#click d3b6a2a
@niik niik Merge remote-tracking branch 'origin/master' into app-menu-take-two 5ca9201
@niik niik Guard against open foldout but no menu f79e32d
@niik niik 📖 1ad64f3
@niik niik 📖
e13b936
@niik niik 🎨 typo b4db246
@niik niik 🎨 Cleanup 1fcd96c
@niik niik Only react to new props
Mistakenly used only props to get selected item
496ea30
@niik niik Ensure createState is pure f844cda
@niik niik No need to reset openedWithAccessKey
If it was open with access key once it'll have been opened with access key until it's closed
77eb312
@niik niik Hacks upon hacks upon hacks
3ee96cb
@niik niik 📖 410c99c
@niik niik 🎨 Extract creating state
This ensure a pure method that only relies on received props
cf5721e
@niik niik 🎨 indent 3e63a8e
@niik niik Access keys for edit menu items c336feb
@niik niik 📖 b4b2664

niik added some commits Mar 22, 2017

@niik niik Enable resizing from the top part of the title bar 1b03d2c
@niik niik Filter out invisible menu items 2708103
@niik niik Allow disabled top-level menu items
e8a7d06
@niik niik Shorten text so it fits in menus
There's precedence for this in the Repository menu where we do `View on GitHub`. Since this is under the branch menu it should be implied that we're referring to the branch
db113dd
@niik niik 🎨 typos 7228bfa
@niik niik 📖 this is no longer true 5ea47a2
@niik niik 📖 487ab63
@niik niik 📖 autoHeight 0043cfa
@niik niik 🎨 indentation 1b8b044
@niik niik This is not neccessary since we only render submenu items 7332ca7
@niik niik 📖 Mouse and Keyboard events 8631b3a
@niik niik 📖 AppMenuBarButton props 7c01bae
@niik niik 📖 MenuListItem props b84aab4
@niik niik 📖 Add note about where this event comes from
01543ca
@niik niik Rename highlight state to reflect that it's not just the button any more
d41d99b
@niik niik Export the AppMenu foldout type specifically 6c43ee8
@niik niik Trailing comma c4e7908
@niik niik 📖 AppMenuFoldout properties 77e87a7
@niik niik 📖 App menu bar
a408d44
@niik niik 🎨 Cleanup
ecc02b2
@niik niik 📖 onMouseEnter
05edbaa
@niik niik Merge remote-tracking branch 'origin/master' into app-menu-take-two
176184e

niik changed the title from [WIP] Windows application menu take two to Windows application menu take two Mar 22, 2017

Contributor

niik commented Mar 22, 2017

I believe this is finally ready for a first review!

niik referenced this pull request Mar 23, 2017

Merged

Remove Add Menu #1065

@niik niik Merge remote-tracking branch 'origin/master' into app-menu-take-two
57de02a
Contributor

shiftkey commented Mar 24, 2017 edited

Looking good so far. One question I have is around how the access keys are displayed.

What I was hoping to see was something like in Fiddler. Here's a GIF of me pressing ALT a couple of times with the window focused:

EDIT: having the File menu item be active when pressing ALT would actually be really great. But I'm fine to 👢 that to a follow-up PR.

It looks like this current version needs me to interact with the menu with my mouse while holding ALT to get these to show. The other way seems to be to press a known chord - e.g. ALT+F.

Is this something on your radar?

@shiftkey

This feels pretty great, and I'm happy to polish this further based on @niik's feels about addressing the access key visibility, rather than drag this out.

+
+ const delta = direction === 'next' ? 1 : -1
+
+ // http://javascript.about.com/od/problemsolving/a/modulobug.htm

shiftkey self-assigned this Mar 24, 2017

niik added some commits Mar 24, 2017

@niik niik This is not a thing any more c5bd77f
@niik niik Proper focus state for menu bar buttons 04dd287
@niik niik 📖 better docs 7f2123e
@niik niik Disable sequential keyboard navigation for menu buttons c30d188
@niik niik Expose focusing and retrieval of client rect through components 2a3538d
@niik niik Allow programmatic focus of menu button 7ef2a53
@niik niik Let consumers know why the menu was closed 8e846b7
@niik niik Move focus to button when menu is closed with Escape aea3153
@niik niik Add methods to remove focus from a button 191c452
@niik niik Need to import this 92ad564
@niik niik Expose button focus/blur events 691e50b
@niik niik Keep track of whether the menu bar button is foucsed c8d4e41
@niik niik Keep track of whether button in bar has focus bbe8729
@niik niik Expose blur method dd87e00
@niik niik Blur button on double-escape d73f97a
@niik niik Blur button when hovering other menu items 8818094
@niik niik Refs return null when unmounting, not undefined 7fbd2ab
@niik niik Use null instead of undefined
For consistency with ref callback
21e8594
@niik niik Track menu button instances c49e676
@niik niik Move focus between items when using arrow keys in collapsed mode af17749
@niik niik Open the menu when collapsed and receiving ArrowDown 1bea290
@niik niik 📖 c64af20
@niik niik 📖
afef5ef
@niik niik Merge remote-tracking branch 'origin/master' into app-menu-take-two
6c1cb2b
@niik niik We no longer have to keep track of whether we have focus
Checking whether we're collapsed or not should be enough
4db82fe
@niik niik Close menu if open and user presses Alt 47c448e
@niik niik Rename for consistency 8b47354
@niik niik We don't need this any more
The menu is closed in onWindowKeyDown
7999e8e
@niik niik Be good citizens and reset when closing ece1e57
@niik niik Focus (and blur) menu item when hitting Alt
dc986c8
@niik niik Initial windows menu documentation 10b8650
@niik niik some more interaction stuff d0702e6
@niik niik moar docs
88e4525
Contributor

niik commented Mar 27, 2017

EDIT: having the File menu item be active when pressing ALT would actually be really great. But I'm fine to 👢 that to a follow-up PR.

Good catch, we should indeed support that scenario. I modeled the interactions after how Notepad does things as that seemed like a good example of how things should be done. I've documented some of my findings in https://github.com/desktop/desktop/blob/88e4525ac9f8f94392eff44ca35f8e891557ed8b/docs/windows-menu-bar.md

I'm pretty happy with the current state so it's time for another look

menubar-focus-opt

@shiftkey

Shout out to some great docs. I'm mostly nit-picking things now.

I'd also love @joshaber or @iAmWillShepherd to pull this down and test it out a bit, just incase I've missed something.

docs/windows-menu-bar.md
+
+## Keyboard navigation
+
+When a user is holding down the `ALT` key the access-keys (which is separate from
@shiftkey

shiftkey Mar 28, 2017

Contributor

Reviewer's note: if you're using something like Parallels here you might see the Option/ALT key behave differently during testing this - it'll raise the keydown and keyup events after you release the key on the host OS.

If you bust out your Onscreen Keyboard in the guest OS you'll see the right timing for events be sent to the app.

docs/windows-menu-bar.md
+File -> New Branch item a user should be able to press `ALT+F` followed by `B`.
+
+Pressing the `ALT` key and releasing it without pressing an access key should
+put focus on the first top level menu item if no menu is currently expanded. If
@shiftkey

shiftkey Mar 28, 2017

Contributor

This one is also relevant to your test setup, in case you're in a VM.

app/src/ui/app-menu/menu-list-item.tsx
+ * Whether or not to render the accelerator (shortcut) next to the label.
+ * This can be turned off when the menu item is used as a stand-alone item
+ */
+ readonly renderAcceleratorText?: boolean
@shiftkey

shiftkey Mar 28, 2017

Contributor

Is it worth calling out the default behaviour here when no value is defined? Both this and renderSubMenuArrow seem to default to rendering when no value set, which might be confusing to the caller...

@niik

niik Mar 28, 2017

Contributor

Good call

app/src/ui/app.tsx
private renderTitlebar() {
const winControls = __WIN32__
? <WindowControls />
: null
+ // On windows it's not possible to resize a frameless window if the
@shiftkey

shiftkey Mar 28, 2017

Contributor

capital W for Windows

+ private onKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
+
+ if (event.key === 'Escape') {
+ // Are we currently collapsed?
@shiftkey

shiftkey Mar 28, 2017

Contributor

Duplicate comments and checks make me think this check could be extracted a variable or function to make this easier to understand. Thoughts?

niik added some commits Mar 28, 2017

@niik niik ___---=== [ WINDOWS ] ===---___ c5c5b6e
@niik niik Invert logic, 📖 b2ee85e
@niik niik 📖 d2291c9
@niik niik Use some snazzy styling for keyboard shortcuts
b1e3930
@niik niik 🎨 Cleanup
73ef765
Contributor

niik commented Mar 28, 2017

🔊

joshaber referenced this pull request Mar 28, 2017

Merged

No menu for you #1082

Contributor

joshaber commented Mar 28, 2017

Damn, this is a hell of a thing. Works well in the cursory testing I did 👍

- ? 'open'
- : 'closed'
-
+ const dropDownState = this.isMenuOpen ? 'open' : 'closed'
@shiftkey

shiftkey Mar 28, 2017

Contributor

We seem to have dropped the openMenu && openMenu.id === item.id check here as part of the refactoring. No longer necessary?

@niik

niik Mar 28, 2017

Contributor

Nope, this is ensured at the parent component already, it was a remnant from a colder darker era

@shiftkey

shiftkey Mar 28, 2017

Contributor

Then onward and upward!

shiftkey merged commit 470c123 into master Mar 28, 2017

2 checks passed

continuous-integration/appveyor/pr AppVeyor build succeeded
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details

shiftkey deleted the app-menu-take-two branch Mar 28, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment