-
-
Notifications
You must be signed in to change notification settings - Fork 167
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
Menu improvements #423
base: main
Are you sure you want to change the base?
Menu improvements #423
Conversation
Fold it all into Link instead
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 quite a change in syntax, but I believe this PR improves it.
- Some docblocks are incorrect or "incomplete"
- I prefer using "hotkey" instead of "accelerator."
- I got a bug with my custom event on a menu item throwing an exception because of a missing named argument on my constructor. I think we should either ask devs to extend
MenuItemClicked
with their event or better create a contract that they should implement with the following constructor:public function __construct(public array $item, public array $combo = [])
Overall it's great!
Also we should add a note in the documentation stating that we cannot change the name of the first menu in macOS. Those two examples does not work, always shows with config('app.name')
:
Menu::create(Menu::edit())
Menu::create(Menu::make()->label('My label'))
use Native\Laravel\Menu\Items\Separator; | ||
|
||
/** | ||
* @method static \Native\Laravel\Menu\Menu make(MenuItem ...$items) |
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 references the wrong MenuItem, it should reference Native\Laravel\Menu\Items\MenuItem
* @method static \Native\Laravel\Menu\Menu make(MenuItem ...$items) | ||
* @method static Checkbox checkbox(string $label, bool $checked = false, ?string $hotkey = null) | ||
* @method static Label label(string $label) | ||
* @method static Link link(string $url, string $label = null, ?string $hotkey = null) |
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 named $hotkey here and $accelerator in the class.
I prefer $hotkey
@@ -3,11 +3,15 @@ | |||
namespace Native\Laravel\Menu\Items; | |||
|
|||
use Native\Laravel\Contracts\MenuItem as MenuItemContract; | |||
use Native\Laravel\Facades\Menu as MenuFacade; | |||
use Native\Laravel\Menu\Menu; | |||
|
|||
abstract class MenuItem implements MenuItemContract |
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.
Can we create an alias to accelerator() as hotkey() ?
@@ -12,7 +12,7 @@ class MenuItemClicked implements ShouldBroadcastNow | |||
{ | |||
use Dispatchable, InteractsWithSockets, SerializesModels; | |||
|
|||
public function __construct(public array $item) {} | |||
public function __construct(public array $item, public array $combo = []) {} |
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.
Can we add some PHP Doc here to represent:
array:2 [▼
"item" => array:2 [▼
"label" => "Settings"
"checked" => false
]
"combo" => array:5 [▼
"shiftKey" => false
"ctrlKey" => false
"altKey" => false
"metaKey" => false
"triggeredByAccelerator" => false
]
]
Honestly this works great! I've tinkered with it a bit now. One thing I might be missing. Context menu's were mentioned. Is it possible to trigger a menu in-place on a button click? This doesn't work right now and could be a cool addition. I've got a alpine magic I use for this. I'm happy to extract that to the Native helper if you want. Right now it looks like this: <button
type="button"
x-on:click="
$contextMenu([
new MenuItem({
label: 'Foo',
}),
new MenuItem({
label: 'Bar',
}),
])
"
>
It does involve adding the MenuItem class to the window scope. But that can be namespaced under the Native helper if needed. I haven't tested this, but it might be feasible to add this to the php api instead. The code is pretty slim. |
Turns out using |
@gwleuverink that context menu stuff looks super cool! Fancy wrapping whatever you've needed to modify there into a new PR? |
Done! NativePHP/electron#140 |
Heads up, this introduces some significant breaking changes!
Depends on NativePHP/electron#139
We've been discussing internally for a while how the Menu API sucks a little. There are a few quirks, it doesn't really expose the stuff you probably want, and it just feels awkward, it doesn't feel very "Laravel".
You
new()
up a menu and then you have toregister()
it, which is what sets it as the application menu. It's not immediately obvious (imo) that you can omitregister()
and pass the resultingMenu
to other things like Windows, the MenuBar and the Dock.Defining items that should be in a list and can be nested inside each other as part of fluent chain feels really strange. You have to 'break' the chain (conceptually) in places that make it feel awkward and inconsistent, and the code ends up looking jarring rather than familiar.
The fluent chain is nice, but because we're immediately adding sparse instances to the chained
Menu
we lose access to the underlyingMenuItem
classes and so can't make deeper customisations easily.It's currently impossible to change the application Menu once it's been defined.
So this is my attempt to improve on all of these issues by:
Menu
facade which wraps a newMenuBuilder
classThis menu builder let's you access the underlying
MenuItem
objects more easily and build your menus with a more expressive DX. More on this in a moment...MenuItem
types that map to standard OS functions (calledRoles
)Link
menu items default to changing the currently-focused window's URL onclick without any extra wiring.If you want to open in the user's browser (the current default), you will be able to chain the new
->openInBrowser()
method toMenu::link()
Menu
objects, which are aMenuItem
too) definable in a more consistent, expressive waydefault()
helper to create the default menu even more easilyMenuItem
instances - useful in handling genericMenuItemClicked
events on the Laravel sideHere's what this looks like:
Create the application menu
Before
After
Menu::create
builds the menu and registers it all in one shot.Create a menu for use elsewhere (e.g. as a context menu, Dock menu, or MenuBar menu)
Before
After
Define the default menu
Before
After
Menu::default()
allows you to easily return your menu to the default that would be provided if you didn't register a menu at all.Define a custom menu
Before
After
Menu::make()
returns aNative\Laravel\Menu\Menu
instance.Many of the other helpers return a
MenuItem
subclass, from which you can chain calls to their other methods.This gives you far more control over your menus. Building your menus has never been more straightforward.
Define a blank menu
Before
After