{ "cells": [ { "cell_type": "code", "execution_count": null, "id": "682c5dc6-553e-4e93-9617-b07419c6842c", "metadata": {}, "outputs": [], "source": [ "import math\n", "\n", "import panel as pn\n", "from panel_material_ui import (\n", " Column, Container, Drawer, Paper, ButtonIcon, ThemeToggle, Typography, ToggleIcon, Row, Pagination, Grid\n", ")\n", "\n", "pn.extension()" ] }, { "cell_type": "markdown", "id": "99429527-f8ca-4ca5-977f-db3487064ed3", "metadata": {}, "source": [ "In addition to the `Page` component, Material components like `Container`, `Paper`, and others can be combined to manually define the layout of an application.\n", "These building blocks provide more granular control over structure, spacing, and visual hierarchy when you need a fully custom page design.\n", "\n", "In this reference guide we will discover a few ways we can use these components to generate a page-like layout." ] }, { "cell_type": "code", "execution_count": null, "id": "5adcc651-e51b-462c-859f-2638d05e5677", "metadata": {}, "outputs": [], "source": [ "LOREM_IPSUM = \"\"\"\n", "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do\n", "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad\n", "minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n", "aliquip ex ea commodo consequat. Duis aute irure dolor in\n", "reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla\n", "pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n", "culpa qui officia deserunt mollit anim id est laborum.\n", "\"\"\"\n", "\n", "def generate_pages(text: str, chars_per_page: int, num_pages: int) -> list[str]:\n", " total_chars_needed = chars_per_page * num_pages\n", " repeats = math.ceil(total_chars_needed / len(text))\n", " full_text = text * repeats\n", " return [\n", " full_text[i*chars_per_page : (i+1)*chars_per_page]\n", " for i in range(num_pages)\n", " ]" ] }, { "cell_type": "markdown", "id": "288403a2-fb36-4d70-9166-29332e79a382", "metadata": {}, "source": [ "### Building a Custom Layout with `Container` and `Paper`\n", "\n", "When manually designing a page, two key Material components often form the foundation: `Container` and `Paper`. The `Container` sets the overall width, margins, and centering for your content, while the `Paper` provides a surface with padding, elevation, and layout flexibility inside the container.\n", "\n", "In this example, we start by wrapping the entire layout inside a `Container`, which centers the content and constrains its width with `width_option='sm'`.\n", "Inside the container, a `Paper` component acts as the main surface of the application — giving the content a card-like feel, adding padding (`sx={\"p\": \"1rem\"}`), and stretching to fill the available height and width." ] }, { "cell_type": "code", "execution_count": null, "id": "2ca3a86a-6a3e-4fd1-b713-019118dc26e5", "metadata": {}, "outputs": [], "source": [ "title = Typography('Lorem Ipsum', variant='h3', margin=(20, 30))\n", "sidebar = Drawer('# Drawer', anchor='right', variant='temporary', size=300)\n", "toggles = Row(\n", " ThemeToggle(),\n", " sidebar.create_toggle(),\n", " styles={'position': 'absolute', 'top': \"0\", 'right': \"0\"}\n", ")\n", "pages = generate_pages(LOREM_IPSUM, 1000, 99)\n", "pagination = Pagination(count=99, align=('center', 'end'), styles={'marginTop': \"auto\"})\n", "\n", "Container(\n", " Paper(\n", " title,\n", " toggles,\n", " sidebar,\n", " pn.rx(pages)[pagination],\n", " pagination,\n", " elevation=3,\n", " sizing_mode='stretch_both',\n", " sx={\"p\": \"1rem\"}\n", " ),\n", " margin=(10, 0),\n", " height=580,\n", " width_option='sm'\n", ").preview(sizing_mode='stretch_width', height=600)" ] }, { "cell_type": "markdown", "id": "567ba69f-ae8b-4f5e-9055-fc3fd3fa2448", "metadata": {}, "source": [ "Within the `Paper`, we arrange the individual UI elements:\n", "\n", "- A `Typography` component displays the title, styled with custom margins.\n", "- A `Row` positions the theme toggle and sidebar toggle buttons absolutely in the top-right corner.\n", "- A `Drawer` provides a collapsible sidebar anchored to the right side.\n", "- The main content is a set of paginated pages, dynamically generated and linked to a `Pagination` control at the bottom.\n", "\n", "By combining `Container` and `Paper`, you can quickly establish a clean, responsive base for your application — layering in more interactive components as needed while maintaining full control over layout and styling." ] }, { "cell_type": "markdown", "id": "3b16e640-b9ef-45ab-92b3-a92dd9c9a698", "metadata": {}, "source": [ "## Building a Dashboard layout with `Grid` and `Drawer`\n", "\n", "This example builds a simple dashboard layout by combining a persistent `Drawer`, a title, a `Grid` for the main content, and floating toggle controls.\n", "\n", "- A `Drawer` is anchored to the left side of the page, using `variant='persistent'` so it pushes the content when open instead of overlaying it. It is styled with padding to align its content below the fixed title.\n", "- A `Typography` component displays the dashboard title, positioned with a left margin to avoid overlap with the drawer.\n", "- The main content is arranged in a `Grid`, with two charts placed side-by-side on medium and larger screens (`md=6` each) and stacked on smaller screens (`xs=12`), followed by a full-width chart.\n", "- Each chart is wrapped in a `Paper` component to provide padding, elevation, and a consistent card-like appearance.\n", "- A `ThemeToggle` and a drawer toggle button are positioned absolutely in the top-right corner for easy access, without affecting the flow of the main layout.\n", "- The overall layout is built with a `Row`, placing the `Drawer` beside the main content and the floating controls.\n", "\n", "This structure keeps the layout responsive, clean, and modular, while giving the user control over both theme and sidebar visibility." ] }, { "cell_type": "code", "execution_count": null, "id": "4a0cadd2-610d-459e-bd63-7b73cbd1feb5", "metadata": {}, "outputs": [], "source": [ "title = Typography(\"My Dashboard\", variant=\"h4\", margin=(0, 0, 0, 50))\n", "\n", "drawer = Drawer(\n", " Typography(\"I'm in a Drawer!\", variant=\"h6\"),\n", " variant=\"persistent\",\n", " anchor=\"left\",\n", " styles={\"height\": \"100%\"},\n", " sx={\"paddingTop\": \"50px\"}\n", ")\n", "\n", "theme_toggle = ThemeToggle(styles={\"position\": \"fixed\", \"right\": \"0\", \"zIndex\": \"10001\"})\n", "\n", "render_content = lambda text: Paper(Typography(text, variant='h6'), elevation=2, sx={\"p\": \"1rem\"}, sizing_mode=\"stretch_both\")\n", "\n", "grid = Grid(\n", " Grid(\n", " render_content(\"Chart 1\"),\n", " size={\"md\": 6, \"xs\": 12}\n", " ),\n", " Grid(\n", " render_content(\"Chart 2\"),\n", " size={\"md\": 6, \"xs\": 12}\n", " ),\n", " Grid(\n", " render_content(\"Chart 3\"),\n", " size={\"md\": 12, \"xs\": 12}\n", " ),\n", " container=True,\n", " column_spacing=2,\n", " row_spacing=2,\n", " sizing_mode='stretch_both',\n", " margin=(0, 20, 20, 20)\n", ")\n", "\n", "main = Column(title, grid)\n", "\n", "toggle = drawer.create_toggle(styles={\"position\": \"fixed\", \"zIndex\": \"10001\"})\n", "\n", "Row(\n", " drawer,\n", " main,\n", " theme_toggle,\n", " toggle,\n", " sizing_mode=\"stretch_width\"\n", ").preview(sizing_mode='stretch_width')" ] }, { "cell_type": "markdown", "id": "9f7ca891-19b0-42e9-8062-032530085adc", "metadata": {}, "source": [ "These are just two ways in which components can be combined to create a custom application layout." ] } ], "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.12.2" } }, "nbformat": 4, "nbformat_minor": 5 }