Dash boostrap components#

Documentation:
https://dash-bootstrap-components.opensource.faculty.ai/docs/components/

What is bootstrap?
Bootstrap is a front-end framework that makes it easy to create web pages. It provides a set of pre-defined styles and components that can be used to create a web page. It is a popular framework, and is used by many web developers.

We will not get into the details of how to use bootstrap to create a web page from scratch. Instead, we will use the dash-bootstrap-components package to incorporate bootstrap into our Dash apps.

Themes#

By incorporating dash bootstrap components, we can use one of their themes to style our app. This is done by incorporating one of their style sheets.

You can find more information about the themes in the documentation:
https://dash-bootstrap-components.opensource.faculty.ai/docs/themes/

And you can see the available themes here:
https://bootswatch.com/

Here is an example of how to use a theme. We just need to pass the theme name — dbc.themes.SLATE, in this case — in a list to the external_stylesheets argument of the Dash object.

import dash
import dash_bootstrap_components as dbc

app = dash.Dash( external_stylesheets=[dbc.themes.SLATE] )

Important

If you want to use dash bootstrap components, then you should always include a theme. The default theme is dbc.themes.BOOTSTRAP. Include that as a minimum. If you do not include this as an external stylesheet, then some components might not look as expected.

Buttons#

Buttons are obviously an important part of any web page. Here are some examples of how to use buttons in a Dash app.

Notice that the dbc.Button function takes a color argument. This can be set to primary, secondary, success, warning, or danger. These colors are part of the bootstrap framework. For example, one bootstrap style could make the primary button blue, and the secondary button gray, while another style could make the primary button green, and the secondary button yellow.

It is also important to realize that while these buttons will appear on the web page, they do not do anything by default. We will need to use the callback function to make them interactive. We will get to this in a later section.

Here is an example of a layout with a header, a sub-header, and a few buttons. The buttons are all the same size, but have different colors.

app.layout = html.Div(
    children=[
        html.H1('This is the main header'),
        html.H2('Level 2 header'),
        dbc.Button('Important Button'),
        dbc.Button('Another Button', color='primary'),
        dbc.Button('Button', color='secondary'),
        dbc.Button('Button', color='success'),
        dbc.Button('Button', color='warning'),
        dbc.Button('Button', color='danger'),
    ]
)

Collecting user input#

There are many different ways that a dashboard user can input data. Here are some examples of how to use input components in a Dash app.

Radio and checklist#

The first example shows how to use radio buttons and checklists. The dbc.RadioItems and dbc.Checklist functions take a list of dictionaries as the options argument. Each dictionary should have a label and a value. The label is the text that will appear next to the button, and the value is the value that will be returned when the button is clicked.

The difference between a radio button and a checklist is that a radio button only allows one option to be selected, while a checklist allows multiple options to be selected.

Notice that the value argument is set to a sinlge value for the radio buttons, and a list of values for the checklist.

In this example, instead of placing the component directly into the layout, we are creating the component and then assigning it to a variable. We then place the variable into the layout. This is a good practice to follow, especially when the component is complex or has many arguments.

bourbon_radios = dbc.RadioItems(
    options=[
        dict(label="Buffalo Trace", value=1),
        dict(label="Basil Hayden", value=2),
        dict(label="Blanton's", value=3),
    ],
    value=2,
)

bourbon_checklist = dbc.Checklist(
    options=[
        dict(label="Buffalo Trace", value=1),
        dict(label="Basil Hayden", value=2),
        dict(label="Blanton's", value=3),
    ],
    value=[2,3],
)

app.layout = html.Div(
    children=[
        bourbon_radios,
        bourbon_checklist,
    ]
)

Select#

The dbc.Select function is used to create a dropdown menu. It takes a list of dictionaries as the options argument. Each dictionary should have a label and a value. The label is the text that will appear in the dropdown, and the value is the value that will be returned when the option is selected.

Just like with the radio buttons and checklist, we first define the component and then place it into the layout.

major_dropdown = dbc.Select(
    options=[
        dict(label='Finance', value=1),
        dict(label='Accounting', value=2),
        dict(label='Marketing', value=3),
        dict(label='Management', value=4),
    ],
    value=1,
)

app.layout = html.Div(
    children=[
        major_dropdown,
    ]
)

Input#

The dbc.Input function is used to create an input field. It takes a type argument that can be set to number or text. The number type will only allow numbers to be entered, and the text type will allow any text to be entered.

Input with numbers#

If the type argument is set to number, we can also set the min, max, and step arguments. The min and max arguments set the minimum and maximum values that can be entered, and the step argument sets the increment that the value will change when the up or down arrows are clicked.

numeric_input_var = dbc.Input(type="number", min=-5, max=5, step=0.5)

Input with text#

In this example, our type argument is set to text, and we also set the placeholder argument. This is the text that will appear in the input field when it is empty.

string_input_var = dbc.Input(type="text", placeholder="Some filler text")

Forms#

A form is a collection of input fields. By using forms, we can collect multiple pieces of information from the user at once. Forms also help us to organize the input fields on the page.

See here for more information on dash bootstrap forms:
https://dash-bootstrap-components.opensource.faculty.ai/docs/components/form/

Here is a basic example from their documentation that shows how to use a form. The dbc.Form function takes a list of input fields as the children argument. In this example, we have two input fields, email_input and password_input. These are defined as html.Div objects that contain a dbc.Label and a dbc.Input object.

import dash
from dash import html
import dash_bootstrap_components as dbc

app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP])

email_input = html.Div(
    [
        dbc.Label("Email", html_for="example-email"),
        dbc.Input(
            type="email",
            id="example-email",
            placeholder="Enter email"
        ),
    ],
)

password_input = html.Div(
    [
        dbc.Label("Password", html_for="example-password"),
        dbc.Input(
            type="password",
            id="example-password",
            placeholder="Enter password",
        ),
    ],
)

form = dbc.Form([email_input, password_input])

app.layout = html.Div(
    children=[
        form,
    ]
)

if __name__ == '__main__':
    app.run_server(debug=True)

Layout#

Dash bootstrap components has a Row and Col function that can be used to create a grid layout. This is a powerful feature that allows us to create complex layouts with ease.

For full details:
https://dash-bootstrap-components.opensource.faculty.ai/docs/components/layout/

For more on bootstrap’s grid system, see here:
https://getbootstrap.com/docs/5.2/layout/grid/

This is a somewhat lengthy example, but it shows how to use the Row and Col functions to create a layout with two rows. The first row has two columns, and the second row has one column. Each column contains a html.P object with some text, and the columns are styled with different background colors so that we can see how they are arranged on the page.

The first and second row are then passed to a dbc.Container object in the layout. We also include the fluid=True argument in the dbc.Container function. This makes the container take up the full width of the page and resize fluidly.

In each column in the first row, we also specify the width of the column with the width argument. This is set to a number between 1 and 12, and determines the width of the column. In this example, the first column is set to a width of 2, and the second column is set to a width of 6. This means that the first column will take up 2/12 of the width of the page, and the second column will take up 6/12 of the width of the page.

In the second row, we also use the width argument, but we set it to a dictionary instead of a number. This dictionary has two keys, size and offset. The size key is set to 6, and the offset key is set to 3. This means that the column will take up 6/12 of the width of the page, and will be offset by 3/12 of the width of the page. This is a way to center the column on the page.

import dash
import dash_bootstrap_components as dbc
from dash import html

app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP])

first_row = dbc.Row(
    [
        dbc.Col(
            html.P(
                'Some text that will be in the first column.',
                style=dict(
                    backgroundColor='red',
                    color='white',
                ),
            ),
            width=2,
        ),
        dbc.Col(
            html.P(
                'Some text that will be in the second column.',
                style=dict(backgroundColor='lightgreen'),
            ),
            width=6,
        ),
    ],
)

second_row = dbc.Row(
    [
        dbc.Col(
            html.P(
                'Some text that will be in the second row.',
                style=dict(backgroundColor='lightblue'),
            ),
            width=dict(size=6, offset=3),
        ),
    ]
)

app.layout = dbc.Container(
    children=[
        first_row,
        second_row,
    ],
    fluid=True,
)

if __name__ == '__main__':
    app.run_server(debug=True)

Styling#

Bootstrap allows us to use styling shortcuts.

Font#

Bootstrap font styling:
https://getbootstrap.com/docs/5.2/utilities/text/

Bootstrap colors:
https://getbootstrap.com/docs/5.2/utilities/colors/

A checklist with larger green text.

dbc.Checklist(
    options=[
        dict(label="Buffalo Trace", value=1),
        dict(label="Basil Hayden", value=2),
        dict(label="Blanton's", value=3),
    ],
    value=[2,3],
    class_name='text-success fs-3',
),

Border#

Bootstrap borders:
https://getbootstrap.com/docs/5.2/utilities/borders/

dbc.Checklist(
    options=[
        dict(label="Buffalo Trace", value=1),
        dict(label="Basil Hayden", value=2),
        dict(label="Blanton's", value=3),
    ],
    value=[2,3],
    class_name='border border-warning border-3 rounded',
),

Spacing#

Bootstrap spacing https://getbootstrap.com/docs/5.2/utilities/spacing/

Margin vs padding:
https://blog.hubspot.com/website/css-margin-vs-padding

Putting it all together#

import dash
from dash import html
import dash_bootstrap_components as dbc

app = dash.Dash( external_stylesheets=[dbc.themes.SLATE] )

# define the layout
app.layout = html.Div(
    children=[
        html.H1('This is the main header'),
        html.H2('Level 2 header'),
        dbc.Button('Important Button'),
        dbc.Button('Another Button', color='primary'),
        dbc.Button('Button', color='secondary'),
        dbc.Button('Button', color='success'),
        dbc.Button('Button', color='warning'),
        dbc.Button('Button', color='danger'),
        dbc.Select(
            options=[
                dict(label='Finance', value=1),
                dict(label='Analytics', value=2),
                dict(label='Marketing', value=3),
                dict(label='Management', value=4),
                dict(label='Accounting', value=5),
            ],
            value=1,
            class_name='mt-3',
        ),
        dbc.Input(type="number", min=-5, max=5, step=0.5, class_name='mt-3'),
        dbc.Input(type="text", placeholder="Some filler text", class_name='mt-3'),
        dbc.Row([
            dbc.Col(
                [
                dbc.Label('Type your name:', html_for='input-name'),
                dbc.Input(type="text", placeholder="Tyson", id='input-name'),
                ],
                width=5,
                class_name='mx-auto',
            ),
            dbc.Col(
                [
                dbc.Label('Pick a number between 3 and 7:', html_for='input-number'),
                dbc.Input(type="number", min=3, max=7, step=1, id='input-number'),
                ],
                width=5,
                class_name='mx-auto',
            ),
        ], className='mt-3 py-3 text-info border border-2 border-danger rounded',
        ),
        dbc.Row([
            dbc.Col(
                [
                dbc.Label('Select bourbons:', html_for='input-bourbon-1'),
                dbc.Checklist(
                    options=[
                        dict(label="Buffalo Trace", value=1),
                        dict(label="Basil Hayden", value=2),
                        dict(label="Blanton's", value=3),
                    ],
                    value=[2,3],
                    id='input-bourbon-1'
                ),
                ],
                width=5,
                class_name='mx-auto',
            ),
            dbc.Col(
                [
                dbc.Label('Select bourbons:', html_for='input-bourbon-2'),
                dbc.RadioItems(
                    options=[
                        dict(label="Buffalo Trace", value=1),
                        dict(label="Basil Hayden", value=2),
                        dict(label="Blanton's", value=3),
                    ],
                    value=3,
                    id='input-bourbon-2'
                ),
                ],
                width=5,
                class_name='mx-auto',
            ),
        ], className='mt-3 text-warning',
        )
    ], className='mx-5',
)

# run the app
if __name__ == '__main__':
    app.run_server(debug=True)