{ "cells": [ { "cell_type": "code", "metadata": {}, "source": [ "import panel as pn\n", "pn.extension()" ], "outputs": [], "execution_count": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "``Tabs`` allow switching between multiple objects by clicking on the corresponding tab header. Tab labels may be defined explicitly as part of a tuple or will be inferred from the ``name`` parameter of the tab's contents. Like ``Column`` and ``Row``, ``Tabs`` has a list-like API with methods to ``append``, ``extend``, ``clear``, ``insert``, ``pop``, ``remove`` and ``__setitem__``, which make it possible to interactively update and modify the tabs.\n", "\n", "#### Parameters:\n", "\n", "For details on other options for customizing the component see the [layout](../../how_to/layout/index.md) and [styling](../../how_to/styling/index.md) how-to guides.\n", "\n", "* **``active``** (int, default=0): The index of the currently selected tab. Updates when a tab is selected and may also be set programmatically to flip between tabs.\n", "* **``dynamic``** (boolean, default=False): Dynamically populate only the active Tab.\n", "* **``closable``** (boolean, default=False): Whether it should be allowed to close tabs using the GUI, which deletes them from the list of objects.\n", "* **``objects``** (list): The list of objects to display in the Column. Should not generally be modified directly except when replaced in its entirety.\n", "* **``tabs_location``** (str, default='above'): The location of the tabs relative to the content. Must be one of 'left', 'right', 'below' or 'above'.\n", "\n", "___" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Tabs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A ``Tabs`` layout can either be instantiated as empty and be populated after the fact, or using a list of objects provided as positional arguments. If the objects are not already Panel components they will each be converted to one using the ``pn.panel`` conversion method. Unlike other panel ``Tabs`` also accepts tuples to specify the title of each tab, if no name is supplied explicitly the name of the underlying object will be used." ] }, { "cell_type": "code", "metadata": {}, "source": [ "from bokeh.plotting import figure\n", "\n", "p1 = figure(width=300, height=300, name='Scatter')\n", "p1.scatter([0, 1, 2, 3, 4, 5, 6], [0, 1, 2, 3, 2, 1, 0])\n", "\n", "p2 = figure(width=300, height=300, name='Line')\n", "p2.line([0, 1, 2, 3, 4, 5, 6], [0, 1, 2, 3, 2, 1, 0])\n", "\n", "tabs = pn.Tabs(('Scatter', p1), p2)\n", "tabs" ], "outputs": [], "execution_count": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "The ``Tabs`` objects should never be modified directly. Instead, it is recommended to modify tabs using the provided methods, except when replacing the list of ``objects`` entirely. Using the methods ensures that the rendered views of the ``Tabs`` are rerendered in response to the change, but even more importantly it ensures the tab titles are kept in sync with the objects. As a simple example we might add an additional widget to the ``tabs`` using the append method:" ] }, { "cell_type": "code", "metadata": {}, "source": [ "p3 = figure(width=300, height=300, name='Square')\n", "p3.scatter([0, 1, 2, 3, 4, 5, 6], [0, 1, 2, 3, 2, 1, 0], marker='square', size=10)\n", "\n", "tabs.append(p3)" ], "outputs": [], "execution_count": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "On a live server or in a notebook the `tabs` displayed above will dynamically expand to include the new tab. To see the effect in a statically rendered page, we will display the tabs a second time:" ] }, { "cell_type": "code", "metadata": {}, "source": [ "tabs" ], "outputs": [], "execution_count": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### ``active``" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In addition to being able to modify the ``objects`` using methods we can also get and set the currently ``active`` tab as an integer, which will update any rendered views of the object:" ] }, { "cell_type": "code", "metadata": {}, "source": [ "print(tabs.active)\n", "tabs.active = 0" ], "outputs": [], "execution_count": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### ``dynamic``\n", "\n", "When enabled the dynamic option ensures that only the active tab is actually rendered, only when switching to a new Tab are the contents loaded. This can be very helpful in a server context or notebook context when displaying a lot of tabs or when rendering the individual objects are very large or expensive to render. Note however that without a live server the contents of the non-active tab will never load:" ] }, { "cell_type": "code", "metadata": {}, "source": [ "tabs = pn.Tabs(p1, p2, p3, dynamic=True)\n", "\n", "tabs" ], "outputs": [], "execution_count": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you want the `Tabs` to be completely lazy when rendering some output you can leverage a [ParamFunction or ParamMethod](../../user_guide/Param.ipynb) to ensure that the output is not computed until you navigate to the tab:" ] }, { "cell_type": "code", "metadata": {}, "source": [ "import time\n", "import numpy as np\n", "\n", "def plot():\n", " time.sleep(1) # some long running calculation\n", " np.random.seed(tabs.active)\n", " xs, ys = np.random.randn(2, 100)\n", " p = figure(width=300, height=300, name=f'Scatter Seed {tabs.active}')\n", " p.scatter(xs, ys)\n", " return p\n", "\n", "p1 = pn.param.ParamFunction(plot, lazy=True, name='Seed 0')\n", "p2 = pn.param.ParamFunction(plot, lazy=True, name='Seed 1')\n", "p3 = pn.param.ParamFunction(plot, lazy=True, name='Seed 2')\n", "\n", "tabs = pn.Tabs(p1, p2, p3, dynamic=True)\n", "\n", "tabs" ], "outputs": [], "execution_count": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### ``closable``\n", "\n", "``Tabs`` may also be initialized as ``closable``, which provides an `x` widget in the GUI that makes it possible to remove tabs and therefore remove them from the list of ``objects``:" ] }, { "cell_type": "code", "metadata": {}, "source": [ "tabs = pn.Tabs(\n", " ('red', pn.Spacer(styles=dict(background='red'), width=100, height=100)),\n", " ('blue', pn.Spacer(styles=dict(background='blue'), width=100, height=100)),\n", " ('green', pn.Spacer(styles=dict(background='green'), width=100, height=100)),\n", " closable=True\n", ")\n", "\n", "tabs" ], "outputs": [], "execution_count": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### ``tabs_location``\n", "\n", "Lastly, it is possible to modify the location of the tabs header relative to the content using the ``tabs_location`` parameter:" ] }, { "cell_type": "code", "metadata": {}, "source": [ "pn.Row(tabs, tabs.clone(active=1, tabs_location='right'), tabs.clone(active=2, tabs_location='below'), tabs.clone(tabs_location='left'))" ], "outputs": [], "execution_count": null } ], "metadata": { "language_info": { "name": "python", "pygments_lexer": "ipython3" } }, "nbformat": 4, "nbformat_minor": 4 }