From b707da35d080439e7f4365a794ca6b13d2817745 Mon Sep 17 00:00:00 2001 From: Ferran Recio Date: Thu, 27 Jul 2023 16:45:39 +0200 Subject: [PATCH] MDL-78665 tool_componentlibrary: add action menu page --- .../content/moodle/components/actionmenu.md | 212 ++++++++++++++++++ .../componentlibrary/examples/actionmenu.php | 159 +++++++++++++ 2 files changed, 371 insertions(+) create mode 100644 admin/tool/componentlibrary/content/moodle/components/actionmenu.md create mode 100644 admin/tool/componentlibrary/examples/actionmenu.php diff --git a/admin/tool/componentlibrary/content/moodle/components/actionmenu.md b/admin/tool/componentlibrary/content/moodle/components/actionmenu.md new file mode 100644 index 00000000000..b9102221131 --- /dev/null +++ b/admin/tool/componentlibrary/content/moodle/components/actionmenu.md @@ -0,0 +1,212 @@ +--- +layout: docs +title: "Action menus" +description: "A reusable action menu component" +date: 2023-07-27T10:10:00+08:00 +draft: false +tags: +- MDL-78665 +- "4.3" +--- + +## How it works + +Moodle action menus are a reusable component that can display a list of actions in a dropdown menu. They are used in many places in Moodle, including the user menu, the course administration menu, and the activity administration menu. + +## Source files + +- `lib/outputcomponents.php`: contains the main `action_menu`, `action_menu_link` and `pix_icon`. +- `lib/classes/output/local/action_menu/subpanel.php`: contains the `subpanel` menu item class. +- `lib/templates/action_menu.mustache`: contains the main template for the action menu. +- `lib/templates/action_menu_*`: location for the legacy auxliar mustache files. +- `lib/templates/local/action_menu/*`: location for any new auxiliar mustache files. + +## Examples + + + + +## Usage + +### Rendering an action menu + +The component output classes can render an action menu entirely in PHP. The steps to do it are: + +1. Create an action menu instance (with or without items) +2. (optional) Setup the action menu trigger +3. (optional) Add items to the menu (if they are not added on creation) +4. Render the menu. + +The following code is a basic example of an action menu: + +{{< php >}} +/** @var core_renderer $output*/ +$output = $PAGE->get_renderer('core'); + +$menu = new action_menu(); + +// Add items. +$menu->add(new action_menu_link( + new moodle_url($PAGE->url, ['foo' => 'bar']), + new pix_icon('t/emptystar', ''), + 'Action link example', + false +)); + +echo $output->render($menu); +{{< / php >}} + +And this is the same example but passing the items in the creation: + +{{< php >}} +/** @var core_renderer $output*/ +$output = $PAGE->get_renderer('core'); + +$menu = new action_menu([ + new action_menu_link( + new moodle_url($PAGE->url, ['foo' => 'bar']), + new pix_icon('t/emptystar', ''), + 'Action link example', + false + ), +]); + +echo $output->render($menu); +{{< / php >}} + +### Setup the menu trigger + +By default, the action menu trigger is a cog icon. However, the class has methods to convert it to a kebab menu or even display any arbitrary content. + +Example of a kebab menu: + +{{< php >}} +/** @var core_renderer $output*/ +$output = $PAGE->get_renderer('core'); + +$menu = new action_menu(); +$menu->set_kebab_trigger(get_string('edit'), $output); +$menu->set_additional_classes('fields-actions'); +{{< / php >}} + +Example of a custom trigger: + +{{< php >}} +/** @var core_renderer $output*/ +$output = $PAGE->get_renderer('core'); + +$menu = new action_menu(); +$menu->set_menu_trigger(get_string('edit')); +{{< / php >}} + +### Add items + +Items can be added as an array on creation or using the `add` method. Depending on the param passed to `add` the item can be displayed in two different locations: + +Primary items: are displayed next to the trigger button as direct actions. +Secondary items: are displayed inside the action menu dropdown. + +The item location must be configured before adding the element. The following example shows different ways to add primary and secondary menu items. + +{{< php >}} +// Primary items examples. +$menu->add(new action_menu_link( + new moodle_url($PAGE->url), + new pix_icon('t/emptystar', ''), + 'Action link example', + true +)); +$menu->add(new action_menu_link_primary( + $PAGE->url, + new pix_icon('t/emptystar', ''), + 'Action link example', +)); + +// Secondary items examples. +$menu->add(new action_menu_link( + new moodle_url($PAGE->url), + new pix_icon('t/emptystar', ''), + 'Action link example', + false +)); +$menu->add(new action_menu_link_secondary( + $PAGE->url, + new pix_icon('t/user', ''), + 'Action link example', +)); +{{< / php >}} + +## Types of items + +The `add` method accepts several item types. + +### `action_menu_link` + +The `action_menu_link` class is the generic class for link items. It has several construct params: + +- `moodle_url $url`: the link URL. +- `pix_icon $icon`: an optional pix_icon. If none passed, the item will show the trigger icon or none if it is a kebab menu. +- `string $text`: the text to display. +- `bool $primary`: if the item is primary or secondary. By default, all items are primary. +- `array $attributes`: an optional array of HTML attributes. + +Two convenience classes extend `action_menu_link`: + +- `action_menu_link_primary`: will be added as a primary item. +- `action_menu_link_secondary`: will be added as a secondary item. + +### `pix_icon` + +The action menu can render `pix_icon` as primary actions. The `pix_icon` is a standard output class for generating icons in Moodle. + +Construct params: + +- `String $pix`: the internal icon location. For example, "t/user". +- `String $alt`: an optional alternative text +- `String $component`: the pix icon component. By default, only core icons from the `pix` folder will be used +- `Array $attributes`: optional HTML attributes. + +### `core\output\local\action_menu\subpanel` + +The `core\output\local\action_menu` allow the `action_menu` to add items that display subpanels when hovered or clicked. + +Construct params: + +- `string $text`: text to display in the menu item +- `renderable $subpanel`: the output to render inside the subpanel. This param should be renderable using the standard `output::render` method. +- `array $attributes` optional HTML attributes + +The following example creates a subpanel using a renderable choicelist instance: + +{{< php >}} +/** @var core_renderer $output*/ +$output = $PAGE->get_renderer('core'); + +// A choice list is a renderable class to outpout a user choice. +$choice = new core\output\choicelist('Choice example'); +$choice->add_option("statusa", "Status A", [ + 'url' => $PAGE->url, + 'description' => 'Status A description', + 'icon' => new pix_icon('t/user', '', ''), +]); +$choice->add_option("statusb", "Status B", [ + 'url' => $PAGE->url, + 'description' => 'Status B description', + 'icon' => new pix_icon('t/groupv', '', ''), +]); +$choice->set_selected_value('statusb'); + +$menu = new action_menu(); + +// Add subpanel item. +$menu->add(new core\output\local\action_menu\subpanel( + 'Subpanel example', + $choice +)); + +echo $output->render($menu); +{{< / php >}} + +### HTML string + +If a plain string is added to an action_menu, the action_menu::add method will be printed as it is inside the dropdown menu (as a secondary item). diff --git a/admin/tool/componentlibrary/examples/actionmenu.php b/admin/tool/componentlibrary/examples/actionmenu.php new file mode 100644 index 00000000000..0721fb41e81 --- /dev/null +++ b/admin/tool/componentlibrary/examples/actionmenu.php @@ -0,0 +1,159 @@ +. + +/** + * Moodle Component Library + * + * A sample of a default action menu. + * + * @package tool_componentlibrary + * @copyright 2023 Ferran Recio + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +declare(strict_types=1); + +require_once(__DIR__ . '/../../../../config.php'); + +global $PAGE; + +$PAGE->set_url(new moodle_url('/admin/tool/componentlibrary/examples/actionmenu.php')); +$PAGE->set_context(context_system::instance()); +$PAGE->set_pagelayout('embedded'); + +$PAGE->set_heading('Moodle action menus'); +$PAGE->set_title('Moodle action menus'); + +/** @var core_renderer $output*/ +$output = $PAGE->get_renderer('core'); + +// Some menu items require as renderable element. This is just an +// example of a choice list but it can be any other renderable. +$choice = new core\output\choicelist('Choice example'); +$choice->add_option("statusa", "Status A", [ + 'url' => $PAGE->url, + 'description' => 'Status A description', + 'icon' => new pix_icon('t/user', '', ''), +]); +$choice->add_option("statusb", "Status B", [ + 'url' => $PAGE->url, + 'description' => 'Status B description', + 'icon' => new pix_icon('t/groupv', '', ''), +]); +$choice->set_selected_value('statusb'); + +// Those are some examples of action items. + +// Action menu links is the most used action item. +$basicactionlink = new action_menu_link( + new moodle_url($PAGE->url), + new pix_icon('t/emptystar', ''), + 'Action link example', + false +); + +// Subpanels display lateral panels on hovered or clicked. +$subpanel = new core\output\local\action_menu\subpanel( + 'Subpanel example', + $choice +); + +echo $output->header(); + +echo '

Important note: actions menus are not prepared + to be displayed inside iframes. You may need to scroll to see the + action menu options.

'; + +echo $output->heading("Action menu default example", 4); + +$menu = new action_menu(); + +$menu->add($basicactionlink); +$menu->add($basicactionlink); +$menu->add($subpanel); +$menu->add($basicactionlink); + +echo '
'; +echo '
Example of default an action menu
'; +echo $OUTPUT->render($menu); +echo '
'; + +echo $output->heading("Kebab menu example", 4); + +$menu = new action_menu(); +$menu->set_kebab_trigger(get_string('edit'), $output); +$menu->set_additional_classes('fields-actions'); + +$menu->add($basicactionlink); +$menu->add($basicactionlink); +$menu->add(new core\output\local\action_menu\subpanel( + 'Subpanel example', + $choice +)); +$menu->add($basicactionlink); + +echo '
'; +echo '
Example of kebab menu
'; +echo $OUTPUT->render($menu); +echo '
'; + +echo $output->heading("Custom trigger menu example", 4); + +$menu = new action_menu(); +$menu->set_menu_trigger(get_string('edit')); + +$menu->add($basicactionlink); +$menu->add($basicactionlink); +$menu->add(new core\output\local\action_menu\subpanel( + 'Subpanel example', + $choice +)); +$menu->add($basicactionlink); + +echo '
'; +echo '
Example of kebab menu
'; +echo $OUTPUT->render($menu); +echo '
'; + +echo $output->heading("Primary actions menu example", 4); + +$menu = new action_menu(); +$menu->set_menu_trigger(get_string('edit')); + +$menu->add($basicactionlink); +$menu->add($basicactionlink); +$menu->add(new core\output\local\action_menu\subpanel( + 'Subpanel example', + $choice +)); +$menu->add($basicactionlink); +$menu->add(new action_menu_link_primary( + $PAGE->url, + new pix_icon('t/emptystar', ''), + 'Action link example', +)); +$menu->add(new action_menu_link_primary( + $PAGE->url, + new pix_icon('t/user', ''), + 'Action link example', +)); + +echo '
'; +echo '
Example of a menu with primary actions
'; +echo $OUTPUT->render($menu); +echo '
'; + +echo $output->footer();