Skip to content
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

Allow selecting all options in a multiselect #147

Merged
merged 14 commits into from
May 27, 2024
Merged

Allow selecting all options in a multiselect #147

merged 14 commits into from
May 27, 2024

Conversation

duncanmcclean
Copy link
Contributor

Currently, when using the multiselect component, if you want to select all of the available options, you have to manually hit space + down until you've toggled all the options.

This is mostly fine. However, if you have 10 options, you might not want to force your users to manually select all the options. Instead, you might want to let them toggle a single option.

This PR adds a new canSelectAll property to the MultiSelectPrompt class, which if true, will show an "All" option at the top of the options:

CleanShot 2024-05-10 at 17 34 25

multiselect(
    label: 'Select your favourite Laravel packages',
    options: [
        'laravel/prompts',
        'laravel/pulse',
        'laravel/horizon',
        'laravel/octane',
        'laravel/jetstream',
    ],
    canSelectAll: true,
);

When enabled, it'll select all the options and when disabled it'll deselect them all. In the case the user enables the "All" option but subsequently goes to select one of the options, the "All" option will be deselected.

An alternative UX for this could be to somehow disable all of the other options when the "All" option is toggled so they can't be changed.

Let me know if you'd like me to make any changes and I'll do my best to do them. Otherwise, if this isn't something you want to add to Prompts, then that's fine as well, just an idea I had. ❤️

@taylorotwell taylorotwell marked this pull request as draft May 10, 2024 19:20
@jessarcher
Copy link
Member

Hey @duncanmcclean,

This is pretty cool!

My only real issue is the "All" option is included in the returned array, which could cause problems depending on what the user is doing with the response. We'd need to be careful filtering it out, though, in case someone already has their own "All" option which they expect to be returned.

I don't love that it gets injected into the $options array, but I can't think of a nicer way off the top of my head. I was thinking it should be a renderer concern, but the prompt class needs to know when it has been toggled.

I think the new parameter should also accept a string, allowing folks to change or localize the wording (similar to the required param). I'm also not totally sold on the parameter naming, but I don't have a better alternative now.

@macocci7
Copy link
Contributor

How about toggling when [Ctrl]+[A] is pressed?

@duncanmcclean
Copy link
Contributor Author

duncanmcclean commented May 14, 2024

My only real issue is the "All" option is included in the returned array, which could cause problems depending on what the user is doing with the response. We'd need to be careful filtering it out, though, in case someone already has their own "All" option which they expect to be returned.
I don't love that it gets injected into the $options array, but I can't think of a nicer way off the top of my head. I was thinking it should be a renderer concern, but the prompt class needs to know when it has been toggled.

Ah yeah, that's a problem.

I can probably refactor the "All" option to live in the renderer instead, rather than being merged into the actual options of the prompt.

I think the new parameter should also accept a string, allowing folks to change or localize the wording (similar to the required param). I'm also not totally sold on the parameter naming, but I don't have a better alternative now.

Good idea 👍

I also don't completely love the name of the parameter but it's the best I could come up with at the time. I'll see if I can think of a better name.

How about toggling when [Ctrl]+[A] is pressed?

That's a good idea. In fact, I think I actually prefer it to what I've done in this PR in adding a separate option.

However, it seems like there's already a keybinding for ctrl + a to navigate to the top of the options list so maybe we can't do that 🤔

@duncanmcclean
Copy link
Contributor Author

duncanmcclean commented May 20, 2024

@jessarcher

I've finally managed to carve out some time to work on refactoring this PR.

I've renamed the property to $selectAll (still don't totally love it but will do for now) and allowed for a string to be passed through.

I've also started to dive into moving the "select all" logic into the renderer, as suggested. However, I'm struggling to figure out the best way to prepend an option to the list without actually merging it into $this->options. 🤔

I'm likely missing something obvious, so if there's any pointers you can give me, that'd be great.

Like I mentioned in my previous comment, I actually quite like (or might even prefer) it being a keyboard shortcut, rather than a separate visual option. It would actually be very simple to implement (I built it in 5 minutes as a POC 😆 ). However, it looks like ctrl + a (the most likely candidate) has already been taken.

@jessarcher
Copy link
Member

jessarcher commented May 21, 2024

Keyboard shortcuts can be funny in the terminal. Ctrl+A is a Readline/Emacs thing (added in #70).

I believe it technically only applies to typed input (i.e. horizontal movement), so I'm open to remapping it.

I'm thinking the following could be good:

  • Ctrl+A selects all in multiselect and also when focused on the options list in multisearch. Ctrl+E would do nothing in these contexts.
  • In a text input (including the text input of a multisearch) Ctrl+A and Ctrl+E move to the beginning and end of the input (i.e. unchanged)
  • Home and End would remain unchanged everywhere (moving between the top and bottom of lists and the beginning and end of text inputs).

I'm hoping this is pretty straight-forward and would also remove the need for a parameter to be added, as this feature would always be active.

Although... Ctrl+A should only select all options when the user is in the context of the options, not when they're in the context of searching.
src/MultiSearchPrompt.php Show resolved Hide resolved
src/MultiSearchPrompt.php Outdated Show resolved Hide resolved
@duncanmcclean
Copy link
Contributor Author

@jessarcher Thanks for your suggestions - I've updated this PR to use keyboard shortcuts, rather than the separate "All" option.

This PR is ready for review, whenever you're able.

@jessarcher
Copy link
Member

Thanks @duncanmcclean! I've made a few minor tweaks to the key ordering just to keep related things together in my head.

Just need to figure out the right approach for that multisearch behaviour. I can probably jump in if you need a hand.

@jessarcher
Copy link
Member

(I've fixed the phpstan issue in the main branch)

Co-authored-by: Jess Archer <jess@jessarcher.com>
Copy link
Member

@jessarcher jessarcher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Really dig this feature.

@jessarcher jessarcher marked this pull request as ready for review May 27, 2024 10:04
@taylorotwell taylorotwell merged commit 9bc4df7 into laravel:main May 27, 2024
4 checks passed
@duncanmcclean duncanmcclean deleted the multiselect-select-all branch May 27, 2024 17:39
@pelmered
Copy link

There is an example in the documentation for a canSelectAll option here, but there is nothing in the code. When I googled I ended up here, but it seems like that option was reverted and replaced with a keyboard shortcut. So I guess that example should be deleted from docs then?

Great feature anyway!

pelmered added a commit to pelmered/docs that referenced this pull request Aug 21, 2024
It looks like this parameter was reverted and replaced with a keyboard shortcut. See the PR here: laravel/prompts#147
taylorotwell pushed a commit to laravel/docs that referenced this pull request Aug 21, 2024
It looks like this parameter was reverted and replaced with a keyboard shortcut. See the PR here: laravel/prompts#147
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants