Quarto dashboards


Leykun Getaneh (MSc)

NDMC, EPHI

February 17 - 20, 2026

Quarto dashboards

  • An output format for creating dashboards from notebooks
  • Publish groups of visualizations, tables, text together
  • Released in Quarto 1.4

Tip

Run this command in your terminal to see what version of Quarto you are on:

Terminal
quarto --version

Cards

Dashboards are composed of cards.

Rows and columns

Cards are arranged into rows and columns.

Layouts

Pages, tabsets, and sidebars allow for more advanced layouts.

Start from Scratch

Begin with front matter:

dashboard.qmd
---
title: "My first Quarto dashboard"
format: dashboard
---

Start from Scratch

Add a card:

dashboard.qmd
---
title: "My first Quarto dashboard"
format: dashboard
---

```{r}
library(tidyverse)
yrbss_complete <- read_csv("data/yrbss_complete.csv") 
```

```{r}
ggplot(yrbss_complete, aes(x = bmi, y = stweight)) +
  geom_point(alpha = 0.6) +
  theme_bw()
```

Start from Scratch

Add a card:

dashboard.qmd
---
title: "My first Quarto dashboard"
format: dashboard
---

```{r}
ggplot(yrbss_complete, aes(x = bmi, y = stweight)) +
  geom_point(alpha = 0.6) +
  theme_bw()
```

Start from scratch

Continue adding cards:

dashboard.qmd
---
title: "My first Quarto dashboard"
format: dashboard
---

```{r}
ggplot(yrbss_complete, aes(x = bmi, y = stweight)) +
  geom_point(alpha = 0.6) +
  theme_bw()
```

```{r}
ggplot(yrbss_complete, aes(x = sex)) +
  geom_bar(fill = "steelblue") +
  theme_classic()
```

Start from Scratch

Add a title to your cards:

dashboard.qmd
---
title: "My first Quarto dashboard"
format: dashboard
---

```{r}
#| title: "Plot 1"
ggplot(yrbss_complete, aes(x = bmi, y = stweight)) +
  geom_point(alpha = 0.6) +
  theme_bw()
```

```{r}
#| title: "Plot 2"
ggplot(yrbss_complete, aes(x = sex)) +
  geom_bar(fill = "steelblue") +
  theme_classic()
```

Rows

By default, cards are laid out in rows:

dashboard.qmd
---
title: "My first Quarto dashboard"
format: dashboard
---

```{r}
#| title: "Plot 1"
ggplot(yrbss_complete, aes(x = bmi, y = stweight)) +
  geom_point(alpha = 0.6) +
  theme_bw()
```

```{r}
#| title: "Plot 2"
ggplot(yrbss_complete, aes(x = sex)) +
  geom_bar(fill = "steelblue") +
  theme_classic()
```

Rows

By default, cards are laid out in rows:

dashboard.qmd
---
title: "My first Quarto dashboard"
format: 
  dashboard:
    orientation: rows
---

```{r}
#| title: "Plot 1"
ggplot(yrbss_complete, aes(x = bmi, y = stweight)) +
  geom_point(alpha = 0.6) +
  theme_bw()
```

```{r}
#| title: "Plot 2"
ggplot(yrbss_complete, aes(x = sex)) +
  geom_bar(fill = "steelblue") +
  theme_classic()
```

Columns

We can change it to be columns instead:

dashboard.qmd
---
title: "My first Quarto dashboard"
format: 
  dashboard:
    orientation: columns
---

```{r}
#| title: "Plot 1"
ggplot(yrbss_complete, aes(x = bmi, y = stweight)) +
  geom_point(alpha = 0.6) +
  theme_bw()
```

```{r}
#| title: "Plot 2"
ggplot(yrbss_complete, aes(x = sex)) +
  geom_bar(fill = "steelblue") +
  theme_classic()
```

Headings

Alternatively, we can use headings to arrange cards:

dashboard.qmd
---
title: "My first Quarto dashboard"
format: 
  dashboard:
    orientation: rows
---

## Row

```{r}
#| title: "Plot 1"
ggplot(yrbss_complete, aes(x = bmi, y = stweight)) +
  geom_point(alpha = 0.6) +
  theme_bw()
```

```{r}
#| title: "Plot 2"
ggplot(yrbss_complete, aes(x = sex)) +
  geom_bar(fill = "steelblue") +
  theme_classic()
```

Headings

Alternatively, we can use headings to arrange cards:

dashboard.qmd
---
title: "My first Quarto dashboard"
format: 
  dashboard:
    orientation: rows
---

## Row

```{r}
#| title: "Plot 1"
ggplot(yrbss_complete, aes(x = bmi, y = stweight)) +
  geom_point(alpha = 0.6) +
  theme_bw()
```

```{r}
#| title: "Plot 2"
ggplot(yrbss_complete, aes(x = sex)) +
  geom_bar(fill = "steelblue") +
  theme_classic()
```

Headings

Make another row with content:

dashboard.qmd
---
title: "My first Quarto dashboard"
format: 
  dashboard:
    orientation: rows
---

## Row

Here is my dashboard:

## Row

```{r}
#| title: "Plot 1"
ggplot(yrbss_complete, aes(x = bmi, y = stweight)) +
  geom_point(alpha = 0.6) +
  theme_bw()
```

```{r}
#| title: "Plot 2"
ggplot(yrbss_complete, aes(x = sex)) +
  geom_bar(fill = "steelblue") +
  theme_classic()
```

Headings

Continue adding content:

dashboard.qmd
---
title: "My first Quarto dashboard"
format: 
  dashboard:
    orientation: rows
---

## Row

Here is my dashboard:

## Row

```{r}
#| title: "Plot 1"
ggplot(yrbss_complete, aes(x = bmi, y = stweight)) +
  geom_point(alpha = 0.6) +
  theme_bw()
```

```{r}
#| title: "Plot 2"
ggplot(yrbss_complete, aes(x = sex)) +
  geom_bar(fill = "steelblue") +
  theme_classic()
```

```{r}
#| title: "Plot 3"
ggplot(yrbss_complete, aes(x = bmi)) +
  geom_histogram(fill = "steelblue", color = "white") +
  theme_classic()
```

Headings

We can add columns within our rows:

dashboard.qmd
---
title: "My first Quarto dashboard"
format: 
  dashboard:
    orientation: rows
---

## Row

Here is my dashboard:

## Row

### Column

```{r}
#| title: "Plot 1"
ggplot(yrbss_complete, aes(x = bmi, y = stweight)) +
  geom_point(alpha = 0.6) +
  theme_bw()
```

```{r}
#| title: "Plot 2"
ggplot(yrbss_complete, aes(x = sex)) +
  geom_bar(fill = "steelblue") +
  theme_classic()
```

### Column

```{r}
#| title: "Plot 3"
ggplot(yrbss_complete, aes(x = bmi)) +
  geom_histogram(fill = "steelblue", color = "white") +
  theme_classic()
```

Tabsets

Or use tabsets to put content in different tabs:

dashboard.qmd
---
title: "My first Quarto dashboard"
format: 
  dashboard:
    orientation: rows
---

## Row

Here is my dashboard:

## Row

### Column {.tabset}

```{r}
#| title: "Plot 1"
ggplot(yrbss_complete, aes(x = bmi, y = stweight)) +
  geom_point(alpha = 0.6) +
  theme_bw()
```

```{r}
#| title: "Plot 2"
ggplot(yrbss_complete, aes(x = sex)) +
  geom_bar(fill = "steelblue") +
  theme_classic()
```

### Column

```{r}
#| title: "Plot 3"
ggplot(yrbss_complete, aes(x = bmi)) +
  geom_histogram(fill = "steelblue", color = "white") +
  theme_classic()
```

Tabsets

Pages

Use a Level 1 heading to create new pages:

dashboard.qmd
---
title: "My first Quarto dashboard"
format: 
  dashboard:
    orientation: rows
---

## Row

Here is my dashboard:

# Page 1

```{r}
#| title: "Plot 1"
ggplot(yrbss_complete, aes(x = bmi, y = stweight)) +
  geom_point(alpha = 0.6) +
  theme_bw()
```

```{r}
#| title: "Plot 2"
ggplot(yrbss_complete, aes(x = sex)) +
  geom_bar(fill = "steelblue") +
  theme_classic()
```

# Page 2

```{r}
#| title: "Plot 3"
ggplot(yrbss_complete, aes(x = bmi)) +
  geom_histogram(fill = "steelblue", color = "white") +
  theme_classic()
```

Pages

Use a Level 1 heading to create new pages:

Text

Content that is included at the top of a dashboard is considered leading content, and will be included as is with no card styling:

dashboard.qmd
---
title: "My first Quarto dashboard"
format: dashboard
---

## Row

Here is my dashboard:

## Row

```{r}
#| title: "Plot 1"
ggplot(yrbss_complete, aes(x = bmi, y = stweight)) +
  geom_point(alpha = 0.6) +
  theme_bw()
```

```{r}
#| title: "Plot 2"
ggplot(yrbss_complete, aes(x = sex)) +
  geom_bar(fill = "steelblue") +
  theme_classic()
```

Plots

Size plots in static dashboards using code chunk options:

dashboard.qmd
---
title: "My first Quarto dashboard"
format: dashboard
---

## Row

```{r}
#| title: "Plot 1"
#| fig-width: 5
#| fig-height: 4
ggplot(yrbss_complete, aes(x = bmi, y = stweight)) +
  geom_point(alpha = 0.6) +
  theme_bw()
```

```{r}
#| title: "Plot 2"
ggplot(yrbss_complete, aes(x = sex)) +
  geom_bar(fill = "steelblue") +
  theme_classic()
```

Value Boxes

Value boxes display simple values within a dashboard:

dashboard.qmd
---
title: "My first Quarto dashboard"
format: dashboard
---

```{r}
#| context: setup
library(tidyverse)
yrbss_complete <- read_csv("data/yrbss_complete.csv")
```

## Row

::: {.valuebox color="#ADD8E6"}
Last updated:

`{{r}} Sys.Date()`
:::

```{r}
#| content: valuebox
#| title: "Number of students"
n <- yrbss_complete |> count() |> pull(n)

list(
  color = "#ADD8E6",
  value = n
)
```

## Row

```{r}
#| title: "Plot 2"
ggplot(yrbss_complete, aes(x = sex)) +
  geom_bar(fill = "steelblue") +
  theme_classic()
```

Value Boxes

dashboard.qmd
---
title: "My first Quarto dashboard"
format: dashboard
---

```{r}
#| context: setup
library(tidyverse)
yrbss_complete <- read_csv("data/yrbss_complete.csv")
```

## Row

::: {.valuebox color="#ADD8E6"}
Last updated:

`{{r}} Sys.Date()`
:::

```{r}
#| content: valuebox
#| title: "Number of students"
n <- yrbss_complete |> count() |> pull(n)

list(
  color = "#ADD8E6",
  value = n
)
```

## Row

```{r}
#| title: "Plot 2"
ggplot(yrbss_complete, aes(x = sex)) +
  geom_bar(fill = "steelblue") +
  theme_classic()
```

Value Boxes

Input Layout

There are several ways to layout inputs within interactive dashboards:

  • Sidebars provide a collapsible vertical panel for inputs.

  • Toolbars provide a horizontal panel for inputs.

  • Card Inputs provide a panel for card-specific inputs.

Input Layout

There are several ways to layout inputs within interactive dashboards:

  • Sidebars provide a collapsible vertical panel for inputs.

  • Toolbars provide a horizontal panel for inputs.

  • Card Inputs provide a panel for card-specific inputs.

Exercise

  • Create a simple dashboard of monthly measles case data for Ethiopia from 2012 to 2024, highlighting temporal trends and yearly patterns in the disease cases.