Dashboard components and themes

Small Data SF

Sara Altman

Posit, PBC

Isabella Velásquez

Posit, PBC

2024-09-23

Dashboard components

Cards

Cards are containers for code cell outputs (e.g., plots, tables, value boxes) and free form markdown text. The content of cards typically maps to cells in your notebook or source document.

Pages

dashboard.qmd
---
title: "Pages"
format: dashboard
---

```{python}
from plotnine import ggplot, aes, geom_point, geom_bar
from plotnine.data import mpg
```

# Scatter

```{python}
#| title: Highway vs. city mileage
(
    ggplot(mpg, aes(x = "cty", y = "hwy"))
    + geom_point()
)
```

# Bar

```{python}
#| title: Drive types
(
    ggplot(mpg, aes(x = "drv"))
    + geom_bar()
)
```

Pages

dashboard.qmd
---
title: "Pages"
format: dashboard
---

```{python}
from plotnine import ggplot, aes, geom_point, geom_bar
from plotnine.data import mpg
```

# Scatter

```{python}
#| title: Highway vs. city mileage
(
    ggplot(mpg, aes(x = "cty", y = "hwy"))
    + geom_point()
)
```

# Bar

```{python}
#| title: Drive types
(
    ggplot(mpg, aes(x = "drv"))
    + geom_bar()
)
```

Pages

dashboard.qmd
---
title: "Pages"
format: dashboard
---

```{python}
from plotnine import ggplot, aes, geom_point, geom_bar
from plotnine.data import mpg
```

# Scatter

```{python}
#| title: Highway vs. city mileage
(
    ggplot(mpg, aes(x = "cty", y = "hwy"))
    + geom_point()
)
```

# Bar

```{python}
#| title: Drive types
(
    ggplot(mpg, aes(x = "drv"))
    + geom_bar()
)
```

Heights and widths of rows and columns

dashboard.qmd
---
title: "Rows, then columns"
format: 
  dashboard:
    logo: images/beetle.png
---

```{python}
from plotnine import ggplot, aes, geom_point, geom_bar
from plotnine.data import mpg
```

## Overview {height="30%"}

###  {width="20%"}

This dashboard summarizes an illuminating analysis of fuel economy of cars.

###  {width="80%"}

This is a car.

![](images/car.png){fig-alt="Illustration of a teal color car." width="300"}

## Plots {height="70%"}

### Scatter {width="75%"}

```{python}
#| title: Highway vs. city mileage
(
    ggplot(mpg, aes(x = "cty", y = "hwy"))
    + geom_point()
)
```

### Bar {width="25%"}

```{python}
#| title: Drive types
(
    ggplot(mpg, aes(x = "drv"))
    + geom_bar()
)
```

Heights and widths of rows and columns

dashboard.qmd
---
title: "Rows, then columns"
format: 
  dashboard:
    logo: images/beetle.png
---

```{python}
from plotnine import ggplot, aes, geom_point, geom_bar
from plotnine.data import mpg
```

## Overview {height="30%"}

###  {width="20%"}

This dashboard summarizes an illuminating analysis of fuel economy of cars.

###  {width="80%"}

This is a car.

![](images/car.png){fig-alt="Illustration of a teal color car." width="300"}

## Plots {height="70%"}

### Scatter {width="75%"}

```{python}
#| title: Highway vs. city mileage
(
    ggplot(mpg, aes(x = "cty", y = "hwy"))
    + geom_point()
)
```

### Bar {width="25%"}

```{python}
#| title: Drive types
(
    ggplot(mpg, aes(x = "drv"))
    + geom_bar()
)
```

Tabsets

dashboard.qmd
---
title: "Tabsets"
format: 
  dashboard:
    logo: images/beetle.png
---

```{python}
from plotnine import ggplot, aes, geom_point, geom_bar
from plotnine.data import mpg
```

## Overview {.tabset}

### Objective

This dashboard summarizes an illuminating analysis of fuel economy of cars.

### Car

This is a car.

![](images/car.png){fig-alt="Illustration of a teal color car." width="299"}

## Plots {.tabset}

### Scatter

```{python}
#| title: Highway vs. city mileage
(
    ggplot(mpg, aes(x = "cty", y = "hwy"))
    + geom_point()
)
```

### Bar

```{python}
#| title: Drive types
(
    ggplot(mpg, aes(x = "drv"))
    + geom_bar()
)
```

Tabsets

Each card within a row/column or each row/column within another becomes a tab:

dashboard.qmd
---
title: "Tabsets"
format: 
  dashboard:
    logo: images/beetle.png
---

```{python}
from plotnine import ggplot, aes, geom_point, geom_bar
from plotnine.data import mpg
```

## Overview {.tabset}

### Objective

This dashboard summarizes an illuminating analysis of fuel economy of cars.

### Car

This is a car.

![](images/car.png){fig-alt="Illustration of a teal color car." width="299"}

## Plots {.tabset}

### Scatter

```{python}
#| title: Highway vs. city mileage
(
    ggplot(mpg, aes(x = "cty", y = "hwy"))
    + geom_point()
)
```

### Bar

```{python}
#| title: Drive types
(
    ggplot(mpg, aes(x = "drv"))
    + geom_bar()
)
```

Value boxes

  • Value boxes are a great way to prominently display simple values within a dashboard

  • You can create value boxes in executable cells or plain markdown in divs

  • Value boxes use Bootstrap icons (https://icons.getbootstrap.com) and can be set to any color (e.g., with a HEX code) or color alias defined by the theme (we’ll get to themes later!)

    Color alias Default theme color(s)
    primary Blue
    secondary Gray
    success Green
    info Bright Blue
    warning Yellow/Orange
    danger Red
    light Light Gray
    dark Black

Value boxes

dashboard.qmd
---
title: "Valueboxes"
format: dashboard
---

```{python}
from plotnine import ggplot, aes, geom_point, geom_bar
from plotnine.data import mpg
```

## Value boxes {height="25%"}

```{python}
#| label: calculate-values
lowest_mileage_index = mpg['cty'].idxmin()
lowest_mileage_car = mpg.iloc[lowest_mileage_index]
lowest_mileage_cty = mpg.loc[lowest_mileage_index, 'cty']

highest_mileage_index = mpg['cty'].idxmax()
highest_mileage_car = mpg.iloc[highest_mileage_index]
highest_mileage_cty = mpg.loc[highest_mileage_index, 'cty']

mean_city_mileage = mpg['cty'].mean()
rounded_mean_city_mileage = round(mean_city_mileage, 2)
```

```{python}
#| content: valuebox
#| title: "Least efficient"
#| icon: fuel-pump-fill
#| color: danger
dict(
  value = str(f"{lowest_mileage_cty} mpg")
)
```

```{python}
#| content: valuebox
#| title: "Most efficient"
dict(
  icon = "fuel-pump",
  color = "success",
  value = str(f"{highest_mileage_cty} mpg")
)
```

::: {.valuebox icon="fuel-pump" color="secondary"}
Average city mileage

`{python} str(rounded_mean_city_mileage)` mpg
:::

## Plots {height="75%"}

```{python}
#| title: Highway vs. city mileage
(
    ggplot(mpg, aes(x = "cty", y = "hwy"))
    + geom_point()
)
```

```{python}
#| title: Drive types
(
    ggplot(mpg, aes(x = "drv"))
    + geom_bar()
)
```

Value boxes

dashboard.qmd
---
title: "Valueboxes"
format: dashboard
---

```{python}
from plotnine import ggplot, aes, geom_point, geom_bar
from plotnine.data import mpg
```

## Value boxes {height="25%"}

```{python}
#| label: calculate-values
lowest_mileage_index = mpg['cty'].idxmin()
lowest_mileage_car = mpg.iloc[lowest_mileage_index]
lowest_mileage_cty = mpg.loc[lowest_mileage_index, 'cty']

highest_mileage_index = mpg['cty'].idxmax()
highest_mileage_car = mpg.iloc[highest_mileage_index]
highest_mileage_cty = mpg.loc[highest_mileage_index, 'cty']

mean_city_mileage = mpg['cty'].mean()
rounded_mean_city_mileage = round(mean_city_mileage, 2)
```

```{python}
#| content: valuebox
#| title: "Least efficient"
#| icon: fuel-pump-fill
#| color: danger
dict(
  value = str(f"{lowest_mileage_cty} mpg")
)
```

```{python}
#| content: valuebox
#| title: "Most efficient"
dict(
  icon = "fuel-pump",
  color = "success",
  value = str(f"{highest_mileage_cty} mpg")
)
```

::: {.valuebox icon="fuel-pump" color="secondary"}
Average city mileage

`{python} str(rounded_mean_city_mileage)` mpg
:::

## Plots {height="75%"}

```{python}
#| title: Highway vs. city mileage
(
    ggplot(mpg, aes(x = "cty", y = "hwy"))
    + geom_point()
)
```

```{python}
#| title: Drive types
(
    ggplot(mpg, aes(x = "drv"))
    + geom_bar()
)
```

Markdown text

  • You can include markdown text anywhere within a dashboard

  • Markdown text is automatically placed in cards, but you can also explicitly put them in cards with fenced divs, and add titles to cards

    ::: {.card title="Title goes here"}
    Text goes here.
    :::
  • You can place markdown text and other cell output in a single card as well

    ::: {.card title="Title goes here"}
    Text goes here.
    
    ```{r}
    # code generating output goes here
    ```
    :::    

Your turn

Start

Work on olympicdash-2.qmd.

Goal

Your goal is to create a dashboard that looks like the following:

Step 1

  • Make the columns 65% (first) and 35% (second) of width of the dashboard.
  • Divide the first column into rows of 60% (first) and 40% (second) of height of the dashboard.
  • In the second row of the first column, combine markdown text about cancelled Olympic games with the medals by year plot in the same cell.
05:00

Step 2

  • Divide the second column into rows of 25% (first) and 75% (second) of height of the dashboard.
  • In the first row of this second column, add value boxes for highest numbers of gold, silver, and bronze medals with appropriate color for each medal and using the award-fill icon.

Use the code commented with TODO for Step 2 to help you create the value boxes.

10:00

Step 3

  • In the second row of the second column, create tables (using the great_tables library) of top 30 and bottom 30 total medals by team, sorted in descending order for the top 30 and ascending order for the bottom 30 total medals, and add color to the table based on data values. Use data_color().
  • Place these tables in tabsets with descriptive text about table content in the same card/tab.

Un-comment the code under TODO for Step 3 and move it to the appropriate location. Use olympics_sorted_descending_top30 and olympics_sorted_ascending_bottom30 to create the tables.

10:00

Interactive plotting

  • We’ve been creating static plots with plotnine
  • But you can also add interactive plots to your dashboard, e.g., with plotly

Theming

Bootswatch themes

Quarto dashboards can be styled with one of the 25 themes from the Bootswatch project:

dashboard.qmd
---
title: "Bootswatch themes"
format: 
  dashboard:
    theme: quartz
---

```{python}
from plotnine import ggplot, aes, geom_point, geom_bar
from plotnine.data import mpg
```

## Value boxes {height="25%"}

```{python}
#| label: calculate-values
lowest_mileage_index = mpg['cty'].idxmin()
lowest_mileage_car = mpg.iloc[lowest_mileage_index]
lowest_mileage_cty = mpg.loc[lowest_mileage_index, 'cty']

highest_mileage_index = mpg['cty'].idxmax()
highest_mileage_car = mpg.iloc[highest_mileage_index]
highest_mileage_cty = mpg.loc[highest_mileage_index, 'cty']

mean_city_mileage = mpg['cty'].mean()
rounded_mean_city_mileage = round(mean_city_mileage, 2)
```

```{python}
#| content: valuebox
#| title: "Least efficient"
#| icon: fuel-pump-fill
#| color: danger
dict(
  value = str(f"{lowest_mileage_cty} mpg")
)
```

```{python}
#| content: valuebox
#| title: "Most efficient"
dict(
  icon = "fuel-pump",
  color = "success",
  value = str(f"{highest_mileage_cty} mpg")
)
```

::: {.valuebox icon="fuel-pump" color="secondary"}
Average city mileage

`{r} rounded_mean_city_mileage` mpg
:::

## Plots {height="75%"}

```{python}
#| title: Highway vs. city mileage
(
    ggplot(mpg, aes(x = "cty", y = "hwy"))
    + geom_point()
)
```

```{python}
#| title: Drive types
(
    ggplot(mpg, aes(x = "drv"))
    + geom_bar()
)
```

Bootswatch themes

dashboard.qmd
---
title: "Bootswatch themes"
format: 
  dashboard:
    theme: quartz
---

```{python}
from plotnine import ggplot, aes, geom_point, geom_bar
from plotnine.data import mpg
```

## Value boxes {height="25%"}

```{python}
#| label: calculate-values
lowest_mileage_index = mpg['cty'].idxmin()
lowest_mileage_car = mpg.iloc[lowest_mileage_index]
lowest_mileage_cty = mpg.loc[lowest_mileage_index, 'cty']

highest_mileage_index = mpg['cty'].idxmax()
highest_mileage_car = mpg.iloc[highest_mileage_index]
highest_mileage_cty = mpg.loc[highest_mileage_index, 'cty']

mean_city_mileage = mpg['cty'].mean()
rounded_mean_city_mileage = round(mean_city_mileage, 2)
```

```{python}
#| content: valuebox
#| title: "Least efficient"
#| icon: fuel-pump-fill
#| color: danger
dict(
  value = str(f"{lowest_mileage_cty} mpg")
)
```

```{python}
#| content: valuebox
#| title: "Most efficient"
dict(
  icon = "fuel-pump",
  color = "success",
  value = str(f"{highest_mileage_cty} mpg")
)
```

::: {.valuebox icon="fuel-pump" color="secondary"}
Average city mileage

`{r} rounded_mean_city_mileage` mpg
:::

## Plots {height="75%"}

```{python}
#| title: Highway vs. city mileage
(
    ggplot(mpg, aes(x = "cty", y = "hwy"))
    + geom_point()
)
```

```{python}
#| title: Drive types
(
    ggplot(mpg, aes(x = "drv"))
    + geom_bar()
)
```

Bootswatch themes

Custom themes

  • You can create an entirely custom theme and apply it to your dashboard:

    format:
      theme: style.scss
  • Or you can customize an existing Bootswatch theme:

    format:
      theme:
        - cosmo
        - custom.scss

Your turn

Goal

Your goal is to create a dashboard that looks like the following:

Step 1

  • Update the theme to the appropriate Bootswatch theme.
02:00

Learn more

Theming Quarto

A lot more to learn on theming all things Quarto!