Skip to content

Commit

Permalink
Bootstrap 5 support (#646)
Browse files Browse the repository at this point in the history
* Alert

* Badge

* Button

* ButtonGroup

* Carousel

* Collapse

* Fade

* Add shim for html components that don't have class_name defined yet

* Update block button docs

* Update docs for Bootstrap 5

* RIP Jumbotron

* Add react-bootstrap beta

* Layout

* Docs fix

* Label

* Clean up example

* Monkeypatch doc tests

* New components - Offcanvas and pagination (#643)

* Added offcanvas components

* Offcanvas doc snippets

* Added offcanvas documentation

* Fixed long text issue

* Added react-bootstrap

* Added offcanvas

* Added offcanvas tests

* Added js tests for offcanvas

* Addition of new pagination component

* Combined offcanvas into single component

* Formatting

* ABetter handling of pagination component

* Updated pagination docs

* Removed invalid code

* Updated npm demo to Bootstrap 5

* Updated pagination docs to include R and jl

* Updated pagination tests

* Fixed callbacks

* Reverted to 5.0.2 to avoid issues with offcanvas backdrop until resolved

* Fixed offcanvas tests

* Tidy up

* Progress

* Format tests

* Spinner

* Table

* Toast

* New component Accordion (#645)

* Accordion component and js test

* Added documentation for accordion

* R and Julia examples

* Fixed h2 formatting issues

* Added accordion folder for flake8

* Update demo/Demo.js

Co-authored-by: glsdown <52132406+glsdown@users.noreply.github.com>

Co-authored-by: Tom Begley <tomcbegley@gmail.com>

* flake8 config

* List group updated to Bootstrap 5 (#647)

* Updated list-group component

* Updated list-group docs

* Bug fixes

* Tabs

* Form

* Form updates + examples

* Checklist / RadioItems

* Select

* themes

* BS5 updates for docs

* Fix doc tests

* InputGroup

* Fix JS tests

* Checkbox/Radio

* format js

* Modal

* Modal docs

* Fix format command

* Card, Nav and Navbar (#648)

* Monkeypatch doc tests

* Card

* Nav and NavBar  Update to Collapse to remove navbar prop

* fixed Card.test.js for Card body test

* updated docs for Navbar example.
Also updated julia and R snippets

* updates to Navbar and Collapse after review

* updated index for deleted NavbarCollapse

* lint and black

Co-authored-by: tcbegley <tomcbegley@gmail.com>

* DropdownMenu

* NavbarToggler

* Tooltip+Popover

* Consistent imports

* Fix accordion tests

* Initial breadcrumb component

* Set accordion to first component

* Format code

* Update Breadcrumb

* Snippet test fixes for breadcrumb

* Popover - minor prop updates (#652)

* Use size prop consistently

Co-authored-by: glsdown <52132406+glsdown@users.noreply.github.com>
Co-authored-by: AnnMarieW <72614349+AnnMarieW@users.noreply.github.com>
  • Loading branch information
3 people committed Aug 24, 2021
1 parent 262bb9b commit 0e6ac77
Show file tree
Hide file tree
Showing 360 changed files with 6,044 additions and 5,379 deletions.
12 changes: 8 additions & 4 deletions R/themes.R
@@ -1,12 +1,12 @@
.prependBootswatch <- function(suffix) {
BOOTSWATCH_BASE <- "https://stackpath.bootstrapcdn.com/bootswatch/4.5.2/"
BOOTSWATCH_BASE <- "https://cdn.jsdelivr.net/npm/bootswatch@5.1.0/dist/"
return(paste(BOOTSWATCH_BASE, suffix, sep=""))
}

#' @export'
dbcThemes <- list(
BOOTSTRAP = "https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css",
GRID = "https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap-grid.min.css",
BOOTSTRAP = "https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css",
GRID = "https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap-grid.min.css",
CERULEAN = .prependBootswatch("cerulean/bootstrap.min.css"),
COSMO = .prependBootswatch("cosmo/bootstrap.min.css"),
CYBORG = .prependBootswatch("cyborg/bootstrap.min.css"),
Expand All @@ -18,7 +18,9 @@ dbcThemes <- list(
LUX = .prependBootswatch("lux/bootstrap.min.css"),
MATERIA = .prependBootswatch("materia/bootstrap.min.css"),
MINTY = .prependBootswatch("minty/bootstrap.min.css"),
MORPH = .prependBootswatch("morph/bootstrap.min.css"),
PULSE = .prependBootswatch("pulse/bootstrap.min.css"),
QUARTZ = .prependBootswatch("quartz/bootstrap.min.css"),
SANDSTONE = .prependBootswatch("sandstone/bootstrap.min.css"),
SIMPLEX = .prependBootswatch("simplex/bootstrap.min.css"),
SKETCHY = .prependBootswatch("sketchy/bootstrap.min.css"),
Expand All @@ -27,5 +29,7 @@ dbcThemes <- list(
SPACELAB = .prependBootswatch("spacelab/bootstrap.min.css"),
SUPERHERO = .prependBootswatch("superhero/bootstrap.min.css"),
UNITED = .prependBootswatch("united/bootstrap.min.css"),
YETI = .prependBootswatch("yeti/bootstrap.min.css")
VAPOR = .prependBootswatch("vapor/bootstrap.min.css"),
YETI = .prependBootswatch("yeti/bootstrap.min.css"),
ZEPHYR = .prependBootswatch("zephyr/bootstrap.min.css")
)
10 changes: 7 additions & 3 deletions dash_bootstrap_components/themes.py
@@ -1,10 +1,10 @@
BOOTSTRAP = (
"https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
"https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css"
)

GRID = "https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap-grid.min.css" # noqa
GRID = "https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap-grid.min.css" # noqa

_BOOTSWATCH_BASE = "https://stackpath.bootstrapcdn.com/bootswatch/4.5.2/"
_BOOTSWATCH_BASE = "https://cdn.jsdelivr.net/npm/bootswatch@5.1.0/dist/"

CERULEAN = _BOOTSWATCH_BASE + "cerulean/bootstrap.min.css"
COSMO = _BOOTSWATCH_BASE + "cosmo/bootstrap.min.css"
Expand All @@ -17,7 +17,9 @@
LUX = _BOOTSWATCH_BASE + "lux/bootstrap.min.css"
MATERIA = _BOOTSWATCH_BASE + "materia/bootstrap.min.css"
MINTY = _BOOTSWATCH_BASE + "minty/bootstrap.min.css"
MORPH = _BOOTSWATCH_BASE + "morph/bootstrap.min.css"
PULSE = _BOOTSWATCH_BASE + "pulse/bootstrap.min.css"
QUARTZ = _BOOTSWATCH_BASE + "quartz/bootstrap.min.css"
SANDSTONE = _BOOTSWATCH_BASE + "sandstone/bootstrap.min.css"
SIMPLEX = _BOOTSWATCH_BASE + "simplex/bootstrap.min.css"
SKETCHY = _BOOTSWATCH_BASE + "sketchy/bootstrap.min.css"
Expand All @@ -26,4 +28,6 @@
SPACELAB = _BOOTSWATCH_BASE + "spacelab/bootstrap.min.css"
SUPERHERO = _BOOTSWATCH_BASE + "superhero/bootstrap.min.css"
UNITED = _BOOTSWATCH_BASE + "united/bootstrap.min.css"
VAPOR = _BOOTSWATCH_BASE + "vapor/bootstrap.min.css"
YETI = _BOOTSWATCH_BASE + "yeti/bootstrap.min.css"
ZEPHYR = _BOOTSWATCH_BASE + "zephyr/bootstrap.min.css"
32 changes: 16 additions & 16 deletions demo/Demo.js
Expand Up @@ -202,8 +202,8 @@ const Demo = () => (
<Card color="dark" outline={true}>
<CardHeader>Header</CardHeader>
<CardBody>
<h5 class_name="card-title">This card has a header</h5>
<p class_name="card-text">And some text in the body</p>
<h5 className="card-title">This card has a header</h5>
<p className="card-text">And some text in the body</p>
</CardBody>
<CardFooter>Footer</CardFooter>
</Card>
Expand All @@ -215,25 +215,25 @@ const Demo = () => (
src="https://images.pexels.com/photos/457882/pexels-photo-457882.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=350"
/>
<CardBody>
<h5 class_name="card-title">Card with image</h5>
<p class_name="card-text">This card has an image</p>
<h5 className="card-title">Card with image</h5>
<p className="card-text">This card has an image</p>
</CardBody>
</Card>
</Col>
<Col md={3}>
<Card>
<CardBody>
<h5 class_name="card-title">Here's another card</h5>
<p class_name="card-text">With some text, and a button</p>
<h5 className="card-title">Here's another card</h5>
<p className="card-text">With some text, and a button</p>
<Button color="success">Click here</Button>
</CardBody>
</Card>
</Col>
<Col md={3}>
<Card>
<CardBody>
<h5 class_name="card-title">Here's yet another card</h5>
<p class_name="card-text">With some text, and some links</p>
<h5 className="card-title">Here's yet another card</h5>
<p className="card-text">With some text, and some links</p>
<CardLink href="https://www.asidatascience.com">
External
</CardLink>
Expand All @@ -247,17 +247,17 @@ const Demo = () => (
<CardDeck>
<Card>
<CardBody>
<h5 class_name="card-title">The first card</h5>
<p class_name="card-text">
<h5 className="card-title">The first card</h5>
<p className="card-text">
This is a card with some text on it, it's the first one in the
deck.
</p>
</CardBody>
</Card>
<Card>
<CardBody>
<h5 class_name="card-title">The second card</h5>
<p class_name="card-text">
<h5 className="card-title">The second card</h5>
<p className="card-text">
This is a card with some text on it, it's the second one in the
deck. It has a bit more text in it so that we can see how the
vertical spacing will work.
Expand All @@ -266,9 +266,9 @@ const Demo = () => (
</Card>
<Card outline={true} color="primary">
<CardBody>
<h5 class_name="card-title">The third card</h5>
<h6 class_name="card-subtitle">...and the last :(</h6>
<p class_name="card-text">This card doesn't have much text...</p>
<h5 className="card-title">The third card</h5>
<h6 className="card-subtitle">...and the last :(</h6>
<p className="card-text">This card doesn't have much text...</p>
<Button color="danger">Click me</Button>
</CardBody>
</Card>
Expand Down Expand Up @@ -365,7 +365,7 @@ const Demo = () => (
<FadeComponent>
<Card>
<CardBody>
<p class_name="card-text">This content fades in and out</p>
<p className="card-text">This content fades in and out</p>
</CardBody>
</Card>
</FadeComponent>
Expand Down
3 changes: 1 addition & 2 deletions demo/index.html
Expand Up @@ -6,8 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css"
integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2"
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
crossorigin="anonymous"
/>
</head>
Expand Down
47 changes: 43 additions & 4 deletions docs/components_page/__init__.py
Expand Up @@ -3,12 +3,46 @@

import dash
import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_html_components as html
from jinja2 import Environment, FileSystemLoader

from .components.table.simple import table_body, table_header
from .components.tabs.simple import tab1_content, tab2_content
from .markdown_parser import parse

# TODO: delete once Dash 2.0 is released
def class_name_shim(fn):
def new_init(self, *args, **kwargs):
kwargs["className"] = kwargs.get("class_name", kwargs.get("className"))
return fn(
self,
*args,
**{k: v for k, v in kwargs.items() if k != "class_name"},
)

return new_init


for component in [
dcc.Markdown,
html.A,
html.Blockquote,
html.Div,
html.H1,
html.H2,
html.H3,
html.H4,
html.H5,
html.H6,
html.Hr,
html.I,
html.P,
html.Small,
]:
component.__init__ = class_name_shim(component.__init__)


from .components.table.simple import table_body, table_header # noqa
from .components.tabs.simple import tab1_content, tab2_content # noqa
from .markdown_parser import parse # noqa

SERVE_LOCALLY = os.getenv("DBC_DOCS_MODE", "production") == "dev"

Expand Down Expand Up @@ -59,8 +93,10 @@ def _get_label(slug):

def register_apps():
component_bodies = {
"accordion": {"markdown_path": COMPONENTS / "accordion.md"},
"alert": {"markdown_path": COMPONENTS / "alert.md"},
"badge": {"markdown_path": COMPONENTS / "badge.md"},
"breadcrumb": {"markdown_path": COMPONENTS / "breadcrumb.md"},
"button": {"markdown_path": COMPONENTS / "button.md"},
"button_group": {"markdown_path": COMPONENTS / "button_group.md"},
"card": {"markdown_path": COMPONENTS / "card.md"},
Expand All @@ -71,7 +107,6 @@ def register_apps():
"form": {"markdown_path": COMPONENTS / "form.md"},
"input": {"markdown_path": COMPONENTS / "input.md"},
"input_group": {"markdown_path": COMPONENTS / "input_group.md"},
"jumbotron": {"markdown_path": COMPONENTS / "jumbotron.md"},
"layout": {"markdown_path": COMPONENTS / "layout.md"},
"list_group": {"markdown_path": COMPONENTS / "list_group.md"},
"modal": {
Expand All @@ -80,6 +115,10 @@ def register_apps():
},
"nav": {"markdown_path": COMPONENTS / "nav.md"},
"navbar": {"markdown_path": COMPONENTS / "navbar.md"},
"offcanvas": {
"markdown_path": COMPONENTS / "offcanvas.md",
},
"pagination": {"markdown_path": COMPONENTS / "pagination.md"},
"popover": {"markdown_path": COMPONENTS / "popover.md"},
"progress": {"markdown_path": COMPONENTS / "progress.md"},
"spinner": {"markdown_path": COMPONENTS / "spinner.md"},
Expand Down
11 changes: 8 additions & 3 deletions docs/components_page/components/__tests__/helpers.py
Expand Up @@ -8,7 +8,8 @@ def py_source_to_app(py_source, env):
Create a Dash app from a string defining the app.
"""
env = env or {}
exec(py_source, env)
# TODO: remove class_name modifiers
exec(py_source.replace("class_name", "className"), env)
return env["app"]


Expand Down Expand Up @@ -56,12 +57,16 @@ def load_r_app(path, component_name):
snippet=path.read_text(),
components=component_name,
port=8050,
)
).replace(
"class_name", "className"
) # TODO: remove this in future


def load_jl_app(path, component_name):
return JL_WRAPPER.format(
snippet=path.read_text(),
components=component_name,
port=8050,
)
).replace(
"class_name", "className"
) # TODO: remove this in future
55 changes: 55 additions & 0 deletions docs/components_page/components/__tests__/test_accordion.py
@@ -0,0 +1,55 @@
"""
Testing of callbacks in non-Python Accordion snippets.
"""
from pathlib import Path

import dash.testing.wait as wait

from .helpers import load_jl_app, load_r_app

HERE = Path(__file__).parent


def test_r_simple(dashr):
r_app = load_r_app((HERE.parent / "accordion" / "simple.R"), "accordion")
dashr.start_server(r_app)
check_simple_callbacks(dashr)


def test_jl_simple(dashjl):
jl_app = load_jl_app(
(HERE.parent / "accordion" / "simple.jl"), "accordion"
)
with open("app.jl", "w") as f:
f.write(jl_app)
dashjl.start_server(jl_app)
check_simple_callbacks(dashjl)


def check_simple_callbacks(runner):
# Find the accordion object
accordion_comp = runner.find_element("#accordion")
accordion_text = runner.find_element("#accordion-contents")

# Check it has 3 accordion-items in it
items = accordion_comp.find_elements_by_class_name("accordion-item")
wait.until(
lambda: len(items) == 3,
timeout=4,
)

# Click the third section
items[2].find_element_by_class_name("accordion-button").click()

# Check the text in contents changes to "Item selected: item-3"
wait.until(
lambda: accordion_text.text == "Item selected: item-3",
timeout=4,
)

# Check that the right section is showing
item = accordion_comp.find_element_by_class_name("show")
wait.until(
lambda: item.text == "This is the content of the third section",
timeout=4,
)

0 comments on commit 0e6ac77

Please sign in to comment.