Can i use/create a modal/dialog in Panel?

I need to use a modal in my app.
Is there any existing solution?
if not, can you guide me on using HTML pane to do it?

Hi @ItamarShDev

How to solve this depends on what you want to do with the model.

Should it contain

  • Text
  • Markdown
  • Html
  • Panel Buttons
  • Panel layouts, panes or widgets?

I believe you would have to do one of the following.

I would try the first or second option depending on your use case.

And please add a Feature Request to Panel on Github describing your use case. That will help.

Hi @ItamarShDev

Did you find a solution? And which?

I think I will be experimenting a bit with this today as I need to learn about it too.

Regarding whether it’s in Panel 0.10 I’m not sure. I can see that there is a statement in that direction though.

Hi @ItamarShDev.

I’ve created an example based on a custom Panel Template.

Check it out live at

You can find the most recent code here

I include the current code below for completeness


{% extends base %}

{% block postamble %}
<!-- -->
<link rel="stylesheet" href="">
<script type="module" src=""></script>
    body, .bk-root .bk, .bk-root .bk:before, .bk-root .bk:after {
        font-family: var(--sl-input-font-family);
{% endblock %}

<!-- goes in body -->
{% block contents %}
{{ embed(roots.header) }}
<div id="main" style="margin: 25px">
    {{ embed(roots.main) }}
    <!-- -->
    <sl-dialog label="{{ dialog_label }}" class="dialog-overview" style="--width: 550px;--height: 500px;">
        {{ embed(roots.dialog) }}
    <sl-button slot="footer" type="primary">Close</sl-button>

    <sl-button>Open Dialog</sl-button>

(() => {
    const dialog = document.querySelector('.dialog-overview');
    const openButton = dialog.nextElementSibling;
    const closeButton = dialog.querySelector('sl-button[slot="footer"]');

    openButton.addEventListener('click', () =>;
    closeButton.addEventListener('click', () => dialog.hide());

{% endblock %}

"""Custom Panel Template With a Dialog"""
import pathlib

import panel as pn
import param

TEMPLATE = (pathlib.Path(__file__).parent / "template.html").read_text()

class TemplateWithDialog(pn.template.Template):
    """Custom Panel Template With a Dialog"""

    dialog_open = param.Action()
    dialog_close = param.Action()

    TEMPLATE = (pathlib.Path(__file__).parent / "template.html").read_text()

    def __init__(self, header, main, dialog, dialog_label: str):

        self.add_panel("header", header)
        self.add_panel("main", main)
        self.add_panel("dialog", dialog)
        self.add_variable("dialog_label", dialog_label)

"""Panel application show casing a Custom Panel Template With a Dialog"""
import hvplot.pandas  # pylint: disable=unused-import
import panel as pn
from bokeh.sampledata import sea_surface_temperature as sst

from .template import TemplateWithDialog

def _get_sea_surface_temperature_plot():
    if "dialog_template_plot" not in pn.state.cache:
        pn.state.cache["dialog_template_plot"] = sst.sea_surface_temperature.hvplot.kde().opts(
            height=300, width=500
    return pn.state.cache["dialog_template_plot"]

def view():
    """Returns a Panel application show casing a Custom Panel Template With a Dialog"""
    top_panel = pn.Row(
    main_panel = pn.Column(
        "This is a Panel application with a dialog",
        "Provided by",
    dialog_panel = pn.Column(_get_sea_surface_temperature_plot(), sizing_mode="fixed")

    template = TemplateWithDialog(
        dialog_label="HvPlot - Sea surface temperature kde",

    return template

Very nice example! I’ve been wondering how to do that.

1 Like

We should learn more about custom templates @Jhsmit :+1:

With a component library like shoelace, fast, material Mwc, sap ui 5 etc you can actually create lots of awesome and modern layouts for you panel app.

Amazing! can we communicate with that example?

For example, get yes/no answer, get inputs values and such?

1 Like


You can place any panel components inside the pn.Column of the dialog_panel. So replace the plot with markdown, checkboxes, radioboxes etc.

1 Like

[quote=“Marc, post:4, topic:1207”]

Hello Guys,
Do these do anything? Can we get feedback from shoelace when the ‘close’ button is pressed?

 dialog_open = param.Action()
 dialog_close = param.Action()


1 Like

I would think so. But how i actually dont know.

Thanks for sharing this. It tried using it at my end. The only trouble is that it is transparent and I see the text behind appearing on the dialog box. I know may be it can be controlled using CSS or the like, but I am not so experienced. I must add that it is happening only within the Jupyter Notebook. When served, the app is fine, just as you showed.


Hi @sam_panel,

The templates provided by panel have now a modal list-like attribute you can populate (as you can already do with the sidebar or the header) with items. They can be controlled from Python with .open_modal() and .close_modal(). Here is an example from the current dev docs:

import time

import panel as pn
import numpy as np
import holoviews as hv


bootstrap = pn.template.BootstrapTemplate(title='Bootstrap Template')

xs = np.linspace(0, np.pi)
freq = pn.widgets.FloatSlider(name="Frequency", start=0, end=10, value=2)
phase = pn.widgets.FloatSlider(name="Phase", start=0, end=np.pi)

@pn.depends(freq=freq, phase=phase)
def sine(freq, phase):
    return hv.Curve((xs, np.sin(xs*freq+phase))).opts(
        responsive=True, min_height=400)

@pn.depends(freq=freq, phase=phase)
def cosine(freq, phase):
    return hv.Curve((xs, np.cos(xs*freq+phase))).opts(
        responsive=True, min_height=400)


        pn.Card(hv.DynamicMap(sine), title='Sine'),
        pn.Card(hv.DynamicMap(cosine), title='Cosine')

# Callback that will be called when the About button is clicked
def about_callback(event):

# Create, link and add the button to the sidebar
btn = pn.widgets.Button(name="About")

# Add some content to the modal
bootstrap.modal.append("# About...")


Thanks @maximlt for the code and the pointers to the modal attribute. I am glad that things are so richly provided all within Panel.