{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import panel as pn\n", "import panel_material_ui as pmui\n", "\n", "pn.extension()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `Details` component creates a collapsible container with three expansion states: collapsed, expanded (with scrollable area), and fully expanded. This makes it useful for providing a preview for longer outputs, while still providing an option to expand and view the full content if needed.\n", "\n", "## Parameters\n", "\n", "### Core\n", "\n", "* **`collapsed`** (`boolean`): Whether the details content is collapsed (default=True).\n", "* **`fully_expanded`** (`boolean`): Whether the details are fully expanded with no scrollable area (default=False). Only applies when collapsed is False.\n", "* **`header`** (`Panel component`): Custom component to display in the header bar.\n", "* **`hide_header`** (`boolean`): Whether to hide the header bar.\n", "* **`title`** (`str`): Text to display in the header (overridden by header if set).\n", "* **`scrollable_height`** (`str`): Maximum height of the scrollable area when expanded but not fully expanded (default=\"200px\").\n", "\n", "### Style\n", "\n", "* **`elevation`** (`int`): The elevation level of the details surface.\n", "* **`header_background`** (`str`): The background color of the header.\n", "* **`header_color`** (`str`): The color of the header text.\n", "* **`header_css_classes`** (`list`): List of CSS classes to apply to the header component.\n", "* **`outlined`** (`boolean`): Whether the details is outlined (default=True).\n", "* **`raised`** (`boolean`): Whether the details appears elevated above the background.\n", "* **`square`** (`boolean`): Whether to disable rounded corners.\n", "* **`title_css_classes`** (`list`): List of CSS classes to apply to the title component.\n", "* **`variant`** (`Literal[\"elevation\", \"outlined\"]`): Whether to show an outline instead of elevation.\n", "\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `Details` component accepts arbitrary Panel components like other layouts. It is `collapsed` by default:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "code = \"\"\"\n", "```python\n", "import panel as pn\n", "import panel_material_ui as pmui\n", "\n", "pn.extension()\n", "\n", "long_content = pn.Column(*[\n", " pn.pane.Str(f\"Item {i}\") for i in range(20)\n", "], margin=5)\n", "\n", "pmui.Details(\n", " long_content,\n", " title='Details'\n", ")\n", "```\n", "\"\"\"\n", "\n", "code = pn.pane.Markdown(code, margin=0, stylesheets=['.codehilite { margin: 0}'])\n", "\n", "details = pmui.Details(code, title='Details', margin=10, collapsed=False)\n", "details" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The contents of the `Details.objects` list should never be modified individually, because Panel cannot detect when items in that list have changed internally, and will thus fail to update any already-rendered views of those objects. Instead, use the provided methods for adding and removing items from the list. The only change that is safe to make directly to `Details.objects` is to replace the list of objects entirely. As a simple example of using the methods, we might add an additional widget to the details using the append method:\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "w3 = pmui.Select(options=['A', 'B', 'C'])\n", "details.append(w3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On a live server or in a notebook the details displayed after the previous code cell (above) will dynamically expand in size to accommodate all three widgets and the title. To see the effect in a statically rendered page, we will display the details a second time:\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "details" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Whether the Details is collapsed or not can be controlled from Python and Javascript:\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(details.collapsed)\n", "details.collapsed = False" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Three Expansion States\n", "\n", "The `Details` component has three distinct expansion states:\n", "\n", "1. **Collapsed**: Content is hidden (default state)\n", "2. **Expanded (scrollable)**: Content is visible with a scrollable area limited by `max_height`\n", "3. **Fully Expanded**: Content takes up all available space without scrolling\n", "\n", "When expanded but not fully expanded, a button appears at the bottom to toggle to fully expanded state:\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Create content that exceeds scrollable_height to demonstrate scrolling\n", "long_content = pmui.Column(*[pn.pane.Str(f\"Item {i}\") for i in range(20)], margin=5)\n", "\n", "details_states = pmui.Details(\n", " long_content,\n", " title='Expandable Details',\n", " collapsed=False,\n", " fully_expanded=False,\n", " scrollable_height=250,\n", " margin=10\n", ")\n", "details_states" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `fully_expanded` state can also be controlled programmatically:\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "details_states.fully_expanded = True" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Header\n", "\n", "Instead of using a title, a Details may also be given an explicit header that can contain any component, e.g. in this case the Panel logo:\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "logo = 'https://panel.holoviz.org/_static/logo_horizontal.png'\n", "\n", "red = pn.Spacer(styles=dict(background='red'), height=100, sizing_mode='stretch_width')\n", "green = pn.Spacer(styles=dict(background='green'), height=100, sizing_mode='stretch_width')\n", "blue = pn.Spacer(styles=dict(background='blue'), height=100, sizing_mode='stretch_width')\n", "\n", "pmui.Details(\n", " red, green, blue,\n", " header_background='#2f2f2f',\n", " header_color='white',\n", " header=pn.panel(logo, height=40),\n", " width=300,\n", " collapsed=False\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Style\n", "\n", "By default `Details` elements are `outlined`. The `scrollable_height` parameter controls the scrollable area height when expanded:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "content = pn.Column(*[pn.pane.Str(f\"Content item {i}\") for i in range(10)], margin=5)\n", "\n", "pmui.Row(*(\n", " pmui.Details(\n", " content,\n", " title=f'Max height={h}',\n", " scrollable_height=h,\n", " collapsed=False,\n", " margin=10\n", " )\n", " for h in range(100, 300, 50)\n", "))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Header styling can be customized with `header_background` and `header_color`:\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "w1 = pmui.TextInput(label='Text:')\n", "w2 = pmui.FloatSlider(label='Slider')\n", "\n", "pmui.Details(\n", " w1, w2,\n", " title='Styled Header',\n", " header_background='#1976d2',\n", " header_color='white',\n", " collapsed=False,\n", " margin=10\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Layout\n", "\n", "In general a `Details` does not have to be given an explicit `width`, `height`, or `sizing_mode`, allowing it to adapt to the size of its contents. However in certain cases it can be useful to declare a fixed-size layout, which its responsively sized contents will then fill, making it possible to achieve equal spacing between multiple objects:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "red = pn.Spacer(styles=dict(background='red'), sizing_mode='stretch_both')\n", "green = pn.Spacer(styles=dict(background='green'), sizing_mode='stretch_both')\n", "blue = pn.Spacer(styles=dict(background='blue'), sizing_mode='stretch_both')\n", "\n", "pmui.Details(red, green, blue, scrollable_height=100, height=300, width=200, title='Fixed size', margin=10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When no fixed size is specified the column will expand to accommodate the sizing behavior of its contents:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from bokeh.plotting import figure\n", "\n", "p1 = figure(height=250, sizing_mode='stretch_width', margin=5)\n", "p2 = figure(height=250, sizing_mode='stretch_width', margin=5)\n", "\n", "p1.line([1, 2, 3], [1, 2, 3])\n", "p2.scatter([1, 2, 3], [1, 2, 3])\n", "\n", "pmui.Details(p1, pn.layout.Divider(), p2, title=\"Responsive\", sizing_mode='stretch_width', margin=10)" ] } ], "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": 4 }