Grouped items
SplitItem radio works well:
<?php
use PhpSchool\CliMenu\Builder\SplitItemBuilder;
use PhpSchool\CliMenu\CliMenu;
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
require_once(__DIR__ . '/../vendor/autoload.php');
$menu = (new CliMenuBuilder)
->setTitle('Header 1')
->addSplitItem(function (SplitItemBuilder $b) use ($itemCallable) {
$b->addRadioItem('Item 1-A', function() {})
->addRadioItem('Item 1-B', function() {})
->addRadioItem('Item 1-C', function() {})
;
})
->build();
$menu->open();
But it's not possible to have multiple groups of RadioItem within the same menu level:
$menu = (new CliMenuBuilder)
->addStaticItem('Header 1')
->addRadioItem('Item 1-A', function() {})
->addRadioItem('Item 1-B', function() {})
->addRadioItem('Item 1-C', function() {})
->addLineBreak('---')
->addStaticItem('Header 2')
->addRadioItem('Item 2-A', function() {})
->addRadioItem('Item 2-B', function() {})
->addRadioItem('Item 2-C', function() {})
->build();
$menu->open();

Similarly, I want to be able to group non-RadioItem items together.
I'm thinking a non-styled container item that can take any number of MenuItemInterface items.
It has the following API:
-
addItem() -
addItems() -
setItems() -
removeItem()
If it contains no items, the parent CliMenu displays nothing - it is only a container of items and has no styling of its own, nor does it affect the UI.
If it has items, it behaves as if those items were defined in-line with the parent menu.
Example:
$menu = (new CliMenuBuilder)
->addStaticItem('Header 1')
->addGroup(function (CliMenuBuilder $b) {
$b->addRadioItem('Item 1-A', function() {})
->addRadioItem('Item 1-B', function() {})
->addRadioItem('Item 1-C', function() {})
;
})
->addLineBreak('---')
->addStaticItem('Header 2')
->addGroup(function (CliMenuBuilder $b) {
$b->addRadioItem('Item 2-A', function() {})
->addRadioItem('Item 2-B', function() {})
->addRadioItem('Item 2-C', function() {})
;
})
->build();
$menu->open();
This would look identical to the GIF above.
If no items are defined,
$menu = (new CliMenuBuilder)
->addStaticItem('Header 1')
->addGroup(function (CliMenuBuilder $b) {
$b->addRadioItem('Item 1-A', function() {})
->addRadioItem('Item 1-B', function() {})
->addRadioItem('Item 1-C', function() {})
;
})
->addLineBreak('---')
->addStaticItem('Header 2')
->addGroup(function (CliMenuBuilder $b) {
})
->build();
$menu->open();
then it acts as if the group isn't defined at all:

This will help group RadioItems in a vertical manner (without needing to use SplitItem), and allow grouping other item types for non-Menu work.
In addition, I would suggest changing RadioItem::getSelectAction() to use this group feature to disable other items within the same group, vs using SplitItem.
If the radio item does not belong to a group, behave as it already does and toggle off other radio items within the same CliMenu object.
edit:
Thinking about this, for initial PR it would be good to keep it simple and not give this class any styling at all. Simply a container, nothing else, but I could see it expending to keeping its own copy of styles and applying them to any children items.
So this would basically end up being a submenu that's visible on the current menu without needing to select an item to view the children items within.
Seems SplitItem handles item selection differently since it displays data horizontally, so it keeps a different selected index to the rest of the parent menu.
It sounds like a logical next step. If was already thinking of this myself. It could have getChecked() method which returns the checked items. If we can implement this in a nice clean way without lots of special casing and touching lots of files I'd be happy to include it.