{ "cells": [ { "cell_type": "code", "execution_count": null, "id": "a1", "metadata": {}, "outputs": [], "source": [ "import panel as pn\n", "import panel_material_ui as pmui\n", "\n", "pn.extension()" ] }, { "cell_type": "markdown", "id": "a2", "metadata": {}, "source": [ "The `MenuBar` component provides a horizontal application menu bar, similar to those found in desktop applications (File, Edit, View, Help). It supports nested submenus, keyboard shortcut hints, icons, checkboxes, radio groups, item groups, and dividers.\n", "\n", "## Item Structure\n", "\n", "The top-level `items` list defines the menu triggers (buttons) in the bar. Each top-level item should have:\n", "\n", "- **`label`** (`str`, required): The button text.\n", "- **`icon`** (`str`, optional): Icon displayed before the label.\n", "- **`disabled`** (`bool`, optional): Whether the entire menu is disabled.\n", "- **`items`** (`list[dict]`, required): The dropdown items for this menu.\n", "\n", "Each dropdown item can be:\n", "\n", "- A **regular item**: `{'label': 'Save', 'icon': 'save', 'hint': 'Ctrl+S'}`\n", "- A **divider**: `None` or `{'label': '---'}`\n", "- A **submenu**: `{'label': 'Share', 'icon': 'share', 'items': [...]}`\n", "- A **group header**: `{'label': 'Alignment', 'group': True, 'items': [...]}`\n", "- A **checkbox item**: `{'label': 'Show Toolbar', 'checkbox': True}`\n", "- A **radio item**: `{'label': 'Light', 'radio': 'light'}`\n", "\n", "## Parameters\n", "\n", "### Core\n", "\n", "- **`active`** (`tuple[int, ...]`): Index path of the last clicked item.\n", "- **`items`** (`list[dict]`): Top-level menus with their dropdown items.\n", "- **`value`** (`dict`): The last clicked item.\n", "\n", "### Display\n", "\n", "- **`color`** (`str`): Color of the menu bar buttons. One of `'default'`, `'primary'`, `'secondary'`, `'success'`, `'info'`, `'warning'`, `'error'`.\n", "- **`size`** (`str`): Size of the menu buttons: `'small'`, `'medium'`, or `'large'`.\n", "- **`variant`** (`str`): Visual style of the bar container: `'elevation'` or `'outlined'`.\n", "\n", "### Styling\n", "\n", "- **`sx`** (`dict`): Component-level styling API.\n", "- **`theme_config`** (`dict`): Theming API.\n", "\n", "---" ] }, { "cell_type": "markdown", "id": "a3", "metadata": {}, "source": [ "## Basic Usage\n", "\n", "A simple menu bar with File, Edit, and Help menus:" ] }, { "cell_type": "code", "execution_count": null, "id": "a4", "metadata": {}, "outputs": [], "source": [ "menu_bar = pmui.MenuBar(items=[\n", " {'label': 'File', 'items': [\n", " {'label': 'New', 'icon': 'note_add', 'hint': 'Ctrl+N'},\n", " {'label': 'Open', 'icon': 'folder_open', 'hint': 'Ctrl+O'},\n", " {'label': 'Save', 'icon': 'save', 'hint': 'Ctrl+S'},\n", " {'label': 'Save As...', 'icon': 'save_as', 'hint': 'Ctrl+Shift+S'},\n", " None,\n", " {'label': 'Exit', 'icon': 'close'},\n", " ]},\n", " {'label': 'Edit', 'items': [\n", " {'label': 'Undo', 'icon': 'undo', 'hint': 'Ctrl+Z'},\n", " {'label': 'Redo', 'icon': 'redo', 'hint': 'Ctrl+Y'},\n", " None,\n", " {'label': 'Cut', 'icon': 'content_cut', 'hint': 'Ctrl+X'},\n", " {'label': 'Copy', 'icon': 'content_copy', 'hint': 'Ctrl+C'},\n", " {'label': 'Paste', 'icon': 'content_paste', 'hint': 'Ctrl+V'},\n", " ]},\n", " {'label': 'Help', 'items': [\n", " {'label': 'Documentation', 'icon': 'menu_book'},\n", " {'label': 'About', 'icon': 'info'},\n", " ]},\n", "], margin=(0, 0, 200, 0))\n", "\n", "menu_bar" ] }, { "cell_type": "markdown", "id": "a5", "metadata": {}, "source": [ "Clicking an item updates both `active` (the index path) and `value` (the item dict):" ] }, { "cell_type": "code", "execution_count": null, "id": "a6", "metadata": {}, "outputs": [], "source": [ "menu_bar.active, menu_bar.value" ] }, { "cell_type": "markdown", "id": "a7", "metadata": {}, "source": [ "## Nested Submenus\n", "\n", "Items with an `items` key (and no `group` key) render as fly-out submenus:" ] }, { "cell_type": "code", "execution_count": null, "id": "a8", "metadata": {}, "outputs": [], "source": [ "pmui.MenuBar(items=[\n", " {'label': 'File', 'items': [\n", " {'label': 'New', 'icon': 'note_add'},\n", " {'label': 'Open Recent', 'icon': 'history', 'items': [\n", " {'label': 'project_v2.py'},\n", " {'label': 'analysis.ipynb'},\n", " {'label': 'dashboard.py'},\n", " ]},\n", " None,\n", " {'label': 'Share', 'icon': 'share', 'items': [\n", " {'label': 'Email Link', 'icon': 'email'},\n", " {'label': 'Copy Link', 'icon': 'link'},\n", " {'label': 'Export PDF', 'icon': 'picture_as_pdf'},\n", " ]},\n", " None,\n", " {'label': 'Close', 'icon': 'close', 'hint': 'Ctrl+W'},\n", " ]},\n", "], margin=(0, 0, 200, 0))" ] }, { "cell_type": "markdown", "id": "a9", "metadata": {}, "source": [ "## Checkbox Items\n", "\n", "Items with a `checkbox` key render a checkbox. The value toggles when clicked and updates the `items` in-place:" ] }, { "cell_type": "code", "execution_count": null, "id": "a10", "metadata": {}, "outputs": [], "source": [ "view_menu = pmui.MenuBar(items=[\n", " {'label': 'View', 'items': [\n", " {'label': 'Show Toolbar', 'checkbox': True},\n", " {'label': 'Show Sidebar', 'checkbox': True},\n", " {'label': 'Show Status Bar', 'checkbox': False},\n", " None,\n", " {'label': 'Full Screen', 'icon': 'fullscreen', 'hint': 'F11'},\n", " ]},\n", "], margin=(0, 0, 200, 0))\n", "\n", "view_menu" ] }, { "cell_type": "markdown", "id": "a11", "metadata": {}, "source": [ "After toggling checkboxes, the updated state is reflected on `items`:" ] }, { "cell_type": "code", "execution_count": null, "id": "a12", "metadata": {}, "outputs": [], "source": [ "view_menu.items[0]['items'][:3]" ] }, { "cell_type": "markdown", "id": "a13", "metadata": {}, "source": [ "## Radio Items\n", "\n", "Items with a `radio` key render as mutually exclusive radio options. All radio items at the same nesting level form a group. Set `_radio_selected: True` on the initially selected item:" ] }, { "cell_type": "code", "execution_count": null, "id": "a14", "metadata": {}, "outputs": [], "source": [ "pmui.MenuBar(items=[\n", " {'label': 'Theme', 'items': [\n", " {'label': 'Light', 'radio': 'light', '_radio_selected': True},\n", " {'label': 'Dark', 'radio': 'dark'},\n", " {'label': 'System', 'radio': 'system'},\n", " ]},\n", "], margin=(0, 0, 200, 0))" ] }, { "cell_type": "markdown", "id": "a15", "metadata": {}, "source": [ "## Groups\n", "\n", "Items with `group: True` render their sub-items as a labeled section (with a subheader), rather than as a nested submenu. This is useful for organizing related options visually:" ] }, { "cell_type": "code", "execution_count": null, "id": "a16", "metadata": {}, "outputs": [], "source": [ "pmui.MenuBar(items=[\n", " {'label': 'Format', 'items': [\n", " {'label': 'Text', 'group': True, 'icon': 'text_fields', 'items': [\n", " {'label': 'Bold', 'icon': 'format_bold', 'hint': 'Ctrl+B'},\n", " {'label': 'Italic', 'icon': 'format_italic', 'hint': 'Ctrl+I'},\n", " {'label': 'Underline', 'icon': 'format_underlined', 'hint': 'Ctrl+U'},\n", " ]},\n", " {'label': 'Paragraph', 'group': True, 'icon': 'format_align_left', 'items': [\n", " {'label': 'Align Left', 'icon': 'format_align_left'},\n", " {'label': 'Align Center', 'icon': 'format_align_center'},\n", " {'label': 'Align Right', 'icon': 'format_align_right'},\n", " ]},\n", " ]},\n", "], margin=(0, 0, 200, 0))" ] }, { "cell_type": "markdown", "id": "a17", "metadata": {}, "source": [ "## Callbacks\n", "\n", "Use `on_click` to register a callback that fires whenever a menu item is clicked:" ] }, { "cell_type": "code", "execution_count": null, "id": "a18", "metadata": {}, "outputs": [], "source": [ "callback_bar = pmui.MenuBar(items=[\n", " {'label': 'Actions', 'items': [\n", " {'label': 'Run', 'icon': 'play_arrow', 'hint': 'F5'},\n", " {'label': 'Debug', 'icon': 'bug_report', 'hint': 'F9'},\n", " {'label': 'Stop', 'icon': 'stop', 'hint': 'Shift+F5'},\n", " ]},\n", "], margin=(0, 0, 200, 0))\n", "\n", "log = pn.Column()\n", "\n", "callback_bar.on_click(lambda item: log.append(f\"Clicked: {item['label']}\"))\n", "\n", "pmui.Row(callback_bar, log)" ] }, { "cell_type": "markdown", "id": "a19", "metadata": {}, "source": [ "## Icons on Top-Level Menus\n", "\n", "Top-level menu triggers can also display icons:" ] }, { "cell_type": "code", "execution_count": null, "id": "a20", "metadata": {}, "outputs": [], "source": [ "pmui.MenuBar(items=[\n", " {'label': 'File', 'icon': 'description', 'items': [\n", " {'label': 'New', 'icon': 'note_add'},\n", " {'label': 'Open', 'icon': 'folder_open'},\n", " ]},\n", " {'label': 'Edit', 'icon': 'edit', 'items': [\n", " {'label': 'Undo', 'icon': 'undo'},\n", " {'label': 'Redo', 'icon': 'redo'},\n", " ]},\n", " {'label': 'View', 'icon': 'visibility', 'items': [\n", " {'label': 'Zoom In', 'icon': 'zoom_in'},\n", " {'label': 'Zoom Out', 'icon': 'zoom_out'},\n", " ]},\n", "], margin=(0, 0, 200, 0))" ] }, { "cell_type": "markdown", "id": "a21", "metadata": {}, "source": [ "## Disabled Menus\n", "\n", "Individual top-level menus or specific items can be disabled:" ] }, { "cell_type": "code", "execution_count": null, "id": "a22", "metadata": {}, "outputs": [], "source": [ "pmui.MenuBar(items=[\n", " {'label': 'File', 'items': [\n", " {'label': 'New', 'icon': 'note_add'},\n", " {'label': 'Save', 'icon': 'save', 'disabled': True},\n", " ]},\n", " {'label': 'Edit', 'disabled': True, 'items': [\n", " {'label': 'Undo'},\n", " ]},\n", " {'label': 'Help', 'items': [\n", " {'label': 'About', 'icon': 'info'},\n", " ]},\n", "], margin=(0, 0, 200, 0))" ] }, { "cell_type": "markdown", "id": "a23", "metadata": {}, "source": [ "## Color and Size\n", "\n", "The `color` parameter controls the button color, and `size` adjusts the button size:" ] }, { "cell_type": "code", "execution_count": null, "id": "a24", "metadata": {}, "outputs": [], "source": [ "sample_items = [\n", " {'label': 'File', 'items': [{'label': 'New'}, {'label': 'Open'}]},\n", " {'label': 'Edit', 'items': [{'label': 'Undo'}, {'label': 'Redo'}]},\n", "]\n", "\n", "pmui.Row(\n", " pmui.MenuBar(items=sample_items, color='primary'),\n", " pmui.MenuBar(items=sample_items, color='secondary'),\n", " pmui.MenuBar(items=sample_items, color='success'),\n", " margin=(0, 0, 200, 0)\n", ")" ] }, { "cell_type": "markdown", "id": "a25", "metadata": {}, "source": [ "## Variant\n", "\n", "The `variant` parameter controls the container style, either `'elevation'` (with a shadow) or `'outlined'` (with a border):" ] }, { "cell_type": "code", "execution_count": null, "id": "a26", "metadata": {}, "outputs": [], "source": [ "pn.Row(\n", " pmui.MenuBar(items=sample_items, variant='elevation'),\n", " pmui.MenuBar(items=sample_items, variant='outlined'),\n", ")" ] }, { "cell_type": "markdown", "id": "a27", "metadata": {}, "source": [ "## Complete Example\n", "\n", "A comprehensive menu bar combining multiple features:" ] }, { "cell_type": "code", "execution_count": null, "id": "a28", "metadata": {}, "outputs": [], "source": [ "pmui.MenuBar(items=[\n", " {'label': 'File', 'items': [\n", " {'label': 'New', 'icon': 'note_add', 'hint': 'Ctrl+N'},\n", " {'label': 'Open', 'icon': 'folder_open', 'hint': 'Ctrl+O'},\n", " {'label': 'Open Recent', 'icon': 'history', 'items': [\n", " {'label': 'project.py'},\n", " {'label': 'analysis.ipynb'},\n", " {'label': 'dashboard.py'},\n", " ]},\n", " None,\n", " {'label': 'Save', 'icon': 'save', 'hint': 'Ctrl+S'},\n", " {'label': 'Save As...', 'icon': 'save_as'},\n", " None,\n", " {'label': 'Exit', 'icon': 'close'},\n", " ]},\n", " {'label': 'Edit', 'items': [\n", " {'label': 'Undo', 'icon': 'undo', 'hint': 'Ctrl+Z'},\n", " {'label': 'Redo', 'icon': 'redo', 'hint': 'Ctrl+Y'},\n", " None,\n", " {'label': 'Cut', 'icon': 'content_cut', 'hint': 'Ctrl+X'},\n", " {'label': 'Copy', 'icon': 'content_copy', 'hint': 'Ctrl+C'},\n", " {'label': 'Paste', 'icon': 'content_paste', 'hint': 'Ctrl+V'},\n", " None,\n", " {'label': 'Find', 'icon': 'search', 'hint': 'Ctrl+F'},\n", " {'label': 'Replace', 'icon': 'find_replace', 'hint': 'Ctrl+H'},\n", " ]},\n", " {'label': 'View', 'items': [\n", " {'label': 'Show Toolbar', 'checkbox': True},\n", " {'label': 'Show Sidebar', 'checkbox': True},\n", " {'label': 'Show Minimap', 'checkbox': False},\n", " None,\n", " {'label': 'Theme', 'group': True, 'icon': 'palette', 'items': [\n", " {'label': 'Light', 'radio': 'light', '_radio_selected': True},\n", " {'label': 'Dark', 'radio': 'dark'},\n", " {'label': 'System', 'radio': 'system'},\n", " ]},\n", " {'label': 'Zoom In', 'icon': 'zoom_in', 'hint': 'Ctrl++'},\n", " {'label': 'Zoom Out', 'icon': 'zoom_out', 'hint': 'Ctrl+-'},\n", " ]},\n", " {'label': 'Help', 'items': [\n", " {'label': 'Documentation', 'icon': 'menu_book'},\n", " {'label': 'Release Notes', 'icon': 'new_releases'},\n", " None,\n", " {'label': 'Report Issue', 'icon': 'bug_report'},\n", " None,\n", " {'label': 'About', 'icon': 'info'},\n", " ]},\n", "], margin=(0, 0, 300, 0))" ] }, { "cell_type": "markdown", "id": "a29", "metadata": {}, "source": [ "### API Reference\n", "\n", "#### Parameters\n", "\n", "The `MenuBar` exposes a number of options which can be changed from both Python and Javascript. Try out the effect of these parameters interactively:" ] }, { "cell_type": "code", "execution_count": null, "id": "a30", "metadata": {}, "outputs": [], "source": [ "pmui.MenuBar(items=[\n", " {'label': 'File', 'items': [\n", " {'label': 'New', 'icon': 'note_add'},\n", " {'label': 'Open', 'icon': 'folder_open'},\n", " {'label': 'Save', 'icon': 'save'},\n", " ]},\n", " {'label': 'Edit', 'items': [\n", " {'label': 'Undo', 'icon': 'undo'},\n", " {'label': 'Redo', 'icon': 'redo'},\n", " ]},\n", "]).api(jslink=True)" ] }, { "cell_type": "markdown", "id": "a31", "metadata": {}, "source": [ "### References\n", "\n", "**Panel Documentation:**\n", "\n", "- [How-to guides on interactivity](https://panel.holoviz.org/how_to/interactivity/index.html) - Learn how to add interactivity to your applications using widgets\n", "- [Setting up callbacks and links](https://panel.holoviz.org/how_to/links/index.html) - Connect parameters between components and create reactive interfaces\n", "- [Declarative UIs with Param](https://panel.holoviz.org/how_to/param/index.html) - Build parameter-driven applications\n", "\n", "**Material UI:**\n", "\n", "- [Material UI MenuBar](https://mui.com/material-ui/react-menubar/) - Complete documentation for the underlying Material UI component\n", "- [Material UI Menu](https://mui.com/material-ui/react-menu/) - Menu component reference\n", "- [Material UI Menu API](https://mui.com/material-ui/api/menu/) - Detailed API reference" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.14.4" } }, "nbformat": 4, "nbformat_minor": 5 }