How to use pn.Modal in combination with a template

I would like to use a modal in combination with a template. For simplicity, for now I am only interested in a TextInput field inside the modal. I know that the template exposes the .open_modal() / .close_modal() methods, but these are less flexible than the pn.Modal layout, namely I want to be able to:

  1. Not show a close button in the top-right of the modal
  2. Not close the modal upon clicking the background
  3. Dynamically resize the modal to its content

I have not found a way to do these three things using the template’s modal, but I can do it using pn.Modal. I am unsure how to utilize pn.Modal in combination with a template. For example, when placing the modal into the template’s main or header, the modal does not render correctly. When placing it in the template’s sidebar it does render correctly, but the TextInput requires two click to gain focus.

import panel as pn

pn.extension("modal")

modal_content = pn.Column(pn.widgets.TextInput(name="Input source"))
modal = pn.Modal(
    modal_content, open=False, show_close_button=False, background_close=False
)
open_button = pn.widgets.Button(name="Open Modal")
open_button.on_click(lambda event: modal.show())

layout = pn.Column(open_button, modal)

template = pn.template.FastListTemplate(
    sidebar=layout,
    sidebar_width=400,
)
template.servable()

What is the proper way to use a pn.Modal in combination with a template?

At least you should provide a list to the sidebar sidebar=[layout],:

import panel as pn

pn.extension("modal")

modal_content = pn.Column(pn.widgets.TextInput(name="Input source"))
modal = pn.Modal(
    modal_content, open=False, show_close_button=False, background_close=False
)
open_button = pn.widgets.Button(name="Open Modal")
open_button.on_click(lambda event: modal.show())

layout = pn.Column(open_button, modal)

template = pn.template.FastListTemplate(
    sidebar=[layout],
    sidebar_width=400,
)
template.servable()

Hi Marc, Thanks for your feedback!

You got me a bit closer, and while this works for the minimal example case I sent, it did not work for my actual app. I did a bit of digging and it seems that this has to do with the type of button I used. Replacing the Button in your example with a ButtonIcon, we get the issue again where the TextInput requires two clicks to gain focus.

import panel as pn

pn.extension("modal")

modal_content = pn.Column(pn.widgets.TextInput(name="Input source"))
modal = pn.Modal(
    modal_content, open=False, show_close_button=False, background_close=False
)
open_button = pn.widgets.ButtonIcon(icon="meeple")
open_button.on_click(lambda event: modal.show())

layout = pn.Column(open_button, modal)

template = pn.template.FastListTemplate(
    sidebar=[layout],
    sidebar_width=400,
)
template.servable()