from dash import html
from dash.dependencies import Input, Output, State
from dash.exceptions import PreventUpdate
from crystal_toolkit.core.mpcomponent import MPComponent
from crystal_toolkit.helpers.layouts import Reveal
[docs]class PanelComponent(MPComponent):
"""
A component intended to do wrap another component or set of components
inside a panel. The key benefit is that the inner contents of the panel
are not loaded until the panel is opened, so can reduce the number of
callbacks run until a user initiates interaction.
To use, implement the "contents_layout" method, and add any new
callbacks necessary to fill it.
"""
@property
def title(self):
return "Untitled Panel"
@property
def description(self):
return None
[docs] def panel_layout(self, open_by_default=False):
message = html.Div(id=self.id("message"))
description = html.Div(
self.description,
id=self.id("description"),
className="mpc-panel-description",
)
initial_contents = html.Div(id=self.id("contents"))
panel = Reveal(
title=self.title,
children=[message, description, html.Br(), initial_contents],
id=self.id("panel"),
summary_id=self.id("panel_summary"),
open=open_by_default,
)
return panel
[docs] def contents_layout(self) -> html.Div:
raise NotImplementedError
[docs] def generate_callbacks(self, app, cache):
pass
@app.callback(
Output(self.id("contents"), "children"),
[Input(self.id("panel_summary"), "n_clicks")],
[State(self.id("contents"), "children")],
)
def load_panel(panel_n_clicks, current_contents):
if current_contents or panel_n_clicks is None:
raise PreventUpdate
return html.Div(self.contents_layout(), id=self.id("inner_contents"))