Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 93 additions & 52 deletions docs/components_page/components/spinner/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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",
),
]
]
22 changes: 22 additions & 0 deletions docs/components_page/components/spinner/loading.py
Original file line number Diff line number Diff line change
@@ -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"
4 changes: 2 additions & 2 deletions docs/components_page/page.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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),
Expand Down
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
77 changes: 72 additions & 5 deletions src/components/Spinner.js
Original file line number Diff line number Diff line change
@@ -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 <RSSpinner {...omit(['setProps'], otherProps)}>{children}</RSSpinner>;
const {
children,
loading_state,
spinner_style,
fullscreen,
...otherProps
} = props;
// this spacing is consistent with the behaviour of dcc.Loading
// it can be overridden with spinnerStyle
let defaultSpinnerStyle = children
? {display: 'block', margin: '1rem auto'}
: {};

const spinnerStyle = children
? {...defaultSpinnerStyle, ...spinner_style}
: spinner_style;
if (!children || (loading_state && loading_state.is_loading)) {
if (fullscreen) {
return (
<div
style={{
position: 'fixed',
width: '100vw',
height: '100vh',
top: 0,
left: 0,
backgroundColor: 'white',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
zIndex: 99
}}
>
<RSSpinner
style={spinnerStyle}
{...omit(['setProps', 'className', 'style'], otherProps)}
/>
</div>
);
}
return (
<RSSpinner
style={spinnerStyle}
{...omit(['setProps', 'className', 'style'], otherProps)}
/>
);
}
if (type(children) !== 'Object' || type(children) !== 'Function') {
return <Fragment>{children}</Fragment>;
}
return children;
};

Spinner._dashprivate_isLoadingComponent = true;

Spinner.propTypes = {
/**
* The ID of this component, used to identify dash components
Expand All @@ -26,11 +77,21 @@ Spinner.propTypes = {
*/
style: PropTypes.object,

/**
* Inline CSS styles to apply to the spinner.
*/
spinner_style: PropTypes.object,

/**
* Often used with CSS to style elements with common properties.
*/
className: PropTypes.string,

/**
* CSS class names to apply to the spinner.
*/
spinnerClassName: PropTypes.string,

/**
* Spinner color, options: primary, secondary, success, info, warning, danger,
* link. If not specified will default to text colour.
Expand All @@ -45,7 +106,13 @@ Spinner.propTypes = {
/**
* The spinner size. Options are 'sm', 'md' and 'lg'.
*/
size: PropTypes.string
size: PropTypes.string,

/**
* Boolean that determines if the loading spinner will be displayed
* full-screen or not.
*/
fullscreen: PropTypes.bool
};

export default Spinner;