I was thinking that Panel needs a Toast (pop up notification) component. So here is a first prototype is should already be quite useable for a variety of use cases. Its based on Notyf
Implementation
Implemented using Panels ReactiveHTML
import panel as pn
import param
from panel.reactive import ReactiveHTML
class Notyf(ReactiveHTML):
_template = """<div id="toast"></div>"""
duration = param.Integer(2000, bounds=(0,15000))
ripple = param.Boolean(True)
position_x = param.Selector(default="right", objects=["left", "right"])
position_y = param.Selector(default="bottom", objects=["bottom", "top"])
dismissible = param.Boolean(False)
types = param.List([])
_dismiss_all = param.Integer()
_error = param.String("")
_success = param.String("")
def error(self, message):
self._error = message
def success(self, message):
self._success = message
def dismiss_all(self):
self._dismiss_all += 1
def __init__(self, **params):
if not params:
params={}
params["height"]=params["width"]=params["margin"]=0
params["sizing_mode"]="fixed"
super().__init__(**params)
__css__ = ["https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.css"]
__javascript__ = ["https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.js"]
_scripts = {
"render": """
function newNotyf(data) {
var config = {
duration: data.duration,
ripple: data.ripple,
position: {x: data.position_x, y: data.position_y},
dismissible: data.dismissible,
types: data.types
}
window.panelNotyf = new Notyf( config )
}
state.newNotyf=newNotyf
state.newNotyf(data)
""",
"_error": """if ( data._error !==""){window.panelNotyf.error( data._error );data._error="";}""",
"_success": """if ( data._success !==""){window.panelNotyf.success( data._success );data._success="";}""",
"_dismiss_all": """window.panelNotyf.dismissAll();""",
"duration": """state.newNotyf(data)""",
"ripple": """state.newNotyf(data)""",
"position_x": """state.newNotyf(data)""",
"position_y": """state.newNotyf(data)""",
"dismissible": """state.newNotyf(data)""",
"types": """state.newNotyf(data)""",
}
Use
pn.extension(sizing_mode="stretch_width")
ACCENT_COLOR = "#db7093"
# ACCENT_COLOR = "#1e90ff"
notyf = Notyf(types=[{"type": "error", "background": "red"}, {"type": "success", "background": ACCENT_COLOR}])
success_button = pn.widgets.Button(name="Success", button_type="primary")
@pn.depends(clicks=success_button.param.clicks, watch=True)
def _update_success(clicks):
notyf.success( str(clicks) + " success clicks" )
error_button = pn.widgets.Button(name="Error", button_type="primary")
@pn.depends(clicks=error_button.param.clicks, watch=True)
def _update_error(clicks):
notyf.error( str(clicks) + " error clicks" )
dismiss_all_button = pn.widgets.Button(name="Dismiss All", button_type="success")
@pn.depends(clicks=dismiss_all_button.param.clicks, watch=True)
def _update_dismiss_all(clicks):
notyf.dismiss_all()
pn.template.FastListTemplate(
site="Awesome Panel",
title="Toast",
main=[
pn.Row(notyf, success_button, error_button, dismiss_all_button),
pn.Param(notyf.param, parameters=["duration", "ripple", "position_x", "position_y", "dismissible", "types"])
],
header_background=ACCENT_COLOR,
accent_base_color=ACCENT_COLOR,
).servable()
Serve it using panel serve name_of_script.py
(or .ipynb
).