Skip to content

Commit 9690c96

Browse files
authored
Implement AppBar component (#680)
* Implement AppBar component * Add tests
1 parent 7788f7e commit 9690c96

6 files changed

Lines changed: 592 additions & 32 deletions

File tree

Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": null,
6+
"id": "a1",
7+
"metadata": {},
8+
"outputs": [],
9+
"source": [
10+
"import panel as pn\n",
11+
"import panel_material_ui as pmui\n",
12+
"\n",
13+
"pn.extension()"
14+
]
15+
},
16+
{
17+
"cell_type": "markdown",
18+
"id": "a2",
19+
"metadata": {},
20+
"source": [
21+
"The `AppBar` component renders a Material UI App Bar (top navigation bar). It supports a title, icon, color theming, and can contain arbitrary child components (buttons, menus, search fields, etc.) via the `objects` parameter.\n",
22+
"\n",
23+
"The AppBar is commonly used as a top-level navigation header, either standalone or inside a `Page` component's `header` slot.\n",
24+
"\n",
25+
"## Parameters\n",
26+
"\n",
27+
"### Core\n",
28+
"\n",
29+
"- **`objects`** (`list`): Components rendered inside the app bar toolbar (buttons, menus, etc.).\n",
30+
"- **`title`** (`str`): Title text displayed in the app bar.\n",
31+
"- **`icon`** (`str`): Icon displayed at the start of the app bar (e.g. a menu or brand icon).\n",
32+
"\n",
33+
"### Display\n",
34+
"\n",
35+
"- **`color`** (`str`): The color theme. One of `'default'`, `'inherit'`, `'primary'`, `'secondary'`, `'transparent'`.\n",
36+
"- **`enable_color_on_dark`** (`bool`): If True, the `color` prop applies in dark mode too.\n",
37+
"- **`position`** (`str`): CSS position. One of `'fixed'`, `'absolute'`, `'sticky'`, `'static'`, `'relative'`.\n",
38+
"- **`variant`** (`str`): Toolbar density. `'dense'` for compact, `'regular'` for standard height.\n",
39+
"\n",
40+
"### Styling\n",
41+
"\n",
42+
"- **`sx`** (`dict`): Component-level styling API.\n",
43+
"- **`theme_config`** (`dict`): Theming API.\n",
44+
"\n",
45+
"---"
46+
]
47+
},
48+
{
49+
"cell_type": "markdown",
50+
"id": "a3",
51+
"metadata": {},
52+
"source": [
53+
"## Basic Usage\n",
54+
"\n",
55+
"A simple app bar with a title and icon:"
56+
]
57+
},
58+
{
59+
"cell_type": "code",
60+
"execution_count": null,
61+
"id": "a4",
62+
"metadata": {},
63+
"outputs": [],
64+
"source": [
65+
"pmui.AppBar(title='My Application', icon='menu')"
66+
]
67+
},
68+
{
69+
"cell_type": "markdown",
70+
"id": "a5",
71+
"metadata": {},
72+
"source": [
73+
"## With Buttons\n",
74+
"\n",
75+
"Add action buttons to the app bar by passing them as positional arguments or via `objects`:"
76+
]
77+
},
78+
{
79+
"cell_type": "code",
80+
"execution_count": null,
81+
"id": "a6",
82+
"metadata": {},
83+
"outputs": [],
84+
"source": [
85+
"pmui.AppBar(\n",
86+
" pmui.Button(label='Login', variant='outlined', color='default'),\n",
87+
" title='Dashboard',\n",
88+
" icon='dashboard',\n",
89+
")"
90+
]
91+
},
92+
{
93+
"cell_type": "markdown",
94+
"id": "a7",
95+
"metadata": {},
96+
"source": [
97+
"## With MenuBar\n",
98+
"\n",
99+
"The `AppBar` pairs naturally with `MenuBar` to create a desktop-style application header:"
100+
]
101+
},
102+
{
103+
"cell_type": "code",
104+
"execution_count": null,
105+
"id": "a8",
106+
"metadata": {},
107+
"outputs": [],
108+
"source": [
109+
"menu = pmui.MenuBar(\n",
110+
" items=[\n",
111+
" {'label': 'File', 'items': [\n",
112+
" {'label': 'New', 'icon': 'note_add', 'hint': 'Ctrl+N'},\n",
113+
" {'label': 'Open', 'icon': 'folder_open', 'hint': 'Ctrl+O'},\n",
114+
" None,\n",
115+
" {'label': 'Save', 'icon': 'save', 'hint': 'Ctrl+S'},\n",
116+
" {'label': 'Exit', 'icon': 'close'},\n",
117+
" ]},\n",
118+
" {'label': 'Edit', 'items': [\n",
119+
" {'label': 'Undo', 'icon': 'undo', 'hint': 'Ctrl+Z'},\n",
120+
" {'label': 'Redo', 'icon': 'redo', 'hint': 'Ctrl+Y'},\n",
121+
" None,\n",
122+
" {'label': 'Cut', 'icon': 'content_cut'},\n",
123+
" {'label': 'Copy', 'icon': 'content_copy'},\n",
124+
" {'label': 'Paste', 'icon': 'content_paste'},\n",
125+
" ]},\n",
126+
" {'label': 'Help', 'items': [\n",
127+
" {'label': 'Documentation', 'icon': 'menu_book'},\n",
128+
" {'label': 'About', 'icon': 'info'},\n",
129+
" ]},\n",
130+
" ],\n",
131+
" variant='outlined',\n",
132+
" sx={'border': 'none', 'boxShadow': 'none', 'background': 'transparent'},\n",
133+
")\n",
134+
"\n",
135+
"pmui.AppBar(menu, title='Code Editor', icon='code')"
136+
]
137+
},
138+
{
139+
"cell_type": "markdown",
140+
"id": "a9",
141+
"metadata": {},
142+
"source": [
143+
"## Color Variants\n",
144+
"\n",
145+
"The `color` parameter controls the app bar's background color:"
146+
]
147+
},
148+
{
149+
"cell_type": "code",
150+
"execution_count": null,
151+
"id": "a10",
152+
"metadata": {},
153+
"outputs": [],
154+
"source": [
155+
"pn.Column(\n",
156+
" pmui.AppBar(title='Primary', color='primary'),\n",
157+
" pmui.AppBar(title='Secondary', color='secondary'),\n",
158+
" pmui.AppBar(title='Default', color='default'),\n",
159+
" pmui.AppBar(title='Transparent', color='transparent'),\n",
160+
")"
161+
]
162+
},
163+
{
164+
"cell_type": "markdown",
165+
"id": "a11",
166+
"metadata": {},
167+
"source": [
168+
"## Dense vs Regular\n",
169+
"\n",
170+
"The `variant` parameter controls the toolbar height:"
171+
]
172+
},
173+
{
174+
"cell_type": "code",
175+
"execution_count": null,
176+
"id": "a12",
177+
"metadata": {},
178+
"outputs": [],
179+
"source": [
180+
"pn.Column(\n",
181+
" pmui.AppBar(title='Dense (compact)', variant='dense', icon='menu'),\n",
182+
" pmui.AppBar(title='Regular', variant='regular', icon='menu'),\n",
183+
")"
184+
]
185+
},
186+
{
187+
"cell_type": "markdown",
188+
"id": "a13",
189+
"metadata": {},
190+
"source": [
191+
"## Multiple Components\n",
192+
"\n",
193+
"You can place multiple components in the app bar. They are laid out horizontally with flex:"
194+
]
195+
},
196+
{
197+
"cell_type": "code",
198+
"execution_count": null,
199+
"id": "a14",
200+
"metadata": {},
201+
"outputs": [],
202+
"source": [
203+
"pmui.AppBar(\n",
204+
" pmui.MenuBar(\n",
205+
" items=[\n",
206+
" {'label': 'File', 'items': [{'label': 'New'}, {'label': 'Open'}]},\n",
207+
" {'label': 'Edit', 'items': [{'label': 'Undo'}, {'label': 'Redo'}]},\n",
208+
" ],\n",
209+
" sx={'border': 'none', 'boxShadow': 'none', 'background': 'transparent'},\n",
210+
" ),\n",
211+
" pmui.Button(label='Sign In', variant='outlined', color='default'),\n",
212+
" title='My App',\n",
213+
" icon='apps',\n",
214+
")"
215+
]
216+
},
217+
{
218+
"cell_type": "markdown",
219+
"id": "a15",
220+
"metadata": {},
221+
"source": [
222+
"## Custom Styling\n",
223+
"\n",
224+
"Use the `sx` parameter for custom styling, or `theme_config` for full theming:"
225+
]
226+
},
227+
{
228+
"cell_type": "code",
229+
"execution_count": null,
230+
"id": "a16",
231+
"metadata": {},
232+
"outputs": [],
233+
"source": [
234+
"pmui.AppBar(\n",
235+
" title='Custom Styled',\n",
236+
" icon='rocket',\n",
237+
" color='transparent',\n",
238+
" sx={\n",
239+
" 'background': 'linear-gradient(45deg, #2196F3 30%, #21CBF3 90%)',\n",
240+
" 'color': 'white',\n",
241+
" },\n",
242+
")"
243+
]
244+
},
245+
{
246+
"cell_type": "markdown",
247+
"id": "a18",
248+
"metadata": {},
249+
"source": [
250+
"### References\n",
251+
"\n",
252+
"**Panel Documentation:**\n",
253+
"\n",
254+
"- [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",
255+
"- [Templates](https://panel.holoviz.org/how_to/templates/index.html) - Build full application layouts\n",
256+
"\n",
257+
"**Material UI:**\n",
258+
"\n",
259+
"- [Material UI App Bar](https://mui.com/material-ui/react-app-bar/) - Complete documentation for the underlying Material UI component\n",
260+
"- [Material UI AppBar API](https://mui.com/material-ui/api/app-bar/) - Detailed API reference"
261+
]
262+
}
263+
],
264+
"metadata": {
265+
"kernelspec": {
266+
"display_name": "Python 3 (ipykernel)",
267+
"language": "python",
268+
"name": "python3"
269+
},
270+
"language_info": {
271+
"codemirror_mode": {
272+
"name": "ipython",
273+
"version": 3
274+
},
275+
"file_extension": ".py",
276+
"mimetype": "text/x-python",
277+
"name": "python",
278+
"nbconvert_exporter": "python",
279+
"pygments_lexer": "ipython3",
280+
"version": "3.14.4"
281+
}
282+
},
283+
"nbformat": 4,
284+
"nbformat_minor": 5
285+
}

examples/reference/page/Manual.ipynb

Lines changed: 88 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
"\n",
1212
"import panel as pn\n",
1313
"from panel_material_ui import (\n",
14-
" Column, Container, Drawer, Paper, ButtonIcon, ThemeToggle, Typography, ToggleIcon, Row, Pagination, Grid\n",
14+
" Column, Container, Drawer, Paper, ButtonIcon, ThemeToggle,\n",
15+
" Typography, ToggleIcon, Row, Pagination, Grid\n",
1516
")\n",
1617
"\n",
1718
"pn.extension()"
@@ -195,7 +196,91 @@
195196
"id": "9f7ca891-19b0-42e9-8062-032530085adc",
196197
"metadata": {},
197198
"source": [
198-
"These are just two ways in which components can be combined to create a custom application layout."
199+
"## Building an App Layout with `AppBar`\n",
200+
"\n",
201+
"The `AppBar` component provides a ready-made top navigation bar that can contain a title, icon, and arbitrary child components like buttons and menus. Combined with other layout components it serves as the header of a full application.\n",
202+
"\n",
203+
"In this example we combine an `AppBar` with a `MenuBar` for navigation, a `Drawer` for a sidebar, and paginated content in the main area."
204+
]
205+
},
206+
{
207+
"cell_type": "code",
208+
"execution_count": null,
209+
"id": "ee6c997d",
210+
"metadata": {},
211+
"outputs": [],
212+
"source": [
213+
"from panel_material_ui import AppBar, MenuBar, Button\n",
214+
"\n",
215+
"menu = MenuBar(\n",
216+
" items=[\n",
217+
" {'label': 'File', 'items': [\n",
218+
" {'label': 'New', 'icon': 'note_add', 'hint': 'Ctrl+N'},\n",
219+
" {'label': 'Open', 'icon': 'folder_open', 'hint': 'Ctrl+O'},\n",
220+
" None,\n",
221+
" {'label': 'Save', 'icon': 'save', 'hint': 'Ctrl+S'},\n",
222+
" ]},\n",
223+
" {'label': 'Edit', 'items': [\n",
224+
" {'label': 'Undo', 'icon': 'undo'},\n",
225+
" {'label': 'Redo', 'icon': 'redo'},\n",
226+
" ]},\n",
227+
" {'label': 'View', 'items': [\n",
228+
" {'label': 'Zoom In', 'icon': 'zoom_in'},\n",
229+
" {'label': 'Zoom Out', 'icon': 'zoom_out'},\n",
230+
" ]},\n",
231+
" ],\n",
232+
" sx={'border': 'none', 'boxShadow': 'none', 'background': 'transparent', 'color': 'white'},\n",
233+
" margin=(15, 0, 0, 0)\n",
234+
")\n",
235+
"\n",
236+
"drawer = Drawer(\n",
237+
" Typography(\"Sidebar\", variant=\"h6\"),\n",
238+
" Typography(\"Navigation and tools go here.\"),\n",
239+
" variant=\"persistent\",\n",
240+
" anchor=\"left\",\n",
241+
" size=250,\n",
242+
" sx={\"paddingTop\": \"60px\", \"zIndex\": 1}\n",
243+
")\n",
244+
"\n",
245+
"appbar = AppBar(\n",
246+
" menu,\n",
247+
" ThemeToggle(styles={\"margin-left\": \"auto\"}),\n",
248+
" drawer_toggle=drawer.create_toggle(sx={\".MuiIcon-root\": {\"color\": \"white\"}}),\n",
249+
" title='My Application',\n",
250+
" icon='nature',\n",
251+
" sizing_mode=\"stretch_width\",\n",
252+
" styles={\"z-index\": \"999\"}\n",
253+
")\n",
254+
"\n",
255+
"pages = generate_pages(LOREM_IPSUM, 800, 10)\n",
256+
"pagination = Pagination(count=10, align=('center', 'end'), styles={'marginTop': 'auto'})\n",
257+
"\n",
258+
"main = Container(\n",
259+
" Paper(\n",
260+
" pn.rx(pages)[pagination],\n",
261+
" pagination,\n",
262+
" elevation=1,\n",
263+
" sx={\"p\": \"1.5rem\", \"m\": \"1em 0\"},\n",
264+
" sizing_mode='stretch_both',\n",
265+
" )\n",
266+
")\n",
267+
"\n",
268+
"Column(\n",
269+
" appbar,\n",
270+
" Row(drawer, main, sizing_mode='stretch_both'),\n",
271+
" sizing_mode='stretch_width',\n",
272+
" height=500,\n",
273+
").preview(sizing_mode='stretch_width', height=520)"
274+
]
275+
},
276+
{
277+
"cell_type": "markdown",
278+
"id": "c3e782b2",
279+
"metadata": {},
280+
"source": [
281+
"The `AppBar` handles the top-level header concerns (title, icon, color theming) while the child components inside it provide the interactive elements. This pattern scales well: you can add search fields, avatar menus, notification badges, or any other widget as children of the AppBar.\n",
282+
"\n",
283+
"These are just a few ways in which components can be combined to create a custom application layout."
199284
]
200285
}
201286
],
@@ -215,7 +300,7 @@
215300
"name": "python",
216301
"nbconvert_exporter": "python",
217302
"pygments_lexer": "ipython3",
218-
"version": "3.12.2"
303+
"version": "3.14.4"
219304
}
220305
},
221306
"nbformat": 4,

0 commit comments

Comments
 (0)