""" This app creates a collapsible, responsive sidebar layout with dash-bootstrap-components and some custom css with media queries. When the screen is small, the sidebar moved to the top of the page, and the links get hidden in a collapse element. We use a callback to toggle the collapse when on a small screen, and the custom CSS to hide the toggle, and force the collapse to stay open when the screen is large. dcc.Location is used to track the current location, a callback uses the current location to render the appropriate page content. The active prop of each NavLink is set automatically according to the current pathname. To use this feature you must install dash-bootstrap-components >= 0.11.0. For more details on building multi-page Dash applications, check out the Dash documentation: https://dash.plotly.com/urls """ import sys sys.path.append('/workspace') import dash import dash_bootstrap_components as dbc from dash import Input, Output, State, dcc, html, page_container from dash_iconify import DashIconify # import callbacks.ui_callbacks import dashboard.callbacks.appointments_callbacks import dashboard.callbacks.appointment_modal_callbacks import dash_mantine_components as dmc app = dash.Dash( external_stylesheets=[dbc.themes.BOOTSTRAP], # these meta_tags ensure content is scaled correctly on different devices # see: https://www.w3schools.com/css/css_rwd_viewport.asp for more meta_tags=[{"name": "viewport", "content": "width=device-width, initial-scale=1"}], use_pages=True, suppress_callback_exceptions=True, ) nav_items = [ {"label": "Übersicht", "href": "/overview", "icon": "mdi:view-dashboard"}, {"label": "Termine", "href": "/appointments","icon": "mdi:calendar"}, {"label": "Bildschirme", "href": "/clients", "icon": "mdi:monitor"}, {"label": "Einstellungen","href": "/settings", "icon": "mdi:cog"}, {"label": "Benutzer", "href": "/users", "icon": "mdi:account"}, ] nav_links = [] for item in nav_items: # Create a NavLink for each item link_id = {"type": "nav-item", "index": item["label"]} nav_link = dbc.NavLink( [ DashIconify(icon=item["icon"], width=24), html.Span(item["label"], className="ms-2 sidebar-label"), ], href=item["href"], active="exact", className="sidebar-item", id=link_id, ) nav_links.append( html.Div( children=nav_link, className="nav-item-container" ) ) # we use the Row and Col components to construct the sidebar header # it consists of a title, and a toggle, the latter is hidden on large screens sidebar_header = dbc.Row( [ dbc.Col(html.H2("Sidebar", className="display-4")), dbc.Col( [ html.Button( # use the Bootstrap navbar-toggler classes to style html.Span(className="navbar-toggler-icon"), className="navbar-toggler", # the navbar-toggler classes don't set color style={ "color": "rgba(0,0,0,.5)", "border-color": "rgba(0,0,0,.1)", }, id="navbar-toggle", ), html.Button( # use the Bootstrap navbar-toggler classes to style html.Span(className="navbar-toggler-icon"), className="navbar-toggler", # the navbar-toggler classes don't set color style={ "color": "rgba(0,0,0,.5)", "border-color": "rgba(0,0,0,.1)", }, id="sidebar-toggle", ), ], # the column containing the toggle will be only as wide as the # toggle, resulting in the toggle being right aligned width="auto", # vertically align the toggle in the center align="center", ), ] ) sidebar = html.Div( [ sidebar_header, # we wrap the horizontal rule and short blurb in a div that can be # hidden on a small screen html.Div( [ html.Hr(), html.P( "A responsive sidebar layout with collapsible navigation " "links.", className="lead", ), ], id="blurb", ), # use the Collapse component to animate hiding / revealing links dbc.Collapse( dbc.Nav( nav_links, # <-- Korrigiert: keine zusätzliche Liste vertical=True, pills=True, ), id="collapse", ), ], id="sidebar", ) content = dmc.MantineProvider([ html.Div( html.Div(page_container, className="page-content"),style={"flex": "1", "padding": "20px"} ) ]) app.layout = html.Div([dcc.Location(id="url"), sidebar, content]) # @app.callback(Output("page-content", "children"), [Input("url", "pathname")]) # def render_page_content(pathname): # if pathname == "/": # return html.P("This is the content of the home page!") # elif pathname == "/page-1": # return html.P("This is the content of page 1. Yay!") # elif pathname == "/page-2": # return html.P("Oh cool, this is page 2!") # # If the user tries to reach a different page, return a 404 message # return html.Div( # [ # html.H1("404: Not found", className="text-danger"), # html.Hr(), # html.P(f"The pathname {pathname} was not recognised..."), # ], # className="p-3 bg-light rounded-3", # ) @app.callback( [Output("sidebar", "className"), Output("collapse", "is_open")], [ Input("sidebar-toggle", "n_clicks"), Input("navbar-toggle", "n_clicks"), ], [ State("sidebar", "className"), State("collapse", "is_open"), ], ) def toggle_sidebar_and_collapse(sidebar_n, navbar_n, classname, is_open): ctx = dash.callback_context if not ctx.triggered: return classname, is_open trigger_id = ctx.triggered[0]["prop_id"].split(".")[0] if trigger_id == "sidebar-toggle": # Toggle sidebar collapse if sidebar_n and classname == "": return "collapsed", is_open return "", is_open elif trigger_id == "navbar-toggle": # Toggle collapse if navbar_n: return classname, not is_open return classname, is_open return classname, is_open if __name__ == "__main__": app.run(port=8888, debug=True)