From 8097ea32deec0aea1d6bf5001fa5aa5c6d84d7d6 Mon Sep 17 00:00:00 2001 From: tcbegley Date: Fri, 12 Mar 2021 17:45:29 +0000 Subject: [PATCH 1/9] Add theme explorer infrastructure --- docs/demos/__init__.py | 55 ++++++++++++++++ docs/demos/theme_explorer.py | 11 ++++ docs/run.py | 4 +- docs/server.py | 22 ++++++- docs/static/js/theme-switcher.js | 66 +++++++++++++++++++ docs/static/theme-explorer.css | 66 +++++++++++++++++++ .../macros/theme-explorer-navbar.html | 23 +++++++ docs/templates/partials/head.html | 1 + docs/templates/theme-explorer.html | 58 ++++++++++++++++ 9 files changed, 304 insertions(+), 2 deletions(-) create mode 100644 docs/demos/theme_explorer.py create mode 100644 docs/static/js/theme-switcher.js create mode 100644 docs/static/theme-explorer.css create mode 100644 docs/templates/macros/theme-explorer-navbar.html create mode 100644 docs/templates/theme-explorer.html diff --git a/docs/demos/__init__.py b/docs/demos/__init__.py index e69de29bb..5095c219b 100644 --- a/docs/demos/__init__.py +++ b/docs/demos/__init__.py @@ -0,0 +1,55 @@ +import os +from pathlib import Path + +import dash +from jinja2 import Environment, FileSystemLoader + +from .theme_explorer import app as theme_explorer + +SERVE_LOCALLY = os.getenv("DBC_DOCS_MODE", "production") == "dev" + +HERE = Path(__file__).parent +TEMPLATES = HERE.parent / "templates" + +INDEX_STRING_TEMPLATE = """{% extends "theme-explorer.html" %} +{% block head %} +{{ super() }} +{{ "{%metas%}{%css%}" }} +{% endblock %} +{% block title %} +{{ "{%title%}" }} +{% endblock %} +{% block content %} +{{ "{%app_entry%}" }} +{% endblock %} +{% block code %}{% endblock %} +{% block scripts %} +
+ {{ "{%config%}{%scripts%}{%renderer%}" }} + {{ super() }} +
+{% endblock %} +""" + + +def register_apps(): + env = Environment(loader=FileSystemLoader(TEMPLATES.as_posix())) + template = env.from_string(INDEX_STRING_TEMPLATE) + template = template.render() + + code = (HERE / "theme_explorer.py").read_text() + + new_theme_explorer = dash.Dash( + external_stylesheets=["/static/loading.css"], + requests_pathname_prefix="/docs/themes/explorer/", + suppress_callback_exceptions=True, + serve_locally=SERVE_LOCALLY, + index_string=template.replace("", code), + update_title=None, + ) + + new_theme_explorer.title = "Theme explorer - dbc docs" + new_theme_explorer.layout = theme_explorer.layout + new_theme_explorer.callback_map = theme_explorer.callback_map + new_theme_explorer._callback_list = new_theme_explorer._callback_list + return {"/docs/themes/explorer": new_theme_explorer} diff --git a/docs/demos/theme_explorer.py b/docs/demos/theme_explorer.py new file mode 100644 index 000000000..edf883bd4 --- /dev/null +++ b/docs/demos/theme_explorer.py @@ -0,0 +1,11 @@ +import dash +import dash_bootstrap_components as dbc + +app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP]) + +app.layout = dbc.Container( + dbc.Alert("Testing, testing", color="success"), className="p-5" +) + +if __name__ == "__main__": + app.run_server(debug=True) diff --git a/docs/run.py b/docs/run.py index 1b437fea1..74b23c9d8 100644 --- a/docs/run.py +++ b/docs/run.py @@ -1,6 +1,7 @@ from werkzeug.middleware.dispatcher import DispatcherMiddleware from components_page import register_apps as register_component_apps +from demos import register_apps as register_demo_apps from examples import register_apps as register_example_apps from markdown_to_html import convert_all_markdown_files from server import create_server @@ -10,7 +11,8 @@ server = create_server() component_routes = register_component_apps() example_routes = register_example_apps() -routes = {**component_routes, **example_routes} +demo_routes = register_demo_apps() +routes = {**component_routes, **example_routes, **demo_routes} application = DispatcherMiddleware( server, {slug: app.server for slug, app in routes.items()} ) diff --git a/docs/server.py b/docs/server.py index 52dec5100..a7b259170 100644 --- a/docs/server.py +++ b/docs/server.py @@ -8,6 +8,25 @@ {"name": "components", "href": "/docs/components", "label": "Components"}, ] +THEMES_SIDENAV_ITEMS = DOCS_SIDENAV_ITEMS[:] +THEMES_SIDENAV_ITEMS[1] = { + "name": "themes", + "href": "/docs/themes", + "label": "Themes", + "children": [ + { + "name": "overview", + "href": "/docs/themes/", + "label": "Overview", + }, + { + "name": "explorer", + "href": "/docs/themes/explorer", + "label": "Theme explorer", + } + ], +} + def create_server(): server = Flask(__name__) @@ -36,8 +55,9 @@ def themes(): try: return render_template( "generated/docs/themes.html", - sidenav_items=DOCS_SIDENAV_ITEMS, + sidenav_items=THEMES_SIDENAV_ITEMS, sidenav_active="themes", + active_child="overview", ) except TemplateNotFound: abort(404) diff --git a/docs/static/js/theme-switcher.js b/docs/static/js/theme-switcher.js new file mode 100644 index 000000000..d7ef89832 --- /dev/null +++ b/docs/static/js/theme-switcher.js @@ -0,0 +1,66 @@ +var bootstrap = + 'https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css'; +var bootswatchBase = 'https://stackpath.bootstrapcdn.com/bootswatch/4.5.2/'; +var bootswatchSfx = '/bootstrap.min.css'; + +var validBootswatch = new Set([ + 'cerulean', + 'cosmo', + 'cyborg', + 'darkly', + 'flatly', + 'journal', + 'litera', + 'lumen', + 'lux', + 'materia', + 'minty', + 'pulse', + 'sandstone', + 'simplex', + 'sketchy', + 'slate', + 'solar', + 'spacelab', + 'superhero', + 'united', + 'yeti' +]); + +function swapStyleSheet(sheetname) { + if (sheetname === 'bootstrap') { + document.getElementById('stylesheet').setAttribute('href', bootstrap); + } else if (validBootswatch.has(sheetname)) { + document + .getElementById('stylesheet') + .setAttribute('href', bootswatchBase + sheetname + bootswatchSfx); + } +} + +function updateSourceCode(sheetname) { + var container = document.getElementById('code-container'); + for (var j = 0; j < container.childNodes.length; j++) { + var node = container.childNodes[j]; + if (node.nodeType === 3) { + var text = node.nodeValue; + var replacedText = text.replace( + /dbc.themes.[A-Z]+/gi, + 'dbc.themes.' + sheetname.toUpperCase() + ); + if (replacedText !== text) { + container.replaceChild(document.createTextNode(replacedText), node); + break; + } + } + } +} + +function handleChange(e) { + if (e.target.value) { + var sheetname = e.target.value; + swapStyleSheet(sheetname); + updateSourceCode(sheetname); + } +} + +document.getElementById('theme-switcher').onchange = handleChange; diff --git a/docs/static/theme-explorer.css b/docs/static/theme-explorer.css new file mode 100644 index 000000000..3422172e3 --- /dev/null +++ b/docs/static/theme-explorer.css @@ -0,0 +1,66 @@ +.te-navbar { + /* navbar */ + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: justify; + justify-content: space-between; + padding: 0.5rem 1rem; + + /* bg-dark */ + background-color: #343a40 !important; + + /* sticky-top */ + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; + + /* .navbar-expand */ + -ms-flex-flow: row nowrap; + flex-flow: row nowrap; + -ms-flex-pack: start; + justify-content: flex-start; + + margin: 0; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + text-align: left; +} + +.te-navbar-nav { + display: flex; + padding-left: 0; + margin-bottom: 0; + list-style: none; + + -ms-flex-direction: row; + flex-direction: row; +} + +.te-nav-link { + /* navbar-expand nav-link */ + padding-right: 0.5rem; + padding-left: 0.5rem; + + /* navbar-dark nav-link */ + color: rgba(255, 255, 255, 0.5); + + /* nav-link */ + display: block; + padding: 0.5rem 1rem; + + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, + 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', + 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; +} + +.te-nav-link:hover, +.te-nav-link:focus { + text-decoration: none; + color: rgba(255, 255, 255, 0.75); +} diff --git a/docs/templates/macros/theme-explorer-navbar.html b/docs/templates/macros/theme-explorer-navbar.html new file mode 100644 index 000000000..08f726fb6 --- /dev/null +++ b/docs/templates/macros/theme-explorer-navbar.html @@ -0,0 +1,23 @@ +{% macro theme_explorer_navbar() -%} + +{%- endmacro %} diff --git a/docs/templates/partials/head.html b/docs/templates/partials/head.html index 11af807b1..d18a5d5c9 100644 --- a/docs/templates/partials/head.html +++ b/docs/templates/partials/head.html @@ -1,6 +1,7 @@ diff --git a/docs/templates/theme-explorer.html b/docs/templates/theme-explorer.html new file mode 100644 index 000000000..c08d05ba0 --- /dev/null +++ b/docs/templates/theme-explorer.html @@ -0,0 +1,58 @@ +{% from "macros/theme-explorer-navbar.html" import theme_explorer_navbar %} {% +extends "base.html" %} {% block head %} {% include "partials/head.html" %} + +{% endblock %} {% block header %}{{ theme_explorer_navbar() }}{% endblock %} {% +block body %} +
+ +
+
+
+ {% block content %}{% endblock %} +
+
+

Source Code

+ +
{% block code %}{% endblock %}
+
+
+{% endblock %} {% block scripts %} {% include "partials/scripts.html" %} + +{% endblock %} From dce43e768360521f65b810f6ec519f28296561c5 Mon Sep 17 00:00:00 2001 From: tcbegley Date: Fri, 12 Mar 2021 17:58:05 +0000 Subject: [PATCH 2/9] Fix linting issues --- docs/server.py | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/server.py b/docs/server.py index a7b259170..fcec16071 100644 --- a/docs/server.py +++ b/docs/server.py @@ -23,7 +23,7 @@ "name": "explorer", "href": "/docs/themes/explorer", "label": "Theme explorer", - } + }, ], } diff --git a/setup.cfg b/setup.cfg index 93fe50173..4bd063fae 100644 --- a/setup.cfg +++ b/setup.cfg @@ -42,7 +42,7 @@ ignore = E203, W503 [isort] multi_line_output = 3 include_trailing_comma = true -known_first_party = components_page, examples, markdown_to_html, server +known_first_party = components_page, demos, examples, markdown_to_html, server known_third_party = dash, dash_bootstrap_components, From 334ffb97287279a48d90c65a071476da41a77f54 Mon Sep 17 00:00:00 2001 From: Ann Marie Ward Date: Tue, 23 Mar 2021 10:48:11 -0700 Subject: [PATCH 3/9] component gallery --- docs/demos/theme_explorer.py | 890 ++++++++++++++++++++++++++++++++++- 1 file changed, 888 insertions(+), 2 deletions(-) diff --git a/docs/demos/theme_explorer.py b/docs/demos/theme_explorer.py index edf883bd4..35c6f510d 100644 --- a/docs/demos/theme_explorer.py +++ b/docs/demos/theme_explorer.py @@ -1,11 +1,897 @@ import dash import dash_bootstrap_components as dbc +import dash_core_components as dcc +import dash_html_components as html +from dash.dependencies import Input, Output, State + +FONT_AWESOME = "https://use.fontawesome.com/releases/v5.10.2/css/all.css" +app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP, FONT_AWESOME]) + +DBC_HOME = "https://dash-bootstrap-components.opensource.faculty.ai/" +DBC_GITHUB = "https://github.com/facultyai/dash-bootstrap-components" +DBC_DOCS = "https://dash-bootstrap-components.opensource.faculty.ai/docs/components/" + + +def make_subheading(label, link): + return html.Div( + [ + dbc.Button( + [ + html.H2( + [ + label, + html.I( + className="far fa-question-circle ml-2 mb-2 align-middle", + style={"fontSize": 18}, + id="tooltip_target" + label.replace(" ", ""), + ), + ], + ) + ], + href=DBC_DOCS + link, + target="_blank", + color="link", + ), + dbc.Tooltip( + "See " + label + " documentation ", + target="tooltip_target" + label.replace(" ", ""), + ), + ], + ) + + +alerts1 = html.Div( + [ + dbc.Alert("This is a primary alert", color="primary"), + dbc.Alert("This is a secondary alert", color="secondary"), + dbc.Alert("This is a success alert! Well done!", color="success"), + dbc.Alert("This is a warning alert... be careful...", color="warning"), + ] +) +alerts2 = html.Div( + [ + dbc.Alert("This is a danger alert. Scary!", color="danger"), + dbc.Alert("This is an info alert. Good to know!", color="info"), + dbc.Alert("This is a light alert", color="light"), + dbc.Alert("This is a dark alert", color="dark"), + ] +) + +alerts = dbc.Card( + [ + html.H2(make_subheading("Alert", "alert")), + dbc.CardBody(dbc.Row([dbc.Col(alerts1), dbc.Col(alerts2)])), + ], + className="mb-4", +) + +badge_colors = html.Span( + [ + dbc.Badge("Primary", color="primary", className="mr-1"), + dbc.Badge("Secondary", color="secondary", className="mr-1"), + dbc.Badge("Success", color="success", className="mr-1"), + dbc.Badge("Warning", color="warning", className="mr-1"), + dbc.Badge("Danger", color="danger", className="mr-1"), + dbc.Badge("Info", color="info", className="mr-1"), + dbc.Badge("Light", color="light", className="mr-1"), + dbc.Badge("Dark", color="dark"), + ], +) + +badges = dbc.Card( + [ + html.H2(make_subheading("Badge", "badge")), + dbc.CardBody( + [ + badge_colors, + html.Br(), + dbc.Button( + ["Notifications", dbc.Badge("4", color="light", className="ml-1")], + color="primary", + className="mt-2", + ), + ] + ), + ], + className="mb-4", +) + +buttons1 = dbc.Card( + [ + html.H2(make_subheading("Button", "button")), + dbc.CardBody( + [ + dbc.Button("Primary", color="primary", className="m-1"), + dbc.Button("Secondary", color="secondary", className="m-1"), + dbc.Button("Success", color="success", className="m-1"), + dbc.Button("Warning", color="warning", className="m-1"), + dbc.Button("Danger", color="danger", className="m-1"), + dbc.Button("Info", color="info", className="m-1"), + ] + ), + html.Div( + [ + dbc.Button("Primary", outline=True, color="primary", className="m-1"), + dbc.Button( + "Secondary", outline=True, color="secondary", className="m-1", + ), + dbc.Button("Success", outline=True, color="success", className="m-1"), + dbc.Button("Warning", outline=True, color="warning", className="m-1"), + dbc.Button("Danger", outline=True, color="danger", className="m-1"), + dbc.Button("Info", outline=True, color="info", className="m-1"), + ], + className="my-2", + ), + html.Div( + [ + dbc.Button("Regular", color="primary", className="m-1"), + dbc.Button("Active", color="primary", active=True, className="m-1"), + dbc.Button("Disabled", color="primary", disabled=True, className="m-1"), + dbc.Button("Large button", size="lg", className="m-1"), + dbc.Button("Regular button", className="m-1"), + dbc.Button("Small button", size="sm", className="m-1"), + ], + ), + ], + className="mb-4", +) + + +buttons2 = dbc.Card( + [ + html.H2(make_subheading("ButtonGroup", "buttongroups")), + dbc.CardBody( + [ + dbc.ButtonGroup( + [ + dbc.Button("Primary", color="primary"), + dbc.Button("Secondary", color="secondary"), + dbc.Button("Success", color="success"), + dbc.Button("Warning", color="warning"), + dbc.Button("Danger", color="danger"), + dbc.Button("Info", color="info"), + ], + className="mb-4", + ), + html.Br(), + dbc.ButtonGroup( + [ + dbc.Button("First"), + dbc.Button("Second"), + dbc.DropdownMenu( + [ + dbc.DropdownMenuItem("Item 1"), + dbc.DropdownMenuItem("Item 2"), + ], + label="Dropdown", + group=True, + ), + ], + vertical=True, + ), + ], + ), + ], + className="mb-4", +) +buttons = dbc.Row([dbc.Col(buttons1), dbc.Col(buttons2)]) + + +cards = dbc.Card( + [ + html.H2(make_subheading("Card", "card")), + dbc.CardBody( + dbc.CardDeck( + [ + dbc.Card( + [ + html.H2("Header"), + dbc.CardBody( + [ + html.H5( + "This card has a title", className="card-title", + ), + html.P("And some text", className="card-text"), + ] + ), + ] + ), + dbc.Card( + [ + dbc.CardBody( + [ + html.H5( + "This card has a title", className="card-title", + ), + html.P( + "and some text, but no header", + className="card-text", + ), + ] + ) + ], + outline=True, + color="primary", + ), + dbc.Card( + [ + dbc.CardBody( + [ + html.H5( + "This card has a title", className="card-title", + ), + html.P( + "and some text, and a footer!", + className="card-text", + ), + ] + ), + dbc.CardFooter("Footer"), + ], + outline=True, + color="dark", + ), + ] + ) + ), + ], + className="mb-4", +) + +collapse = html.Div( + [ + make_subheading("Collapse", "collapse"), + html.Div( + [ + dbc.Button( + "Open collapse", + id="collapse-button", + style={"marginBottom": "1rem"}, + ), + dbc.Collapse( + dbc.Card(dbc.CardBody("This content is hidden in the collapse")), + id="collapse", + ), + ] + ), + ], + className="mb-4", +) + +columns = dbc.Card( + [ + html.H2(make_subheading("Row Col", "layout")), + dbc.CardBody( + [ + dbc.Row( + dbc.Col(html.H4("A single column", className="border bg-light")) + ), + dbc.Row( + [ + dbc.Col( + html.H4( + "One of three columns", className="border bg-light" + ), + ), + dbc.Col( + html.H4( + "One of three columns", className="border bg-light" + ), + ), + dbc.Col( + html.H4( + "One of three columns", className="border bg-light" + ), + ), + ] + ), + ] + ), + html.Hr(), + html.H4("Row with no gutters"), + dbc.Row( + [ + dbc.Col(html.H4("Column 1 md=3", className="border bg-light"), md=3,), + dbc.Col(html.H4("Column 2 md=6", className="border bg-light"), md=6,), + dbc.Col(html.H4("column 3 md=3", className="border bg-light"), md=3,), + ], + no_gutters=True, + ), + ], + className="mb-4", +) + + +fade = html.Div( + [ + make_subheading("Fade", "fade"), + html.Div( + [ + dbc.Button( + "Toggle fade", id="fade-button", style={"marginBottom": "1rem"} + ), + dbc.Fade( + dbc.Card( + dbc.CardBody( + html.P( + "This content fades in and out", className="card-text" + ) + ) + ), + id="fade", + is_in=True, + ), + ] + ), + ], +) + + +form = dbc.Card( + [ + html.H2(make_subheading("Form", "form")), + dbc.CardBody( + [ + dbc.Form( + [ + dbc.FormGroup( + [ + dbc.Label("Username"), + dbc.Input( + placeholder="Enter your username", type="text" + ), + dbc.FormText( + [ + "Can't remember your username? ", + html.A( + "Click here.", + href="#", + className="text-muted", + style={"textDecoration": "underline"}, + ), + ] + ), + ] + ), + dbc.FormGroup( + [ + dbc.Label("Username"), + dbc.Input( + placeholder="Enter your password", type="password" + ), + dbc.FormText( + [ + "Can't remember your password? ", + html.A( + "Click here.", + href="#", + className="text-muted", + style={"textDecoration": "underline"}, + ), + ] + ), + ] + ), + ] + ), + ] + ), + ], + className="mb-4", +) + +input_ = dbc.Card( + [ + html.H2(make_subheading("Input", "input")), + dbc.CardBody( + [ + dbc.FormGroup([dbc.Label("Text input"), dbc.Input(type="text")]), + dbc.FormGroup( + [ + dbc.Label("Valid text input"), + dbc.Input(type="text", valid=True), + dbc.FormFeedback("That's a valid input!", valid=True), + ] + ), + dbc.FormGroup( + [ + dbc.Label("Invalid text input"), + dbc.Input(type="text", invalid=True), + dbc.FormFeedback("That's an invalid input..."), + ] + ), + dbc.FormGroup( + [ + dbc.Label("Color Picker"), + dbc.Input( + type="color", + value="#afc1e4", + style={"width": 100, "height": 75}, + ), + ] + ), + ] + ), + ] +) + + +checklist_items = dbc.Card( + [ + html.H2(make_subheading("Checklist", "input"),), + dbc.CardBody( + [ + dbc.Row( + [ + dbc.Col( + dbc.Checklist( + id="gallery_checklist1", + options=[ + {"label": "Option {}".format(i), "value": i} + for i in range(3) + ], + value=[1, 2], + ) + ), + dbc.Col( + dbc.Checklist( + id="gallery_checklist2", + options=[ + {"label": "Option {}".format(i), "value": i} + for i in range(3) + ], + value=[1, 2], + switch=True, + ) + ), + ] + ), + html.H5("Inline checklist", className="mt-3"), + dbc.Checklist( + id="gallery_checklist3", + options=[ + {"label": "Option {}".format(i), "value": i} for i in range(5) + ], + value=[0, 4], + inline=True, + ), + ] + ), + ], + className="mb-4", +) + +radio_items = dbc.Card( + [ + html.H2(make_subheading("RadioItems", "input"),), + dbc.CardBody( + [ + dbc.RadioItems( + id="gallery_radio1", + options=[ + {"label": "Option {}".format(i), "value": i} for i in range(3) + ], + value=0, + ), + html.H5("Inline radioitems", className="mt-3"), + dbc.RadioItems( + id="gallery_radio2", + options=[ + {"label": "Option {}".format(i), "value": i} for i in range(5) + ], + value=0, + inline=True, + ), + ] + ), + ] +) + +input_group = dbc.Card( + [ + html.H2(make_subheading("InputGroup and addons", "input_group")), + dbc.CardBody( + [ + dbc.InputGroup( + [ + dbc.InputGroupAddon( + dbc.Button("To the left!", color="danger"), + addon_type="prepend", + ), + dbc.Input(type="text"), + ] + ), + html.Br(), + dbc.InputGroup( + [ + dbc.Input(type="text"), + dbc.InputGroupAddon( + dbc.Button("To the right!", color="success"), + addon_type="append", + ), + ] + ), + html.Br(), + dbc.InputGroup( + [ + dbc.InputGroupAddon("@", addon_type="prepend"), + dbc.Input(type="text", placeholder="Enter username"), + ] + ), + ] + ), + ], + className="mb-4", +) + + +jumbotron = dbc.Card( + [ + html.H2(make_subheading("Jumbotron", "jumbotron")), + dbc.Jumbotron( + [ + html.H2("This is a jumbotron"), + html.P("It makes things big..."), + dbc.Button("Click here", color="danger"), + ] + ), + ], + className="mb-4", +) + +list_group = dbc.Card( + [ + html.H2(make_subheading("ListGroup", "list_group")), + dbc.CardBody( + [ + dbc.ListGroup( + [ + dbc.ListGroupItem("Item 1", color="primary", action=True), + dbc.ListGroupItem("Item 2"), + dbc.ListGroupItem("Item 3"), + dbc.ListGroupItem( + [ + dbc.ListGroupItemHeading("Item 4 heading"), + dbc.ListGroupItemText("Item 4 text"), + ] + ), + ] + ), + ] + ), + ], + className="mb-4", +) + + +COOKIE = ( + "https://todaysmama.com/.image/t_share/MTU5OTEwMzkyMDIyMTE1NzAz/cookie-monster.png" +) +modal = html.Div( + [ + make_subheading("Modal", "modal"), + html.P( + [ + dbc.Button("Show the cookie monster", id="button"), + dbc.Modal( + [ + dbc.ModalHeader("Cookies!"), + dbc.ModalBody(html.Img(src=COOKIE, style={"width": "100%"})), + ], + id="modal", + is_open=False, + ), + ] + ), + ] +) + +navbar = dbc.Card( + [ + dbc.Row( + [ + make_subheading("Navbar", "navbar"), + make_subheading("DropdownMenu", "dropdown_menu"), + ], + className="px-2", + ), + dbc.CardBody( + dbc.NavbarSimple( + children=[ + dbc.NavItem(dbc.NavLink("GitHub", href=DBC_GITHUB)), + dbc.DropdownMenu( + nav=True, + in_navbar=True, + label="Menu", + children=[ + dbc.DropdownMenuItem("Entry 1", href="https://google.com"), + dbc.DropdownMenuItem("Entry 2", href="/test"), + dbc.DropdownMenuItem(divider=True), + dbc.DropdownMenuItem("A heading", header=True), + dbc.DropdownMenuItem( + "Entry 3", href="/external-relative", external_link=True + ), + dbc.DropdownMenuItem("Entry 4 - does nothing"), + ], + ), + ], + brand="Dash Bootstrap Components", + brand_href=DBC_HOME, + sticky="top", + color="primary", + dark=True, + ) + ), + ] +) + +popover = html.Div( + [ + make_subheading("Popover", "popover"), + dbc.Button("Click to toggle popover", id="popover-target", color="danger"), + dbc.Popover( + [dbc.PopoverHeader("Popover header"), dbc.PopoverBody("Popover body"),], + id="popover", + is_open=False, + target="popover-target", + ), + ] +) + +progress = dbc.Card( + [ + html.H2(make_subheading("Progress", "progress")), + dbc.CardBody( + [ + dbc.Progress("25%", value=25), + dbc.Progress(value=50, striped=True, className="my-2"), + dbc.Progress(value=75, color="success"), + ] + ), + ], + className="mb-4", +) + +spinner = dbc.Card( + [ + html.H2(make_subheading("Spinner", "spinner")), + dbc.CardBody( + [ + dbc.Spinner(color="secondary"), + dbc.Spinner(color="danger", type="grow"), + dbc.Spinner(color="light", type="grow"), + dbc.Button( + [dbc.Spinner(size="sm"), " Loading..."], + color="primary", + disabled=True, + ), + ] + ), + ], + className="mb-4", +) + + +table = dbc.Card( + [ + html.H2(make_subheading("Table", "table"),), + dbc.CardBody( + dbc.Table( + [ + html.Thead( + html.Tr( + [html.Th("#"), html.Th("First name"), html.Th("Last name"),] + ) + ), + html.Tbody( + [ + html.Tr( + [ + html.Th("1", scope="row"), + html.Td("Tom"), + html.Td("Cruise"), + ] + ), + html.Tr( + [ + html.Th("2", scope="row"), + html.Td("Jodie"), + html.Td("Foster"), + ] + ), + html.Tr( + [ + html.Th("3", scope="row"), + html.Td("Chadwick"), + html.Td("Boseman"), + ] + ), + ] + ), + ], + responsive=True, + striped=True, + hover=True, + ), + ), + ], + className="mb-4", +) + +tabs = dbc.Card( + [ + make_subheading("Tabs", "tabs"), + dbc.CardBody( + dbc.Tabs( + [ + dbc.Tab( + html.H4("This is tab 1"), + label="Tab 1", + style={"padding": "10px"}, + ), + dbc.Tab( + dbc.Card( + dbc.CardBody( + [ + html.P( + "This tab has a card!", className="card-text", + ), + dbc.Button("Click here", color="success"), + ] + ) + ), + label="Tab 2", + style={"padding": "10px"}, + ), + ] + ), + ), + ], + className="my-4", +) + +toast = html.Div( + [ + make_subheading("Toast", "toast"), + dbc.Button( + "Open toast", id="auto-toast-toggle", color="primary", className="mb-3", + ), + dbc.Toast( + [html.P("This is the content of the toast", className="mb-0")], + id="auto-toast", + header="This is the header", + icon="primary", + duration=4000, + ), + ], + className="my-2", +) + +tooltip = html.Div( + [ + make_subheading("Tooltip", "tooltip"), + html.P( + [ + "I wonder what ", + html.Span("floccinaucinihilipilification", id="tooltip-target"), + " means?", + ] + ), + dbc.Tooltip( + "Noun: rare, " "the action or habit of estimating something as worthless.", + target="tooltip-target", + ), + ] +) + +source_code = dcc.Markdown( + """ + ## See the [source code](https://github.com/AnnMarieW/HelloDash/blob/main/apps/dbc_components.py) + """ +) -app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP]) app.layout = dbc.Container( - dbc.Alert("Testing, testing", color="success"), className="p-5" + [ + html.Div( + [ + alerts, + badges, + buttons, + cards, + dbc.Row([dbc.Col([form, input_group,]), dbc.Col([input_])]), + dbc.Row([dbc.Col([checklist_items]), dbc.Col([radio_items])]), + navbar, + tabs, + jumbotron, + columns, + list_group, + table, + progress, + spinner, + dbc.Card( + [ + html.H2("Dialogs", className="pl-2 text-primary"), + dbc.CardBody( + dbc.Row( + [ + dbc.Col([modal, fade, collapse,]), + dbc.Col([popover, toast, tooltip]), + ] + ), + ), + ] + ), + html.Div(style={"height": "50px"}), + source_code, + ], + className="my-2 p-4", + ), + ], + fluid=True, +) + + +@app.callback( + Output("collapse", "is_open"), + [Input("collapse-button", "n_clicks")], + [State("collapse", "is_open")], ) +def toggle_collapse(n, is_open): + if n: + return not is_open + return is_open + + +@app.callback( + Output("fade", "is_in"), + [Input("fade-button", "n_clicks")], + [State("fade", "is_in")], +) +def toggle_fade(n, is_in): + if n: + return not is_in + return is_in + + +@app.callback( + Output("popover", "is_open"), + [Input("popover-target", "n_clicks")], + [State("popover", "is_open")], +) +def toggle_popover(n, is_open): + if n: + return not is_open + return is_open + + +@app.callback( + Output("modal", "is_open"), + [Input("button", "n_clicks")], + [State("modal", "is_open")], +) +def toggle_modal(n, is_open): + if n: + return not is_open + return is_open + + +@app.callback(Output("auto-toast", "is_open"), [Input("auto-toast-toggle", "n_clicks")]) +def open_toast(n): + return True + + +@app.callback( + Output("gallery_checklist1", "value"), + Output("gallery_radio1", "value"), + Output("gallery_checklist2", "value"), + Output("gallery_radio2", "value"), + Input("gallery_checklist1", "value"), +) +def update_checklist(value): + # This is a dummy callback so checkboxes change color when theme is switched + return (value, 0, value, 0) + if __name__ == "__main__": app.run_server(debug=True) From 0547173421d2414d7580ab3735977e18d5d4ab07 Mon Sep 17 00:00:00 2001 From: Ann Marie Ward Date: Tue, 23 Mar 2021 11:20:04 -0700 Subject: [PATCH 4/9] lint --- docs/demos/theme_explorer.py | 193 +++++++++++++++++++++++++---------- 1 file changed, 140 insertions(+), 53 deletions(-) diff --git a/docs/demos/theme_explorer.py b/docs/demos/theme_explorer.py index 35c6f510d..327133666 100644 --- a/docs/demos/theme_explorer.py +++ b/docs/demos/theme_explorer.py @@ -9,7 +9,9 @@ DBC_HOME = "https://dash-bootstrap-components.opensource.faculty.ai/" DBC_GITHUB = "https://github.com/facultyai/dash-bootstrap-components" -DBC_DOCS = "https://dash-bootstrap-components.opensource.faculty.ai/docs/components/" +DBC_DOCS = ( + "https://dash-bootstrap-components.opensource.faculty.ai/docs/components/" +) def make_subheading(label, link): @@ -86,7 +88,10 @@ def make_subheading(label, link): badge_colors, html.Br(), dbc.Button( - ["Notifications", dbc.Badge("4", color="light", className="ml-1")], + [ + "Notifications", + dbc.Badge("4", color="light", className="ml-1"), + ], color="primary", className="mt-2", ), @@ -111,22 +116,39 @@ def make_subheading(label, link): ), html.Div( [ - dbc.Button("Primary", outline=True, color="primary", className="m-1"), dbc.Button( - "Secondary", outline=True, color="secondary", className="m-1", + "Primary", outline=True, color="primary", className="m-1" + ), + dbc.Button( + "Secondary", + outline=True, + color="secondary", + className="m-1", + ), + dbc.Button( + "Success", outline=True, color="success", className="m-1" + ), + dbc.Button( + "Warning", outline=True, color="warning", className="m-1" + ), + dbc.Button( + "Danger", outline=True, color="danger", className="m-1" + ), + dbc.Button( + "Info", outline=True, color="info", className="m-1" ), - dbc.Button("Success", outline=True, color="success", className="m-1"), - dbc.Button("Warning", outline=True, color="warning", className="m-1"), - dbc.Button("Danger", outline=True, color="danger", className="m-1"), - dbc.Button("Info", outline=True, color="info", className="m-1"), ], className="my-2", ), html.Div( [ dbc.Button("Regular", color="primary", className="m-1"), - dbc.Button("Active", color="primary", active=True, className="m-1"), - dbc.Button("Disabled", color="primary", disabled=True, className="m-1"), + dbc.Button( + "Active", color="primary", active=True, className="m-1" + ), + dbc.Button( + "Disabled", color="primary", disabled=True, className="m-1" + ), dbc.Button("Large button", size="lg", className="m-1"), dbc.Button("Regular button", className="m-1"), dbc.Button("Small button", size="sm", className="m-1"), @@ -189,9 +211,12 @@ def make_subheading(label, link): dbc.CardBody( [ html.H5( - "This card has a title", className="card-title", + "This card has a title", + className="card-title", + ), + html.P( + "And some text", className="card-text" ), - html.P("And some text", className="card-text"), ] ), ] @@ -201,7 +226,8 @@ def make_subheading(label, link): dbc.CardBody( [ html.H5( - "This card has a title", className="card-title", + "This card has a title", + className="card-title", ), html.P( "and some text, but no header", @@ -218,7 +244,8 @@ def make_subheading(label, link): dbc.CardBody( [ html.H5( - "This card has a title", className="card-title", + "This card has a title", + className="card-title", ), html.P( "and some text, and a footer!", @@ -249,7 +276,9 @@ def make_subheading(label, link): style={"marginBottom": "1rem"}, ), dbc.Collapse( - dbc.Card(dbc.CardBody("This content is hidden in the collapse")), + dbc.Card( + dbc.CardBody("This content is hidden in the collapse") + ), id="collapse", ), ] @@ -264,23 +293,28 @@ def make_subheading(label, link): dbc.CardBody( [ dbc.Row( - dbc.Col(html.H4("A single column", className="border bg-light")) + dbc.Col( + html.H4("A single column", className="border bg-light") + ) ), dbc.Row( [ dbc.Col( html.H4( - "One of three columns", className="border bg-light" + "One of three columns", + className="border bg-light", ), ), dbc.Col( html.H4( - "One of three columns", className="border bg-light" + "One of three columns", + className="border bg-light", ), ), dbc.Col( html.H4( - "One of three columns", className="border bg-light" + "One of three columns", + className="border bg-light", ), ), ] @@ -291,9 +325,18 @@ def make_subheading(label, link): html.H4("Row with no gutters"), dbc.Row( [ - dbc.Col(html.H4("Column 1 md=3", className="border bg-light"), md=3,), - dbc.Col(html.H4("Column 2 md=6", className="border bg-light"), md=6,), - dbc.Col(html.H4("column 3 md=3", className="border bg-light"), md=3,), + dbc.Col( + html.H4("Column 1 md=3", className="border bg-light"), + md=3, + ), + dbc.Col( + html.H4("Column 2 md=6", className="border bg-light"), + md=6, + ), + dbc.Col( + html.H4("column 3 md=3", className="border bg-light"), + md=3, + ), ], no_gutters=True, ), @@ -308,13 +351,16 @@ def make_subheading(label, link): html.Div( [ dbc.Button( - "Toggle fade", id="fade-button", style={"marginBottom": "1rem"} + "Toggle fade", + id="fade-button", + style={"marginBottom": "1rem"}, ), dbc.Fade( dbc.Card( dbc.CardBody( html.P( - "This content fades in and out", className="card-text" + "This content fades in and out", + className="card-text", ) ) ), @@ -338,7 +384,8 @@ def make_subheading(label, link): [ dbc.Label("Username"), dbc.Input( - placeholder="Enter your username", type="text" + placeholder="Enter your username", + type="text", ), dbc.FormText( [ @@ -347,7 +394,9 @@ def make_subheading(label, link): "Click here.", href="#", className="text-muted", - style={"textDecoration": "underline"}, + style={ + "textDecoration": "underline" + }, ), ] ), @@ -357,7 +406,8 @@ def make_subheading(label, link): [ dbc.Label("Username"), dbc.Input( - placeholder="Enter your password", type="password" + placeholder="Enter your password", + type="password", ), dbc.FormText( [ @@ -366,7 +416,9 @@ def make_subheading(label, link): "Click here.", href="#", className="text-muted", - style={"textDecoration": "underline"}, + style={ + "textDecoration": "underline" + }, ), ] ), @@ -385,7 +437,9 @@ def make_subheading(label, link): html.H2(make_subheading("Input", "input")), dbc.CardBody( [ - dbc.FormGroup([dbc.Label("Text input"), dbc.Input(type="text")]), + dbc.FormGroup( + [dbc.Label("Text input"), dbc.Input(type="text")] + ), dbc.FormGroup( [ dbc.Label("Valid text input"), @@ -427,7 +481,10 @@ def make_subheading(label, link): dbc.Checklist( id="gallery_checklist1", options=[ - {"label": "Option {}".format(i), "value": i} + { + "label": "Option {}".format(i), + "value": i, + } for i in range(3) ], value=[1, 2], @@ -437,7 +494,10 @@ def make_subheading(label, link): dbc.Checklist( id="gallery_checklist2", options=[ - {"label": "Option {}".format(i), "value": i} + { + "label": "Option {}".format(i), + "value": i, + } for i in range(3) ], value=[1, 2], @@ -450,7 +510,8 @@ def make_subheading(label, link): dbc.Checklist( id="gallery_checklist3", options=[ - {"label": "Option {}".format(i), "value": i} for i in range(5) + {"label": "Option {}".format(i), "value": i} + for i in range(5) ], value=[0, 4], inline=True, @@ -469,7 +530,8 @@ def make_subheading(label, link): dbc.RadioItems( id="gallery_radio1", options=[ - {"label": "Option {}".format(i), "value": i} for i in range(3) + {"label": "Option {}".format(i), "value": i} + for i in range(3) ], value=0, ), @@ -477,7 +539,8 @@ def make_subheading(label, link): dbc.RadioItems( id="gallery_radio2", options=[ - {"label": "Option {}".format(i), "value": i} for i in range(5) + {"label": "Option {}".format(i), "value": i} + for i in range(5) ], value=0, inline=True, @@ -546,7 +609,9 @@ def make_subheading(label, link): [ dbc.ListGroup( [ - dbc.ListGroupItem("Item 1", color="primary", action=True), + dbc.ListGroupItem( + "Item 1", color="primary", action=True + ), dbc.ListGroupItem("Item 2"), dbc.ListGroupItem("Item 3"), dbc.ListGroupItem( @@ -564,9 +629,7 @@ def make_subheading(label, link): ) -COOKIE = ( - "https://todaysmama.com/.image/t_share/MTU5OTEwMzkyMDIyMTE1NzAz/cookie-monster.png" -) +COOKIE = "https://todaysmama.com/.image/t_share/MTU5OTEwMzkyMDIyMTE1NzAz/cookie-monster.png" modal = html.Div( [ make_subheading("Modal", "modal"), @@ -576,7 +639,9 @@ def make_subheading(label, link): dbc.Modal( [ dbc.ModalHeader("Cookies!"), - dbc.ModalBody(html.Img(src=COOKIE, style={"width": "100%"})), + dbc.ModalBody( + html.Img(src=COOKIE, style={"width": "100%"}) + ), ], id="modal", is_open=False, @@ -604,12 +669,16 @@ def make_subheading(label, link): in_navbar=True, label="Menu", children=[ - dbc.DropdownMenuItem("Entry 1", href="https://google.com"), + dbc.DropdownMenuItem( + "Entry 1", href="https://google.com" + ), dbc.DropdownMenuItem("Entry 2", href="/test"), dbc.DropdownMenuItem(divider=True), dbc.DropdownMenuItem("A heading", header=True), dbc.DropdownMenuItem( - "Entry 3", href="/external-relative", external_link=True + "Entry 3", + href="/external-relative", + external_link=True, ), dbc.DropdownMenuItem("Entry 4 - does nothing"), ], @@ -628,9 +697,14 @@ def make_subheading(label, link): popover = html.Div( [ make_subheading("Popover", "popover"), - dbc.Button("Click to toggle popover", id="popover-target", color="danger"), + dbc.Button( + "Click to toggle popover", id="popover-target", color="danger" + ), dbc.Popover( - [dbc.PopoverHeader("Popover header"), dbc.PopoverBody("Popover body"),], + [ + dbc.PopoverHeader("Popover header"), + dbc.PopoverBody("Popover body"), + ], id="popover", is_open=False, target="popover-target", @@ -680,7 +754,11 @@ def make_subheading(label, link): [ html.Thead( html.Tr( - [html.Th("#"), html.Th("First name"), html.Th("Last name"),] + [ + html.Th("#"), + html.Th("First name"), + html.Th("Last name"), + ] ) ), html.Tbody( @@ -734,7 +812,8 @@ def make_subheading(label, link): dbc.CardBody( [ html.P( - "This tab has a card!", className="card-text", + "This tab has a card!", + className="card-text", ), dbc.Button("Click here", color="success"), ] @@ -754,7 +833,10 @@ def make_subheading(label, link): [ make_subheading("Toast", "toast"), dbc.Button( - "Open toast", id="auto-toast-toggle", color="primary", className="mb-3", + "Open toast", + id="auto-toast-toggle", + color="primary", + className="mb-3", ), dbc.Toast( [html.P("This is the content of the toast", className="mb-0")], @@ -773,12 +855,15 @@ def make_subheading(label, link): html.P( [ "I wonder what ", - html.Span("floccinaucinihilipilification", id="tooltip-target"), + html.Span( + "floccinaucinihilipilification", id="tooltip-target" + ), " means?", ] ), dbc.Tooltip( - "Noun: rare, " "the action or habit of estimating something as worthless.", + "Noun: rare, " + "the action or habit of estimating something as worthless.", target="tooltip-target", ), ] @@ -799,7 +884,7 @@ def make_subheading(label, link): badges, buttons, cards, - dbc.Row([dbc.Col([form, input_group,]), dbc.Col([input_])]), + dbc.Row([dbc.Col([form, input_group]), dbc.Col([input_])]), dbc.Row([dbc.Col([checklist_items]), dbc.Col([radio_items])]), navbar, tabs, @@ -815,7 +900,7 @@ def make_subheading(label, link): dbc.CardBody( dbc.Row( [ - dbc.Col([modal, fade, collapse,]), + dbc.Col([modal, fade, collapse]), dbc.Col([popover, toast, tooltip]), ] ), @@ -876,8 +961,10 @@ def toggle_modal(n, is_open): return is_open -@app.callback(Output("auto-toast", "is_open"), [Input("auto-toast-toggle", "n_clicks")]) -def open_toast(n): +@app.callback( + Output("auto-toast", "is_open"), [Input("auto-toast-toggle", "n_clicks")] +) +def open_toast(_): return True @@ -890,7 +977,7 @@ def open_toast(n): ) def update_checklist(value): # This is a dummy callback so checkboxes change color when theme is switched - return (value, 0, value, 0) + return value, 0, value, 0 if __name__ == "__main__": From a92fc418273418285509c26f16d1fcd8dc3dcb44 Mon Sep 17 00:00:00 2001 From: tcbegley Date: Mon, 12 Apr 2021 16:52:47 +0100 Subject: [PATCH 5/9] Fix theme explorer and make more responsive --- docs/demos/__init__.py | 91 +- docs/demos/theme_explorer.py | 984 ------------------ docs/demos/theme_explorer/__init__.py | 895 ++++++++++++++++ docs/server.py | 7 + docs/static/js/theme-switcher.js | 63 +- docs/static/loading.css | 6 +- docs/static/theme-explorer.css | 66 -- .../macros/theme-explorer-navbar.html | 9 +- docs/templates/theme-explorer.html | 59 +- 9 files changed, 990 insertions(+), 1190 deletions(-) delete mode 100644 docs/demos/theme_explorer.py create mode 100644 docs/demos/theme_explorer/__init__.py delete mode 100644 docs/static/theme-explorer.css diff --git a/docs/demos/__init__.py b/docs/demos/__init__.py index 5095c219b..b0f94f38d 100644 --- a/docs/demos/__init__.py +++ b/docs/demos/__init__.py @@ -1,55 +1,54 @@ import os -from pathlib import Path - import dash -from jinja2 import Environment, FileSystemLoader +import dash_bootstrap_components as dbc from .theme_explorer import app as theme_explorer SERVE_LOCALLY = os.getenv("DBC_DOCS_MODE", "production") == "dev" - -HERE = Path(__file__).parent -TEMPLATES = HERE.parent / "templates" - -INDEX_STRING_TEMPLATE = """{% extends "theme-explorer.html" %} -{% block head %} -{{ super() }} -{{ "{%metas%}{%css%}" }} -{% endblock %} -{% block title %} -{{ "{%title%}" }} -{% endblock %} -{% block content %} -{{ "{%app_entry%}" }} -{% endblock %} -{% block code %}{% endblock %} -{% block scripts %} -
- {{ "{%config%}{%scripts%}{%renderer%}" }} - {{ super() }} -
-{% endblock %} -""" +FA = "https://use.fontawesome.com/releases/v5.15.3/css/all.css" + +SHEETS = [ + ("bootstrap", dbc.themes.BOOTSTRAP), + ("cerulean", dbc.themes.CERULEAN), + ("cosmo", dbc.themes.COSMO), + ("cyborg", dbc.themes.CYBORG), + ("darkly", dbc.themes.DARKLY), + ("flatly", dbc.themes.FLATLY), + ("journal", dbc.themes.JOURNAL), + ("litera", dbc.themes.LITERA), + ("lumen", dbc.themes.LUMEN), + ("lux", dbc.themes.LUX), + ("materia", dbc.themes.MATERIA), + ("minty", dbc.themes.MINTY), + ("pulse", dbc.themes.PULSE), + ("sandstone", dbc.themes.SANDSTONE), + ("simplex", dbc.themes.SIMPLEX), + ("sketchy", dbc.themes.SKETCHY), + ("slate", dbc.themes.SLATE), + ("solar", dbc.themes.SOLAR), + ("spacelab", dbc.themes.SPACELAB), + ("superhero", dbc.themes.SUPERHERO), + ("united", dbc.themes.UNITED), + ("yeti", dbc.themes.YETI), +] def register_apps(): - env = Environment(loader=FileSystemLoader(TEMPLATES.as_posix())) - template = env.from_string(INDEX_STRING_TEMPLATE) - template = template.render() - - code = (HERE / "theme_explorer.py").read_text() - - new_theme_explorer = dash.Dash( - external_stylesheets=["/static/loading.css"], - requests_pathname_prefix="/docs/themes/explorer/", - suppress_callback_exceptions=True, - serve_locally=SERVE_LOCALLY, - index_string=template.replace("", code), - update_title=None, - ) - - new_theme_explorer.title = "Theme explorer - dbc docs" - new_theme_explorer.layout = theme_explorer.layout - new_theme_explorer.callback_map = theme_explorer.callback_map - new_theme_explorer._callback_list = new_theme_explorer._callback_list - return {"/docs/themes/explorer": new_theme_explorer} + apps = {} + + for name, sheet in SHEETS: + new_theme_explorer = dash.Dash( + external_stylesheets=[FA, sheet, "/static/loading.css"], + requests_pathname_prefix=f"/docs/themes/explorer/{name}/", + suppress_callback_exceptions=True, + serve_locally=SERVE_LOCALLY, + update_title=None, + ) + + new_theme_explorer.title = f"Theme explorer - {name} - dbc docs" + new_theme_explorer.layout = theme_explorer.layout + new_theme_explorer.callback_map = theme_explorer.callback_map + new_theme_explorer._callback_list = theme_explorer._callback_list + apps[f"/docs/themes/explorer/{name}"] = new_theme_explorer + + return apps diff --git a/docs/demos/theme_explorer.py b/docs/demos/theme_explorer.py deleted file mode 100644 index 327133666..000000000 --- a/docs/demos/theme_explorer.py +++ /dev/null @@ -1,984 +0,0 @@ -import dash -import dash_bootstrap_components as dbc -import dash_core_components as dcc -import dash_html_components as html -from dash.dependencies import Input, Output, State - -FONT_AWESOME = "https://use.fontawesome.com/releases/v5.10.2/css/all.css" -app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP, FONT_AWESOME]) - -DBC_HOME = "https://dash-bootstrap-components.opensource.faculty.ai/" -DBC_GITHUB = "https://github.com/facultyai/dash-bootstrap-components" -DBC_DOCS = ( - "https://dash-bootstrap-components.opensource.faculty.ai/docs/components/" -) - - -def make_subheading(label, link): - return html.Div( - [ - dbc.Button( - [ - html.H2( - [ - label, - html.I( - className="far fa-question-circle ml-2 mb-2 align-middle", - style={"fontSize": 18}, - id="tooltip_target" + label.replace(" ", ""), - ), - ], - ) - ], - href=DBC_DOCS + link, - target="_blank", - color="link", - ), - dbc.Tooltip( - "See " + label + " documentation ", - target="tooltip_target" + label.replace(" ", ""), - ), - ], - ) - - -alerts1 = html.Div( - [ - dbc.Alert("This is a primary alert", color="primary"), - dbc.Alert("This is a secondary alert", color="secondary"), - dbc.Alert("This is a success alert! Well done!", color="success"), - dbc.Alert("This is a warning alert... be careful...", color="warning"), - ] -) -alerts2 = html.Div( - [ - dbc.Alert("This is a danger alert. Scary!", color="danger"), - dbc.Alert("This is an info alert. Good to know!", color="info"), - dbc.Alert("This is a light alert", color="light"), - dbc.Alert("This is a dark alert", color="dark"), - ] -) - -alerts = dbc.Card( - [ - html.H2(make_subheading("Alert", "alert")), - dbc.CardBody(dbc.Row([dbc.Col(alerts1), dbc.Col(alerts2)])), - ], - className="mb-4", -) - -badge_colors = html.Span( - [ - dbc.Badge("Primary", color="primary", className="mr-1"), - dbc.Badge("Secondary", color="secondary", className="mr-1"), - dbc.Badge("Success", color="success", className="mr-1"), - dbc.Badge("Warning", color="warning", className="mr-1"), - dbc.Badge("Danger", color="danger", className="mr-1"), - dbc.Badge("Info", color="info", className="mr-1"), - dbc.Badge("Light", color="light", className="mr-1"), - dbc.Badge("Dark", color="dark"), - ], -) - -badges = dbc.Card( - [ - html.H2(make_subheading("Badge", "badge")), - dbc.CardBody( - [ - badge_colors, - html.Br(), - dbc.Button( - [ - "Notifications", - dbc.Badge("4", color="light", className="ml-1"), - ], - color="primary", - className="mt-2", - ), - ] - ), - ], - className="mb-4", -) - -buttons1 = dbc.Card( - [ - html.H2(make_subheading("Button", "button")), - dbc.CardBody( - [ - dbc.Button("Primary", color="primary", className="m-1"), - dbc.Button("Secondary", color="secondary", className="m-1"), - dbc.Button("Success", color="success", className="m-1"), - dbc.Button("Warning", color="warning", className="m-1"), - dbc.Button("Danger", color="danger", className="m-1"), - dbc.Button("Info", color="info", className="m-1"), - ] - ), - html.Div( - [ - dbc.Button( - "Primary", outline=True, color="primary", className="m-1" - ), - dbc.Button( - "Secondary", - outline=True, - color="secondary", - className="m-1", - ), - dbc.Button( - "Success", outline=True, color="success", className="m-1" - ), - dbc.Button( - "Warning", outline=True, color="warning", className="m-1" - ), - dbc.Button( - "Danger", outline=True, color="danger", className="m-1" - ), - dbc.Button( - "Info", outline=True, color="info", className="m-1" - ), - ], - className="my-2", - ), - html.Div( - [ - dbc.Button("Regular", color="primary", className="m-1"), - dbc.Button( - "Active", color="primary", active=True, className="m-1" - ), - dbc.Button( - "Disabled", color="primary", disabled=True, className="m-1" - ), - dbc.Button("Large button", size="lg", className="m-1"), - dbc.Button("Regular button", className="m-1"), - dbc.Button("Small button", size="sm", className="m-1"), - ], - ), - ], - className="mb-4", -) - - -buttons2 = dbc.Card( - [ - html.H2(make_subheading("ButtonGroup", "buttongroups")), - dbc.CardBody( - [ - dbc.ButtonGroup( - [ - dbc.Button("Primary", color="primary"), - dbc.Button("Secondary", color="secondary"), - dbc.Button("Success", color="success"), - dbc.Button("Warning", color="warning"), - dbc.Button("Danger", color="danger"), - dbc.Button("Info", color="info"), - ], - className="mb-4", - ), - html.Br(), - dbc.ButtonGroup( - [ - dbc.Button("First"), - dbc.Button("Second"), - dbc.DropdownMenu( - [ - dbc.DropdownMenuItem("Item 1"), - dbc.DropdownMenuItem("Item 2"), - ], - label="Dropdown", - group=True, - ), - ], - vertical=True, - ), - ], - ), - ], - className="mb-4", -) -buttons = dbc.Row([dbc.Col(buttons1), dbc.Col(buttons2)]) - - -cards = dbc.Card( - [ - html.H2(make_subheading("Card", "card")), - dbc.CardBody( - dbc.CardDeck( - [ - dbc.Card( - [ - html.H2("Header"), - dbc.CardBody( - [ - html.H5( - "This card has a title", - className="card-title", - ), - html.P( - "And some text", className="card-text" - ), - ] - ), - ] - ), - dbc.Card( - [ - dbc.CardBody( - [ - html.H5( - "This card has a title", - className="card-title", - ), - html.P( - "and some text, but no header", - className="card-text", - ), - ] - ) - ], - outline=True, - color="primary", - ), - dbc.Card( - [ - dbc.CardBody( - [ - html.H5( - "This card has a title", - className="card-title", - ), - html.P( - "and some text, and a footer!", - className="card-text", - ), - ] - ), - dbc.CardFooter("Footer"), - ], - outline=True, - color="dark", - ), - ] - ) - ), - ], - className="mb-4", -) - -collapse = html.Div( - [ - make_subheading("Collapse", "collapse"), - html.Div( - [ - dbc.Button( - "Open collapse", - id="collapse-button", - style={"marginBottom": "1rem"}, - ), - dbc.Collapse( - dbc.Card( - dbc.CardBody("This content is hidden in the collapse") - ), - id="collapse", - ), - ] - ), - ], - className="mb-4", -) - -columns = dbc.Card( - [ - html.H2(make_subheading("Row Col", "layout")), - dbc.CardBody( - [ - dbc.Row( - dbc.Col( - html.H4("A single column", className="border bg-light") - ) - ), - dbc.Row( - [ - dbc.Col( - html.H4( - "One of three columns", - className="border bg-light", - ), - ), - dbc.Col( - html.H4( - "One of three columns", - className="border bg-light", - ), - ), - dbc.Col( - html.H4( - "One of three columns", - className="border bg-light", - ), - ), - ] - ), - ] - ), - html.Hr(), - html.H4("Row with no gutters"), - dbc.Row( - [ - dbc.Col( - html.H4("Column 1 md=3", className="border bg-light"), - md=3, - ), - dbc.Col( - html.H4("Column 2 md=6", className="border bg-light"), - md=6, - ), - dbc.Col( - html.H4("column 3 md=3", className="border bg-light"), - md=3, - ), - ], - no_gutters=True, - ), - ], - className="mb-4", -) - - -fade = html.Div( - [ - make_subheading("Fade", "fade"), - html.Div( - [ - dbc.Button( - "Toggle fade", - id="fade-button", - style={"marginBottom": "1rem"}, - ), - dbc.Fade( - dbc.Card( - dbc.CardBody( - html.P( - "This content fades in and out", - className="card-text", - ) - ) - ), - id="fade", - is_in=True, - ), - ] - ), - ], -) - - -form = dbc.Card( - [ - html.H2(make_subheading("Form", "form")), - dbc.CardBody( - [ - dbc.Form( - [ - dbc.FormGroup( - [ - dbc.Label("Username"), - dbc.Input( - placeholder="Enter your username", - type="text", - ), - dbc.FormText( - [ - "Can't remember your username? ", - html.A( - "Click here.", - href="#", - className="text-muted", - style={ - "textDecoration": "underline" - }, - ), - ] - ), - ] - ), - dbc.FormGroup( - [ - dbc.Label("Username"), - dbc.Input( - placeholder="Enter your password", - type="password", - ), - dbc.FormText( - [ - "Can't remember your password? ", - html.A( - "Click here.", - href="#", - className="text-muted", - style={ - "textDecoration": "underline" - }, - ), - ] - ), - ] - ), - ] - ), - ] - ), - ], - className="mb-4", -) - -input_ = dbc.Card( - [ - html.H2(make_subheading("Input", "input")), - dbc.CardBody( - [ - dbc.FormGroup( - [dbc.Label("Text input"), dbc.Input(type="text")] - ), - dbc.FormGroup( - [ - dbc.Label("Valid text input"), - dbc.Input(type="text", valid=True), - dbc.FormFeedback("That's a valid input!", valid=True), - ] - ), - dbc.FormGroup( - [ - dbc.Label("Invalid text input"), - dbc.Input(type="text", invalid=True), - dbc.FormFeedback("That's an invalid input..."), - ] - ), - dbc.FormGroup( - [ - dbc.Label("Color Picker"), - dbc.Input( - type="color", - value="#afc1e4", - style={"width": 100, "height": 75}, - ), - ] - ), - ] - ), - ] -) - - -checklist_items = dbc.Card( - [ - html.H2(make_subheading("Checklist", "input"),), - dbc.CardBody( - [ - dbc.Row( - [ - dbc.Col( - dbc.Checklist( - id="gallery_checklist1", - options=[ - { - "label": "Option {}".format(i), - "value": i, - } - for i in range(3) - ], - value=[1, 2], - ) - ), - dbc.Col( - dbc.Checklist( - id="gallery_checklist2", - options=[ - { - "label": "Option {}".format(i), - "value": i, - } - for i in range(3) - ], - value=[1, 2], - switch=True, - ) - ), - ] - ), - html.H5("Inline checklist", className="mt-3"), - dbc.Checklist( - id="gallery_checklist3", - options=[ - {"label": "Option {}".format(i), "value": i} - for i in range(5) - ], - value=[0, 4], - inline=True, - ), - ] - ), - ], - className="mb-4", -) - -radio_items = dbc.Card( - [ - html.H2(make_subheading("RadioItems", "input"),), - dbc.CardBody( - [ - dbc.RadioItems( - id="gallery_radio1", - options=[ - {"label": "Option {}".format(i), "value": i} - for i in range(3) - ], - value=0, - ), - html.H5("Inline radioitems", className="mt-3"), - dbc.RadioItems( - id="gallery_radio2", - options=[ - {"label": "Option {}".format(i), "value": i} - for i in range(5) - ], - value=0, - inline=True, - ), - ] - ), - ] -) - -input_group = dbc.Card( - [ - html.H2(make_subheading("InputGroup and addons", "input_group")), - dbc.CardBody( - [ - dbc.InputGroup( - [ - dbc.InputGroupAddon( - dbc.Button("To the left!", color="danger"), - addon_type="prepend", - ), - dbc.Input(type="text"), - ] - ), - html.Br(), - dbc.InputGroup( - [ - dbc.Input(type="text"), - dbc.InputGroupAddon( - dbc.Button("To the right!", color="success"), - addon_type="append", - ), - ] - ), - html.Br(), - dbc.InputGroup( - [ - dbc.InputGroupAddon("@", addon_type="prepend"), - dbc.Input(type="text", placeholder="Enter username"), - ] - ), - ] - ), - ], - className="mb-4", -) - - -jumbotron = dbc.Card( - [ - html.H2(make_subheading("Jumbotron", "jumbotron")), - dbc.Jumbotron( - [ - html.H2("This is a jumbotron"), - html.P("It makes things big..."), - dbc.Button("Click here", color="danger"), - ] - ), - ], - className="mb-4", -) - -list_group = dbc.Card( - [ - html.H2(make_subheading("ListGroup", "list_group")), - dbc.CardBody( - [ - dbc.ListGroup( - [ - dbc.ListGroupItem( - "Item 1", color="primary", action=True - ), - dbc.ListGroupItem("Item 2"), - dbc.ListGroupItem("Item 3"), - dbc.ListGroupItem( - [ - dbc.ListGroupItemHeading("Item 4 heading"), - dbc.ListGroupItemText("Item 4 text"), - ] - ), - ] - ), - ] - ), - ], - className="mb-4", -) - - -COOKIE = "https://todaysmama.com/.image/t_share/MTU5OTEwMzkyMDIyMTE1NzAz/cookie-monster.png" -modal = html.Div( - [ - make_subheading("Modal", "modal"), - html.P( - [ - dbc.Button("Show the cookie monster", id="button"), - dbc.Modal( - [ - dbc.ModalHeader("Cookies!"), - dbc.ModalBody( - html.Img(src=COOKIE, style={"width": "100%"}) - ), - ], - id="modal", - is_open=False, - ), - ] - ), - ] -) - -navbar = dbc.Card( - [ - dbc.Row( - [ - make_subheading("Navbar", "navbar"), - make_subheading("DropdownMenu", "dropdown_menu"), - ], - className="px-2", - ), - dbc.CardBody( - dbc.NavbarSimple( - children=[ - dbc.NavItem(dbc.NavLink("GitHub", href=DBC_GITHUB)), - dbc.DropdownMenu( - nav=True, - in_navbar=True, - label="Menu", - children=[ - dbc.DropdownMenuItem( - "Entry 1", href="https://google.com" - ), - dbc.DropdownMenuItem("Entry 2", href="/test"), - dbc.DropdownMenuItem(divider=True), - dbc.DropdownMenuItem("A heading", header=True), - dbc.DropdownMenuItem( - "Entry 3", - href="/external-relative", - external_link=True, - ), - dbc.DropdownMenuItem("Entry 4 - does nothing"), - ], - ), - ], - brand="Dash Bootstrap Components", - brand_href=DBC_HOME, - sticky="top", - color="primary", - dark=True, - ) - ), - ] -) - -popover = html.Div( - [ - make_subheading("Popover", "popover"), - dbc.Button( - "Click to toggle popover", id="popover-target", color="danger" - ), - dbc.Popover( - [ - dbc.PopoverHeader("Popover header"), - dbc.PopoverBody("Popover body"), - ], - id="popover", - is_open=False, - target="popover-target", - ), - ] -) - -progress = dbc.Card( - [ - html.H2(make_subheading("Progress", "progress")), - dbc.CardBody( - [ - dbc.Progress("25%", value=25), - dbc.Progress(value=50, striped=True, className="my-2"), - dbc.Progress(value=75, color="success"), - ] - ), - ], - className="mb-4", -) - -spinner = dbc.Card( - [ - html.H2(make_subheading("Spinner", "spinner")), - dbc.CardBody( - [ - dbc.Spinner(color="secondary"), - dbc.Spinner(color="danger", type="grow"), - dbc.Spinner(color="light", type="grow"), - dbc.Button( - [dbc.Spinner(size="sm"), " Loading..."], - color="primary", - disabled=True, - ), - ] - ), - ], - className="mb-4", -) - - -table = dbc.Card( - [ - html.H2(make_subheading("Table", "table"),), - dbc.CardBody( - dbc.Table( - [ - html.Thead( - html.Tr( - [ - html.Th("#"), - html.Th("First name"), - html.Th("Last name"), - ] - ) - ), - html.Tbody( - [ - html.Tr( - [ - html.Th("1", scope="row"), - html.Td("Tom"), - html.Td("Cruise"), - ] - ), - html.Tr( - [ - html.Th("2", scope="row"), - html.Td("Jodie"), - html.Td("Foster"), - ] - ), - html.Tr( - [ - html.Th("3", scope="row"), - html.Td("Chadwick"), - html.Td("Boseman"), - ] - ), - ] - ), - ], - responsive=True, - striped=True, - hover=True, - ), - ), - ], - className="mb-4", -) - -tabs = dbc.Card( - [ - make_subheading("Tabs", "tabs"), - dbc.CardBody( - dbc.Tabs( - [ - dbc.Tab( - html.H4("This is tab 1"), - label="Tab 1", - style={"padding": "10px"}, - ), - dbc.Tab( - dbc.Card( - dbc.CardBody( - [ - html.P( - "This tab has a card!", - className="card-text", - ), - dbc.Button("Click here", color="success"), - ] - ) - ), - label="Tab 2", - style={"padding": "10px"}, - ), - ] - ), - ), - ], - className="my-4", -) - -toast = html.Div( - [ - make_subheading("Toast", "toast"), - dbc.Button( - "Open toast", - id="auto-toast-toggle", - color="primary", - className="mb-3", - ), - dbc.Toast( - [html.P("This is the content of the toast", className="mb-0")], - id="auto-toast", - header="This is the header", - icon="primary", - duration=4000, - ), - ], - className="my-2", -) - -tooltip = html.Div( - [ - make_subheading("Tooltip", "tooltip"), - html.P( - [ - "I wonder what ", - html.Span( - "floccinaucinihilipilification", id="tooltip-target" - ), - " means?", - ] - ), - dbc.Tooltip( - "Noun: rare, " - "the action or habit of estimating something as worthless.", - target="tooltip-target", - ), - ] -) - -source_code = dcc.Markdown( - """ - ## See the [source code](https://github.com/AnnMarieW/HelloDash/blob/main/apps/dbc_components.py) - """ -) - - -app.layout = dbc.Container( - [ - html.Div( - [ - alerts, - badges, - buttons, - cards, - dbc.Row([dbc.Col([form, input_group]), dbc.Col([input_])]), - dbc.Row([dbc.Col([checklist_items]), dbc.Col([radio_items])]), - navbar, - tabs, - jumbotron, - columns, - list_group, - table, - progress, - spinner, - dbc.Card( - [ - html.H2("Dialogs", className="pl-2 text-primary"), - dbc.CardBody( - dbc.Row( - [ - dbc.Col([modal, fade, collapse]), - dbc.Col([popover, toast, tooltip]), - ] - ), - ), - ] - ), - html.Div(style={"height": "50px"}), - source_code, - ], - className="my-2 p-4", - ), - ], - fluid=True, -) - - -@app.callback( - Output("collapse", "is_open"), - [Input("collapse-button", "n_clicks")], - [State("collapse", "is_open")], -) -def toggle_collapse(n, is_open): - if n: - return not is_open - return is_open - - -@app.callback( - Output("fade", "is_in"), - [Input("fade-button", "n_clicks")], - [State("fade", "is_in")], -) -def toggle_fade(n, is_in): - if n: - return not is_in - return is_in - - -@app.callback( - Output("popover", "is_open"), - [Input("popover-target", "n_clicks")], - [State("popover", "is_open")], -) -def toggle_popover(n, is_open): - if n: - return not is_open - return is_open - - -@app.callback( - Output("modal", "is_open"), - [Input("button", "n_clicks")], - [State("modal", "is_open")], -) -def toggle_modal(n, is_open): - if n: - return not is_open - return is_open - - -@app.callback( - Output("auto-toast", "is_open"), [Input("auto-toast-toggle", "n_clicks")] -) -def open_toast(_): - return True - - -@app.callback( - Output("gallery_checklist1", "value"), - Output("gallery_radio1", "value"), - Output("gallery_checklist2", "value"), - Output("gallery_radio2", "value"), - Input("gallery_checklist1", "value"), -) -def update_checklist(value): - # This is a dummy callback so checkboxes change color when theme is switched - return value, 0, value, 0 - - -if __name__ == "__main__": - app.run_server(debug=True) diff --git a/docs/demos/theme_explorer/__init__.py b/docs/demos/theme_explorer/__init__.py new file mode 100644 index 000000000..0038480fb --- /dev/null +++ b/docs/demos/theme_explorer/__init__.py @@ -0,0 +1,895 @@ +import dash +import dash_bootstrap_components as dbc +import dash_html_components as html +from dash.dependencies import Input, Output, State + +FONT_AWESOME = "https://use.fontawesome.com/releases/v5.10.2/css/all.css" +app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP, FONT_AWESOME]) + +DBC_HOME = "https://dash-bootstrap-components.opensource.faculty.ai/" +DBC_GITHUB = "https://github.com/facultyai/dash-bootstrap-components" +DBC_DOCS = ( + "https://dash-bootstrap-components.opensource.faculty.ai/docs/components/" +) + + +def make_subheading(label, link): + slug = label.replace(" ", "") + + heading = html.H2( + html.Span( + [ + label, + html.A( + html.I(className="fas fa-book fa-xs ml-2"), + href=f"{DBC_DOCS}{link}", + target="_blank", + id=f"tooltip_target_{slug}", + ), + ], + ), + ) + + return html.Div( + [ + heading, + dbc.Tooltip( + f"See {label} documentation", target=f"tooltip_target_{slug}" + ), + ], + className="mt-3", + ) + + +alerts1 = dbc.Col( + [ + dbc.Alert("This is a primary alert", color="primary"), + dbc.Alert("This is a secondary alert", color="secondary"), + dbc.Alert("This is a success alert! Well done!", color="success"), + dbc.Alert("This is a warning alert... be careful...", color="warning"), + ], + md=6, + xs=12, +) + +alerts2 = dbc.Col( + [ + dbc.Alert("This is a danger alert. Scary!", color="danger"), + dbc.Alert("This is an info alert. Good to know!", color="info"), + dbc.Alert("This is a light alert", color="light"), + dbc.Alert("This is a dark alert", color="dark"), + ], + md=6, + xs=12, +) + +alerts = html.Div( + [make_subheading("Alert", "alert"), dbc.Row([alerts1, alerts2])], + className="mb-4", +) + +badge = html.Div( + [ + dbc.Badge("Primary", color="primary", className="mr-1"), + dbc.Badge("Secondary", color="secondary", className="mr-1"), + dbc.Badge("Success", color="success", className="mr-1"), + dbc.Badge("Warning", color="warning", className="mr-1"), + dbc.Badge("Danger", color="danger", className="mr-1"), + dbc.Badge("Info", color="info", className="mr-1"), + dbc.Badge("Light", color="light", className="mr-1"), + dbc.Badge("Dark", color="dark"), + ], +) + +badge_pills = html.Div( + [ + dbc.Badge("Primary", color="primary", className="mr-1", pill=True), + dbc.Badge("Secondary", color="secondary", className="mr-1", pill=True), + dbc.Badge("Success", color="success", className="mr-1", pill=True), + dbc.Badge("Warning", color="warning", className="mr-1", pill=True), + dbc.Badge("Danger", color="danger", className="mr-1", pill=True), + dbc.Badge("Info", color="info", className="mr-1", pill=True), + dbc.Badge("Light", color="light", className="mr-1", pill=True), + dbc.Badge("Dark", color="dark", pill=True), + ], +) + +badges = html.Div( + [make_subheading("Badge", "badge"), badge, badge_pills], + className="mb-4", +) + +buttons1 = dbc.Col( + [ + make_subheading("Button", "button"), + html.Div( + [ + dbc.Button("Primary", color="primary", className="mr-1 mt-1"), + dbc.Button( + "Secondary", color="secondary", className="mr-1 mt-1" + ), + dbc.Button("Success", color="success", className="mr-1 mt-1"), + dbc.Button("Warning", color="warning", className="mr-1 mt-1"), + dbc.Button("Danger", color="danger", className="mr-1 mt-1"), + dbc.Button("Info", color="info", className="mr-1 mt-1"), + ], + className="mb-2", + ), + html.Div( + [ + dbc.Button( + "Primary", + outline=True, + color="primary", + className="mr-1 mt-1", + ), + dbc.Button( + "Secondary", + outline=True, + color="secondary", + className="mr-1 mt-1", + ), + dbc.Button( + "Success", + outline=True, + color="success", + className="mr-1 mt-1", + ), + dbc.Button( + "Warning", + outline=True, + color="warning", + className="mr-1 mt-1", + ), + dbc.Button( + "Danger", + outline=True, + color="danger", + className="mr-1 mt-1", + ), + dbc.Button( + "Info", outline=True, color="info", className="mr-1 mt-1" + ), + ], + className="mb-2", + ), + html.Div( + [ + dbc.Button("Regular", color="primary", className="mr-1 mt-1"), + dbc.Button( + "Active", + color="primary", + active=True, + className="mr-1 mt-1", + ), + dbc.Button( + "Disabled", + color="primary", + disabled=True, + className="mr-1 mt-1", + ), + ], + className="mb-2", + ), + html.Div( + [ + dbc.Button("Large button", size="lg", className="mr-1 mt-1"), + dbc.Button("Regular button", className="mr-1 mt-1"), + dbc.Button("Small button", size="sm", className="mr-1 mt-1"), + ], + className="mb-2", + ), + ], + lg=6, + xs=12, +) + +buttons2 = dbc.Col( + [ + make_subheading("ButtonGroup", "buttongroups"), + html.Div( + dbc.ButtonGroup( + [ + dbc.Button("Success", color="success"), + dbc.Button("Warning", color="warning"), + dbc.Button("Danger", color="danger"), + ] + ), + className="mb-2", + ), + html.Div( + dbc.ButtonGroup( + [ + dbc.Button("First"), + dbc.Button("Second"), + dbc.DropdownMenu( + [ + dbc.DropdownMenuItem("Item 1"), + dbc.DropdownMenuItem("Item 2"), + ], + label="Dropdown", + group=True, + ), + ], + vertical=True, + ), + className="mb-2", + ), + ], + lg=6, + xs=12, +) + +buttons = dbc.Row([buttons1, buttons2], className="mb-4") + +cards = html.Div( + [ + make_subheading("Card", "card"), + dbc.CardDeck( + [ + dbc.Card( + [ + dbc.CardHeader("Header"), + dbc.CardBody( + [ + html.H5( + "This card has a title", + className="card-title", + ), + html.P("And some text", className="card-text"), + ] + ), + ] + ), + dbc.Card( + [ + dbc.CardBody( + [ + html.H5( + "This card has a title", + className="card-title", + ), + html.P( + "and some text, but no header", + className="card-text", + ), + ] + ) + ], + outline=True, + color="primary", + ), + dbc.Card( + [ + dbc.CardBody( + [ + html.H5( + "This card has a title", + className="card-title", + ), + html.P( + "and some text, and a footer!", + className="card-text", + ), + ] + ), + dbc.CardFooter("Footer"), + ], + outline=True, + color="dark", + ), + ] + ), + ], + className="mb-4", +) + +collapse = html.Div( + [ + make_subheading("Collapse", "collapse"), + html.Div( + [ + dbc.Button( + "Open collapse", id="collapse-button", className="mb-2" + ), + dbc.Collapse( + dbc.Card( + dbc.CardBody("This content is hidden in the collapse") + ), + id="collapse", + ), + ] + ), + ], + className="mb-4", +) + +fade = html.Div( + [ + make_subheading("Fade", "fade"), + html.Div( + [ + dbc.Button( + "Toggle fade", + id="fade-button", + style={"marginBottom": "1rem"}, + ), + dbc.Fade( + dbc.Card( + dbc.CardBody( + html.P( + "This content fades in and out", + className="card-text", + ) + ) + ), + id="fade", + is_in=True, + ), + ] + ), + ], +) + +form = html.Div( + [ + make_subheading("Form", "form"), + dbc.Form( + [ + dbc.FormGroup( + [ + dbc.Label("Username"), + dbc.Input( + placeholder="Enter your username", + type="text", + ), + dbc.FormText( + [ + "Can't remember your username? ", + html.A( + "Click here.", + href="#", + className="text-muted", + style={"textDecoration": "underline"}, + ), + ] + ), + ] + ), + dbc.FormGroup( + [ + dbc.Label("Username"), + dbc.Input( + placeholder="Enter your password", + type="password", + ), + dbc.FormText( + [ + "Can't remember your password? ", + html.A( + "Click here.", + href="#", + className="text-muted", + style={"textDecoration": "underline"}, + ), + ] + ), + ] + ), + ] + ), + ], + className="mb-4", +) + +input_ = html.Div( + [ + make_subheading("Input", "input"), + dbc.FormGroup( + [ + dbc.Label("Valid text input"), + dbc.Input(type="text", valid=True), + dbc.FormFeedback("That's a valid input!", valid=True), + ] + ), + dbc.FormGroup( + [ + dbc.Label("Invalid text input"), + dbc.Input(type="text", invalid=True), + dbc.FormFeedback("That's an invalid input..."), + ] + ), + ] +) + +checklist_items = html.Div( + [ + make_subheading("Checklist", "input"), + dbc.Row( + [ + dbc.Col( + dbc.Checklist( + id="gallery_checklist1", + options=[ + { + "label": "Option {}".format(i), + "value": i, + } + for i in range(3) + ], + value=[1, 2], + ) + ), + dbc.Col( + dbc.Checklist( + id="gallery_checklist2", + options=[ + { + "label": "Option {}".format(i), + "value": i, + } + for i in range(3) + ], + value=[1, 2], + switch=True, + ) + ), + ] + ), + html.H5("Inline checklist", className="mt-3"), + dbc.Checklist( + id="gallery_checklist3", + options=[ + {"label": f"Option {i + 1}", "value": i} for i in range(5) + ], + value=[0, 4], + inline=True, + ), + ], + className="mb-4", +) + +radio_items = html.Div( + [ + make_subheading("RadioItems", "input"), + dbc.RadioItems( + id="gallery_radio1", + options=[ + {"label": f"Option {i + 1}", "value": i} for i in range(3) + ], + value=0, + ), + html.H5("Inline radioitems", className="mt-3"), + dbc.RadioItems( + id="gallery_radio2", + options=[ + {"label": f"Option {i + 1}", "value": i} for i in range(5) + ], + value=0, + inline=True, + ), + ] +) + +input_group = html.Div( + [ + make_subheading("InputGroup and addons", "input_group"), + dbc.InputGroup( + [ + dbc.InputGroupAddon( + dbc.Button("To the left!", color="danger"), + addon_type="prepend", + ), + dbc.Input(type="text"), + ], + className="my-3", + ), + dbc.InputGroup( + [ + dbc.Input(type="text"), + dbc.InputGroupAddon( + dbc.Button("To the right!", color="success"), + addon_type="append", + ), + ], + className="mb-3", + ), + dbc.InputGroup( + [ + dbc.InputGroupAddon("@", addon_type="prepend"), + dbc.Input(type="text", placeholder="Enter username"), + ], + className="mb-3", + ), + ], + className="mb-4", +) + +jumbotron = html.Div( + [ + make_subheading("Jumbotron", "jumbotron"), + dbc.Jumbotron( + [ + html.H2("This is a jumbotron"), + html.P("It makes things big..."), + dbc.Button("Click here", color="danger"), + ] + ), + ], + className="mb-4", +) + +list_group = html.Div( + [ + make_subheading("ListGroup", "list_group"), + dbc.ListGroup( + [ + dbc.ListGroupItem("Item 1", color="primary", action=True), + dbc.ListGroupItem("Item 2"), + dbc.ListGroupItem("Item 3"), + dbc.ListGroupItem( + [ + dbc.ListGroupItemHeading("Item 4 heading"), + dbc.ListGroupItemText("Item 4 text"), + ] + ), + ] + ), + ], + className="mb-4", +) + +COOKIE = "https://todaysmama.com/.image/t_share/MTU5OTEwMzkyMDIyMTE1NzAz/cookie-monster.png" # noqa +modal = html.Div( + [ + make_subheading("Modal", "modal"), + html.P( + [ + dbc.Button("Show the cookie monster", id="button"), + dbc.Modal( + [ + dbc.ModalHeader("Cookies!"), + dbc.ModalBody( + html.Img(src=COOKIE, style={"width": "100%"}) + ), + ], + id="modal", + is_open=False, + ), + ] + ), + ], + className="mb-4", +) + +navbar_children = [ + dbc.NavItem(dbc.NavLink("GitHub", href=DBC_GITHUB, target="_blank")), + dbc.DropdownMenu( + nav=True, + in_navbar=True, + label="Menu", + children=[ + dbc.DropdownMenuItem("Entry 1", href="https://google.com"), + dbc.DropdownMenuItem("Entry 2", href="/test"), + dbc.DropdownMenuItem(divider=True), + dbc.DropdownMenuItem("A heading", header=True), + dbc.DropdownMenuItem( + "Entry 3", + href="/external-relative", + external_link=True, + ), + dbc.DropdownMenuItem("Entry 4 - does nothing"), + ], + ), +] + +navbar = html.Div( + [ + make_subheading("Navbar", "navbar"), + dbc.NavbarSimple( + children=navbar_children, + brand="Navbar", + brand_href=DBC_HOME, + color="primary", + dark=True, + className="mb-3", + ), + dbc.NavbarSimple( + children=navbar_children, + brand="Navbar", + brand_href=DBC_HOME, + color="light", + className="mb-3", + ), + dbc.NavbarSimple( + children=navbar_children, + brand="Navbar", + brand_href=DBC_HOME, + color="dark", + dark=True, + ), + ], + className="mb-4", +) + +popover = html.Div( + [ + make_subheading("Popover", "popover"), + dbc.Button( + "Click to toggle popover", id="popover-target", color="danger" + ), + dbc.Popover( + [ + dbc.PopoverHeader("Popover header"), + dbc.PopoverBody("Popover body"), + ], + id="popover", + is_open=False, + target="popover-target", + ), + ], + className="mb-4", +) + +progress = html.Div( + [ + make_subheading("Progress", "progress"), + dbc.Progress("25%", value=25), + dbc.Progress(value=50, striped=True, className="my-2"), + dbc.Progress(value=75, color="success"), + ], + className="mb-4", +) + +spinner = html.Div( + [ + make_subheading("Spinner", "spinner"), + html.Div( + [ + dbc.Spinner(color=col) + for col in [ + "primary", + "secondary", + "success", + "warning", + "danger", + ] + ], + className="mb-2", + ), + html.Div( + [ + dbc.Spinner(color=col, type="grow") + for col in [ + "primary", + "secondary", + "success", + "warning", + "danger", + ] + ], + className="mb-2", + ), + ], + className="mb-4", +) + +table = html.Div( + [ + make_subheading("Table", "table"), + dbc.Table( + [ + html.Thead( + html.Tr( + [ + html.Th("#"), + html.Th("First name"), + html.Th("Last name"), + ] + ) + ), + html.Tbody( + [ + html.Tr( + [ + html.Th("1", scope="row"), + html.Td("Tom"), + html.Td("Cruise"), + ] + ), + html.Tr( + [ + html.Th("2", scope="row"), + html.Td("Jodie"), + html.Td("Foster"), + ] + ), + html.Tr( + [ + html.Th("3", scope="row"), + html.Td("Chadwick"), + html.Td("Boseman"), + ] + ), + ] + ), + ], + responsive=True, + striped=True, + hover=True, + ), + ], + className="mb-4", +) + +tabs = html.Div( + [ + make_subheading("Tabs", "tabs"), + dbc.Tabs( + [ + dbc.Tab( + html.P("This is tab 1", className="py-3"), label="Tab 1" + ), + dbc.Tab( + dbc.Card( + [ + html.P( + "This tab has a card!", + className="card-text", + ), + dbc.Button("Click here", color="success"), + ], + body=True, + ), + label="Tab 2", + style={"padding": "10px"}, + ), + ] + ), + ], + className="mb-4", +) + +toast = html.Div( + [ + make_subheading("Toast", "toast"), + dbc.Button( + "Open toast", + id="auto-toast-toggle", + color="primary", + className="mb-3", + ), + dbc.Toast( + html.P("This is the content of the toast", className="mb-0"), + id="auto-toast", + header="This is the header", + icon="primary", + duration=4000, + ), + ], + className="mb-2", +) + +tooltip = html.Div( + [ + make_subheading("Tooltip", "tooltip"), + html.P( + [ + "I wonder what ", + html.Span( + "floccinaucinihilipilification", id="tooltip-target" + ), + " means?", + ] + ), + dbc.Tooltip( + "Noun: rare, " + "the action or habit of estimating something as worthless.", + target="tooltip-target", + ), + ], + className="mb-4", +) + +app.layout = dbc.Container( + [ + alerts, + badges, + buttons, + cards, + collapse, + fade, + dbc.Row( + [ + dbc.Col([form, input_group], xs=12, md=6), + dbc.Col([input_], xs=12, md=6), + ] + ), + dbc.Row( + [ + dbc.Col([checklist_items], xs=12, md=6), + dbc.Col([radio_items], xs=12, md=6), + ] + ), + jumbotron, + list_group, + modal, + navbar, + popover, + progress, + spinner, + table, + tabs, + toast, + tooltip, + ], + fluid=True, + className="px-4", +) + + +@app.callback( + Output("collapse", "is_open"), + [Input("collapse-button", "n_clicks")], + [State("collapse", "is_open")], +) +def toggle_collapse(n, is_open): + if n: + return not is_open + return is_open + + +@app.callback( + Output("fade", "is_in"), + [Input("fade-button", "n_clicks")], + [State("fade", "is_in")], +) +def toggle_fade(n, is_in): + if n: + return not is_in + return is_in + + +@app.callback( + Output("popover", "is_open"), + [Input("popover-target", "n_clicks")], + [State("popover", "is_open")], +) +def toggle_popover(n, is_open): + if n: + return not is_open + return is_open + + +@app.callback( + Output("modal", "is_open"), + [Input("button", "n_clicks")], + [State("modal", "is_open")], +) +def toggle_modal(n, is_open): + if n: + return not is_open + return is_open + + +@app.callback( + Output("auto-toast", "is_open"), [Input("auto-toast-toggle", "n_clicks")] +) +def open_toast(_): + return True + + +@app.callback( + Output("gallery_checklist1", "value"), + Output("gallery_radio1", "value"), + Output("gallery_checklist2", "value"), + Output("gallery_radio2", "value"), + Input("gallery_checklist1", "value"), +) +def update_checklist(value): + # This is a dummy callback so checkboxes change color when theme is switched + return value, 0, value, 0 + + +if __name__ == "__main__": + app.run_server(debug=True) diff --git a/docs/server.py b/docs/server.py index fcec16071..82ccf51c5 100644 --- a/docs/server.py +++ b/docs/server.py @@ -62,6 +62,13 @@ def themes(): except TemplateNotFound: abort(404) + @server.route("/docs/themes/explorer/") + def theme_explorer(): + try: + return render_template("theme-explorer.html") + except TemplateNotFound: + abort(404) + @server.route("/docs/faq/") def faq(): try: diff --git a/docs/static/js/theme-switcher.js b/docs/static/js/theme-switcher.js index d7ef89832..38d52af78 100644 --- a/docs/static/js/theme-switcher.js +++ b/docs/static/js/theme-switcher.js @@ -1,65 +1,8 @@ -var bootstrap = - 'https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css'; -var bootswatchBase = 'https://stackpath.bootstrapcdn.com/bootswatch/4.5.2/'; -var bootswatchSfx = '/bootstrap.min.css'; - -var validBootswatch = new Set([ - 'cerulean', - 'cosmo', - 'cyborg', - 'darkly', - 'flatly', - 'journal', - 'litera', - 'lumen', - 'lux', - 'materia', - 'minty', - 'pulse', - 'sandstone', - 'simplex', - 'sketchy', - 'slate', - 'solar', - 'spacelab', - 'superhero', - 'united', - 'yeti' -]); - -function swapStyleSheet(sheetname) { - if (sheetname === 'bootstrap') { - document.getElementById('stylesheet').setAttribute('href', bootstrap); - } else if (validBootswatch.has(sheetname)) { - document - .getElementById('stylesheet') - .setAttribute('href', bootswatchBase + sheetname + bootswatchSfx); - } -} - -function updateSourceCode(sheetname) { - var container = document.getElementById('code-container'); - for (var j = 0; j < container.childNodes.length; j++) { - var node = container.childNodes[j]; - if (node.nodeType === 3) { - var text = node.nodeValue; - var replacedText = text.replace( - /dbc.themes.[A-Z]+/gi, - 'dbc.themes.' + sheetname.toUpperCase() - ); - if (replacedText !== text) { - container.replaceChild(document.createTextNode(replacedText), node); - break; - } - } - } -} - function handleChange(e) { if (e.target.value) { - var sheetname = e.target.value; - swapStyleSheet(sheetname); - updateSourceCode(sheetname); + document + .getElementById('explorer-iframe') + .setAttribute('src', '/docs/themes/explorer/' + e.target.value); } } diff --git a/docs/static/loading.css b/docs/static/loading.css index 973a8903b..900d7d1c3 100644 --- a/docs/static/loading.css +++ b/docs/static/loading.css @@ -1,8 +1,8 @@ ._dash-loading { margin: auto; color: transparent; - width: 0; - height: 0; + width: 2rem; + height: 2rem; text-align: center; } @@ -11,7 +11,7 @@ display: inline-block; width: 2rem; height: 2rem; - color: black; + color: var(--secondary); vertical-align: text-bottom; border: 0.25em solid currentColor; border-right-color: transparent; diff --git a/docs/static/theme-explorer.css b/docs/static/theme-explorer.css deleted file mode 100644 index 3422172e3..000000000 --- a/docs/static/theme-explorer.css +++ /dev/null @@ -1,66 +0,0 @@ -.te-navbar { - /* navbar */ - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: justify; - justify-content: space-between; - padding: 0.5rem 1rem; - - /* bg-dark */ - background-color: #343a40 !important; - - /* sticky-top */ - position: -webkit-sticky; - position: sticky; - top: 0; - z-index: 1020; - - /* .navbar-expand */ - -ms-flex-flow: row nowrap; - flex-flow: row nowrap; - -ms-flex-pack: start; - justify-content: flex-start; - - margin: 0; - font-size: 1rem; - font-weight: 400; - line-height: 1.5; - text-align: left; -} - -.te-navbar-nav { - display: flex; - padding-left: 0; - margin-bottom: 0; - list-style: none; - - -ms-flex-direction: row; - flex-direction: row; -} - -.te-nav-link { - /* navbar-expand nav-link */ - padding-right: 0.5rem; - padding-left: 0.5rem; - - /* navbar-dark nav-link */ - color: rgba(255, 255, 255, 0.5); - - /* nav-link */ - display: block; - padding: 0.5rem 1rem; - - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, - 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', - 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; -} - -.te-nav-link:hover, -.te-nav-link:focus { - text-decoration: none; - color: rgba(255, 255, 255, 0.75); -} diff --git a/docs/templates/macros/theme-explorer-navbar.html b/docs/templates/macros/theme-explorer-navbar.html index 08f726fb6..5600adac9 100644 --- a/docs/templates/macros/theme-explorer-navbar.html +++ b/docs/templates/macros/theme-explorer-navbar.html @@ -1,5 +1,5 @@ {% macro theme_explorer_navbar() -%} -