diff --git a/docs/components_page/components/spinner/__init__.py b/docs/components_page/components/spinner/__init__.py
index 464f7d362..253551bbd 100644
--- a/docs/components_page/components/spinner/__init__.py
+++ b/docs/components_page/components/spinner/__init__.py
@@ -4,7 +4,11 @@
import dash_html_components as html
from ...api_doc import ApiDoc
-from ...helpers import ExampleContainer, HighlightedSource
+from ...helpers import (
+ ExampleContainer,
+ HighlightedSource,
+ load_source_with_environment,
+)
from ...metadata import get_component_metadata
from .button import spinners as spinners_button
from .grow import spinners as spinners_grow
@@ -14,59 +18,96 @@
HERE = Path(__file__).parent
spinners_simple_source = (HERE / "simple.py").read_text()
+spinners_loading_source = (HERE / "loading.py").read_text()
spinners_grow_source = (HERE / "grow.py").read_text()
spinners_size_source = (HERE / "size.py").read_text()
spinners_button_source = (HERE / "button.py").read_text()
-content = [
- html.H2("Spinners", className="display-4"),
- html.P(
- dcc.Markdown(
- "Indicate the loading state of a component or page with the "
- "`Spinner` component."
+
+def get_content(app):
+ return [
+ html.H2("Spinners", className="display-4"),
+ html.P(
+ dcc.Markdown(
+ "Indicate the loading state of a component or page with the "
+ "`Spinner` component."
+ ),
+ className="lead",
+ ),
+ html.P(
+ dcc.Markdown(
+ "The `Spinner` component can be used either to create a "
+ "standalone spinner, or used in the same way as [dcc.Loading]"
+ "(https://dash.plot.ly/dash-core-components/loading) by "
+ "passing children."
+ )
+ ),
+ html.H4("Basic usage"),
+ html.P(
+ dcc.Markdown(
+ "To create a simple spinner, just add `dbc.Spinner()` to your "
+ "layout. By default, `Spinner` uses the current text color "
+ "for its border color. Override the color of the `Spinner` "
+ "using the `color` argument and one of the eight supported "
+ "contextual color names."
+ )
+ ),
+ ExampleContainer(spinners_simple),
+ HighlightedSource(spinners_simple_source),
+ html.H4("Loading component"),
+ html.P(
+ dcc.Markdown(
+ "If you pass children to `dbc.Spinner`, it will behave like "
+ "`dcc.Loading`, which is to say it will render a spinner "
+ "until the children component have loaded."
+ ),
+ ),
+ html.P(
+ dcc.Markdown(
+ "The spinner is rendered inside a `html.Div`. The `html.Div` "
+ "that the spinner is rendered in will expand to fill the "
+ "available width, and add a top and bottom margin. This can "
+ "be overridden using `spinner_style` or `spinnerClassName`. "
+ "Alter"
+ )
+ ),
+ ExampleContainer(
+ load_source_with_environment(
+ spinners_loading_source, "loading_spinner", {"app": app}
+ )
+ ),
+ HighlightedSource(spinners_loading_source),
+ html.H4("Growing spinners"),
+ html.P(
+ dcc.Markdown(
+ "There are two types of spinner, border and grow. Border "
+ "spinners are the default and can be seen above. To use grow "
+ 'spinners set `type="grow"`.'
+ )
+ ),
+ ExampleContainer(spinners_grow),
+ HighlightedSource(spinners_grow_source),
+ html.H4("Size"),
+ html.P(
+ dcc.Markdown(
+ 'Create a small spinner with `size="sm"` or use inline style '
+ "arguments for full control of the size of the spinner."
+ )
+ ),
+ ExampleContainer(spinners_size),
+ HighlightedSource(spinners_size_source),
+ html.H4("Buttons"),
+ html.P(
+ dcc.Markdown(
+ "The `Spinner` component can be used inside buttons to "
+ "indicate that an action is currently processing or taking "
+ "place."
+ )
+ ),
+ ExampleContainer(spinners_button),
+ HighlightedSource(spinners_button_source),
+ ApiDoc(
+ get_component_metadata("src/components/Spinner.js"),
+ component_name="Spinner",
),
- className="lead",
- ),
- html.H4("Basic usage"),
- html.P(
- dcc.Markdown(
- "By default, `Spinner` uses the current text color for its border "
- "color. Override the color of the `Spinner` using the `color` "
- "argument and one of the eight supported contextual color names."
- )
- ),
- ExampleContainer(spinners_simple),
- HighlightedSource(spinners_simple_source),
- html.H4("Growing spinners"),
- html.P(
- dcc.Markdown(
- "There are two types of spinner, border and grow. Border spinners "
- "are the default and can be seen above. To use grow spinners set "
- '`type="grow"`.'
- )
- ),
- ExampleContainer(spinners_grow),
- HighlightedSource(spinners_grow_source),
- html.H4("Size"),
- html.P(
- dcc.Markdown(
- 'Create a small spinner with `size="sm"` or use inline style '
- "arguments for full control of the size of the spinner."
- )
- ),
- ExampleContainer(spinners_size),
- HighlightedSource(spinners_size_source),
- html.H4("Buttons"),
- html.P(
- dcc.Markdown(
- "The `Spinner` component can be used inside buttons to indicate "
- "that an action is currently processing or taking place."
- )
- ),
- ExampleContainer(spinners_button),
- HighlightedSource(spinners_button_source),
- ApiDoc(
- get_component_metadata("src/components/Spinner.js"),
- component_name="Spinner",
- ),
-]
+ ]
diff --git a/docs/components_page/components/spinner/loading.py b/docs/components_page/components/spinner/loading.py
new file mode 100644
index 000000000..d3eeea8e6
--- /dev/null
+++ b/docs/components_page/components/spinner/loading.py
@@ -0,0 +1,22 @@
+import time
+
+import dash_bootstrap_components as dbc
+import dash_html_components as html
+from dash.dependencies import Input, Output
+
+loading_spinner = html.Div(
+ [
+ dbc.Button("Load", id="loading-button"),
+ dbc.Spinner(html.Div(id="loading-output")),
+ ]
+)
+
+
+@app.callback(
+ Output("loading-output", "children"), [Input("loading-button", "n_clicks")]
+)
+def load_output(n):
+ if n:
+ time.sleep(1)
+ return f"Output loaded {n} times"
+ return "Output not reloaded yet"
diff --git a/docs/components_page/page.py b/docs/components_page/page.py
index 0e88b6578..09d4a0244 100644
--- a/docs/components_page/page.py
+++ b/docs/components_page/page.py
@@ -21,7 +21,7 @@
from .components.navbar import get_content as get_navbar_content
from .components.popover import get_content as get_popover_content
from .components.progress import get_content as get_progress_content
-from .components.spinner import content as spinner_content
+from .components.spinner import get_content as get_spinner_content
from .components.table import content as table_content
from .components.tabs import get_content as get_tabs_content
from .components.toast import get_content as get_toast_content
@@ -103,7 +103,7 @@ def __init__(self, app):
"navbar": get_navbar_content(self._app),
"popover": get_popover_content(self._app),
"progress": get_progress_content(self._app),
- "spinner": spinner_content,
+ "spinner": get_spinner_content(self._app),
"table": table_content,
"tabs": get_tabs_content(self._app),
"toast": get_toast_content(self._app),
diff --git a/setup.cfg b/setup.cfg
index d80d992e1..03bcd36bb 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -30,6 +30,7 @@ exclude =
docs/components_page/components/popover/popover.py,
docs/components_page/components/progress/animated.py,
docs/components_page/components/progress/interval.py,
+ docs/components_page/components/spinner/loading.py,
docs/components_page/components/table/kwargs.py,
docs/components_page/components/tabs/active_tab.py,
docs/components_page/components/tabs/card.py,
diff --git a/src/components/Spinner.js b/src/components/Spinner.js
index ca8f64f23..755a049a3 100644
--- a/src/components/Spinner.js
+++ b/src/components/Spinner.js
@@ -1,13 +1,64 @@
-import React from 'react';
+import React, {Fragment} from 'react';
import PropTypes from 'prop-types';
-import {omit} from 'ramda';
+import {omit, type} from 'ramda';
import {Spinner as RSSpinner} from 'reactstrap';
const Spinner = props => {
- const {children, ...otherProps} = props;
- return