Hi All
I would like to have a floating panel in Panel. For example for having a floating panel of widgets on top of a map.
I’ve seen @nghenzi experiment with this. But I’ve also found jsPanel which provides a lot of possibilities.
Starting Point
As a starting point I can create something like
import panel as pn
import param
RAW_CSS = """
body {
    margin: 0px;}
"""
if not RAW_CSS in pn.config.raw_css:
    pn.config.raw_css.append(RAW_CSS)
pn.extension()
class JsPanel(pn.reactive.ReactiveHTML):
    _template = """
<div id="floating-panel"></div>
"""
    __css__ = ["https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/jspanel.css"]
    __javascript__ = [
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/jspanel.js",
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal.js",
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip.js",
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint.js",
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout.js",
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu.js",
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock.js",
    ]
    _scripts = {
        "render": """
var config = {
    position: 'right-top',
    content: '<p>I want my widgets here!</p>',
    contentSize: '500 350',
    headerTitle: 'Settings',
    theme: 'primary',
    callback: function(panel) {
        // do something if needed ...
    }
}
jsPanel.create(config);
"""
    }
pn.Column(
    pn.Spacer(background="lightblue", sizing_mode="stretch_both", margin=0),
    JsPanel(),
    sizing_mode="stretch_both",
).servable()
Adding the widget to the app
I can add a widget to the app like shown below
import panel as pn
import param
RAW_CSS = """
body {
    margin: 0px;}
"""
if not RAW_CSS in pn.config.raw_css:
    pn.config.raw_css.append(RAW_CSS)
pn.extension()
class JsPanel(pn.reactive.ReactiveHTML):
    object = param.Parameter()
    _template = """
<div id="element">${object}</div>
"""
    __css__ = ["https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/jspanel.css"]
    __javascript__ = [
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/jspanel.js",
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal.js",
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip.js",
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint.js",
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout.js",
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu.js",
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock.js",
    ]
    _scripts = {
        "render": """
var config = {
    position: 'right-top',
    content: '<p>I want my widget here!</p>',
    contentSize: '500 350',
    headerTitle: 'Settings',
    theme: 'primary',
    callback: function(panel) {
        // do something if needed ...
    }
}
jsPanel.create(config);
"""
    }
pn.Column(
    JsPanel(object=pn.widgets.Button(name="My Widget")),
    pn.Spacer(sizing_mode="stretch_both", margin=0),
    sizing_mode="stretch_both",background="lightblue"
).servable()
I can use a div as content of the Panel
If I set
_template = """
<div id="element">Some Text I've added to a div element that is used inside the jsPanel</div>
"""
and content to element, the div is shown inside the Panel.
import panel as pn
import param
RAW_CSS = """
body {
    margin: 0px;}
"""
if not RAW_CSS in pn.config.raw_css:
    pn.config.raw_css.append(RAW_CSS)
pn.extension()
class JsPanel(pn.reactive.ReactiveHTML):
    _template = """
<div id="element">Some Text I've added to a div element that is used inside the jsPanel</div>
"""
    __css__ = ["https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/jspanel.css"]
    __javascript__ = [
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/jspanel.js",
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal.js",
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip.js",
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint.js",
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout.js",
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu.js",
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock.js",
    ]
    _scripts = {
        "render": """
var config = {
    position: 'right-top',
    content: element,
    contentSize: '500 350',
    headerTitle: 'Settings',
    theme: 'primary',
    callback: function(panel) {
        // do something if needed ...
    }
}
jsPanel.create(config);
"""
    }
pn.Column(
    JsPanel(object=pn.widgets.Button(name="My Widget")),
    pn.Spacer(sizing_mode="stretch_both", margin=0),
    sizing_mode="stretch_both",background="lightblue"
).servable()
Move the widget inside the div element
If I set
_template = """
<div id="element">${object}</div>
"""
where object=pn.widgets.Button(name="My Widget") then I get the error
'element' is not defined
import panel as pn
import param
RAW_CSS = """
body {
    margin: 0px;}
"""
if not RAW_CSS in pn.config.raw_css:
    pn.config.raw_css.append(RAW_CSS)
pn.extension()
class JsPanel(pn.reactive.ReactiveHTML):
    object = param.Parameter()
    _template = """
<div id="element">${object}</div>
"""
    __css__ = ["https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/jspanel.css"]
    __javascript__ = [
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/jspanel.js",
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal.js",
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip.js",
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint.js",
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout.js",
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu.js",
        "https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock.js",
    ]
    _scripts = {
        "render": """
var config = {
    position: 'right-top',
    content: element,
    contentSize: '500 350',
    headerTitle: 'Settings',
    theme: 'primary',
    callback: function(panel) {
        // do something if needed ...
    }
}
jsPanel.create(config);
"""
    }
pn.Column(
    JsPanel(object=pn.widgets.Button(name="My Widget")),
    pn.Spacer(sizing_mode="stretch_both", margin=0),
    sizing_mode="stretch_both",background="lightblue"
).servable()
            





