Skip to content

Commit 10c2c68

Browse files
authored
Merge pull request #489 from facultyai/sidebar-with-icons-example
Add collapsible sidebar with icons example
2 parents dd5772e + b2238f9 commit 10c2c68

File tree

2 files changed

+183
-0
lines changed
  • examples/multi-page-apps/collapsible-sidebar-with-icons

2 files changed

+183
-0
lines changed
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
"""
2+
This app creates an animated sidebar using the dbc.Nav component and some local
3+
CSS. Each menu item has an icon, when the sidebar is collapsed the labels
4+
disappear and only the icons remain. Visit www.fontawesome.com to find
5+
alternative icons to suit your needs!
6+
7+
dcc.Location is used to track the current location, setting the page content
8+
and the active menu item via callbacks.
9+
10+
For more details on building multi-page Dash applications, check out the Dash
11+
documentation: https://dash.plot.ly/urls
12+
"""
13+
import dash
14+
import dash_bootstrap_components as dbc
15+
import dash_core_components as dcc
16+
import dash_html_components as html
17+
from dash.dependencies import Input, Output
18+
19+
FA = "https://use.fontawesome.com/releases/v5.15.1/css/all.css"
20+
PLOTLY_LOGO = "https://images.plot.ly/logo/new-branding/plotly-logomark.png"
21+
22+
app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP, FA])
23+
24+
sidebar = html.Div(
25+
[
26+
html.Div(
27+
[
28+
# width: 3rem ensures the logo is the exact width of the
29+
# collapsed sidebar (accounting for padding)
30+
html.Img(src=PLOTLY_LOGO, style={"width": "3rem"}),
31+
html.H2("Sidebar"),
32+
],
33+
className="sidebar-header",
34+
),
35+
html.Hr(),
36+
dbc.Nav(
37+
[
38+
dbc.NavLink(
39+
[html.I(className="fas fa-home mr-2"), html.Span("Home")],
40+
href="/",
41+
id="home-link",
42+
),
43+
dbc.NavLink(
44+
[
45+
html.I(className="fas fa-calendar-alt mr-2"),
46+
html.Span("Calendar"),
47+
],
48+
href="/calendar",
49+
id="calendar-link",
50+
),
51+
dbc.NavLink(
52+
[
53+
html.I(className="fas fa-envelope-open-text mr-2"),
54+
html.Span("Messages"),
55+
],
56+
href="/messages",
57+
id="messages-link",
58+
),
59+
],
60+
vertical=True,
61+
pills=True,
62+
),
63+
],
64+
className="sidebar",
65+
)
66+
67+
content = html.Div(id="page-content", className="content")
68+
69+
app.layout = html.Div([dcc.Location(id="url"), sidebar, content])
70+
71+
72+
# set the content according to the current pathname
73+
@app.callback(Output("page-content", "children"), [Input("url", "pathname")])
74+
def render_page_content(pathname):
75+
if pathname == "/":
76+
return html.P("This is the home page!")
77+
elif pathname == "/calendar":
78+
return html.P("This is your calendar... not much in the diary...")
79+
elif pathname == "/messages":
80+
return html.P("Here are all your messages")
81+
# If the user tries to reach a different page, return a 404 message
82+
return dbc.Jumbotron(
83+
[
84+
html.H1("404: Not found", className="text-danger"),
85+
html.Hr(),
86+
html.P(f"The pathname {pathname} was not recognised..."),
87+
]
88+
)
89+
90+
91+
# sets the active property on the navlink corresponding to the current page
92+
@app.callback(
93+
[
94+
Output(link_id, "active")
95+
for link_id in ["home-link", "calendar-link", "messages-link"]
96+
],
97+
[Input("url", "pathname")],
98+
)
99+
def toggle_active_links(pathname):
100+
if pathname == "/":
101+
return True, False, False
102+
elif pathname == "/calendar":
103+
return False, True, False
104+
elif pathname == "/messages":
105+
return False, False, True
106+
return False, False, False
107+
108+
109+
if __name__ == "__main__":
110+
app.run_server(debug=True)
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/* This creates a skinny side bar fixed to the left of the page */
2+
.sidebar {
3+
position: fixed;
4+
top: 0;
5+
left: 0;
6+
bottom: 0;
7+
width: 5rem;
8+
padding: 2rem 1rem;
9+
background-color: #f8f9fa;
10+
z-index: 1050;
11+
transition: width 0.1s ease-in-out;
12+
}
13+
14+
/* when the user hovers on the sidebar, expand it */
15+
.sidebar:hover {
16+
width: 16rem;
17+
}
18+
19+
/* make sure the contents of the navlink don't wrap when navbar collapses */
20+
.sidebar .nav-link {
21+
width: 100%;
22+
overflow: hidden;
23+
white-space: nowrap;
24+
}
25+
26+
/* fix the width of the icons */
27+
.sidebar .nav-link i {
28+
width: 1rem;
29+
}
30+
31+
/* hide the navlink labels by default */
32+
.sidebar .nav-link span {
33+
visibility: hidden;
34+
opacity: 0;
35+
transition: opacity 0.1s ease-in-out;
36+
}
37+
38+
/* when the sidebar is hovered, reveal the labels */
39+
.sidebar:hover .nav-link span {
40+
visibility: visible;
41+
opacity: 1;
42+
}
43+
44+
/* container for the sidebar header. make sure the contents don't wrap when
45+
* the sidebar is collapsed.
46+
*/
47+
.sidebar-header {
48+
display: flex;
49+
justify-content: left;
50+
align-items: center;
51+
overflow: hidden;
52+
white-space: nowrap;
53+
}
54+
55+
/* position the header relative to the logo and hide by default */
56+
.sidebar-header h2 {
57+
opacity: 0;
58+
margin-left: 1rem;
59+
margin-bottom: 0;
60+
transition: opacity 0.1s ease-in-out;
61+
}
62+
63+
/* reveal the header when the sidebar is toggled */
64+
.sidebar:hover .sidebar-header h2 {
65+
opacity: 1;
66+
}
67+
68+
/* position the content relative to the collapsed sidebar */
69+
.content {
70+
margin-left: 7rem;
71+
margin-right: 2rem;
72+
padding: 2rem 1rem;
73+
}

0 commit comments

Comments
 (0)