Content Collections: Deep Dive
content-collections.RmdThis vignette goes deep into content collections - the first layer of
dashboardrβs architecture. For a quick overview, see
vignette("getting-started").
Throughout this vignette, we use the General Social Survey as example data. Click below to see the data loading code.
π Data Setup (click to expand)
library(dashboardr)
library(dplyr)
library(gssr)
library(haven)
# Load GSS data
data(gss_all)
# Latest wave only (for most examples)
gss <- gss_all %>%
select(year, age, sex, race, degree, happy, polviews, wtssps,
# Continuous variables for scatter plots
educ, childs,
# Confidence in institutions (for multi-question stackedbar example)
confinan, conbus, coneduc, confed, conmedic) %>%
filter(year == max(year, na.rm = TRUE)) %>%
# Filter to substantive responses for core variables
filter(
happy %in% 1:3, # very happy, pretty happy, not too happy
polviews %in% 1:7, # extremely liberal to extremely conservative
!is.na(age), !is.na(sex), !is.na(race), !is.na(degree)
) %>%
# Convert to factors with proper labels
mutate(
happy = droplevels(as_factor(happy)),
polviews = droplevels(as_factor(polviews)),
degree = droplevels(as_factor(degree)),
sex = droplevels(as_factor(sex)),
race = droplevels(as_factor(race)),
# Confidence variables: convert non-substantive (IAP, don't know, etc.) to NA
# Then use drop_na_vars = TRUE in visualizations
confinan = ifelse(confinan %in% 1:3, confinan, NA),
conbus = ifelse(conbus %in% 1:3, conbus, NA),
coneduc = ifelse(coneduc %in% 1:3, coneduc, NA),
confed = ifelse(confed %in% 1:3, confed, NA),
conmedic = ifelse(conmedic %in% 1:3, conmedic, NA),
# Convert to labeled factors
confinan = factor(confinan, levels = 1:3, labels = c("a great deal", "only some", "hardly any")),
conbus = factor(conbus, levels = 1:3, labels = c("a great deal", "only some", "hardly any")),
coneduc = factor(coneduc, levels = 1:3, labels = c("a great deal", "only some", "hardly any")),
confed = factor(confed, levels = 1:3, labels = c("a great deal", "only some", "hardly any")),
conmedic = factor(conmedic, levels = 1:3, labels = c("a great deal", "only some", "hardly any"))
)
# Full time series (for timeline examples)
gss_timeline <- gss_all %>%
select(year, happy) %>%
filter(happy %in% 1:3, !is.na(year)) %>%
mutate(happy = droplevels(as_factor(happy)))π¦ What Content Collections Store
A content collection is a container that holds visualizations, content blocks, interactive inputs, and layout helpers. Hereβs what you can add:
| Category | Types | Functions |
|---|---|---|
| Visualizations | Bar, Stacked Bar, Histogram, Density, Boxplot, Timeline, Heatmap, Scatter, Treemap, Map |
add_viz(), add_vizzes()
|
| Content Blocks | Text, Callouts, Cards, Accordions, Quotes, Badges, Metrics, Value Boxes, Code, Images, Videos, iframes, HTML |
add_text(), add_callout(),
add_card(), add_accordion(),
add_quote(), add_badge(),
add_metric(), add_value_box(),
add_code(), add_image(),
add_html()
|
| Tables & Custom Charts | gt Tables, Reactable, DT DataTables, Basic Tables, Custom Highcharter Charts |
add_gt(), add_reactable(),
add_DT(), add_table(), add_hc()
|
| Interactive Inputs (see Advanced Features) | Dropdowns, Checkboxes, Sliders, Radio buttons |
add_input_row(), add_input()
|
| Layout Helpers | Dividers, Spacers, Pagination markers |
add_divider(), add_spacer(),
add_pagination()
|
Everything is stored in a unified items list, and you
can inspect it anytime:
content <- create_content(data = gss, type = "bar") %>%
add_viz(x_var = "degree", title = "Education") %>%
add_text("## Analysis", "", "Key findings:") %>%
add_callout(paste0("Sample size: ", nrow(gss)), type = "note")
print(content)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 3 items | β data: 2997 rows x 15 cols
#>
#> β’ [Viz] Education (bar) x=degree
#> βΉ [Text]
#> β [Callout]
preview(content)Key findings:
Sample size: 2997
βοΈ The Defaults System
The defaults system lets you set once, use many
times. Instead of repeating the same parameters for every
visualization, you define them once in create_content() and
they automatically apply to all add_viz() calls.
Why Use Defaults?
Without defaults, youβd need to repeat parameters for every chart:
# Repetitive - don't do this!
content %>%
add_viz(x_var = "age", type = "bar", color_palette = c("#3498DB"), bar_type = "percent") %>%
add_viz(x_var = "sex", type = "bar", color_palette = c("#3498DB"), bar_type = "percent") %>%
add_viz(x_var = "race", type = "bar", color_palette = c("#3498DB"), bar_type = "percent")With defaults, you set them once and they flow through:
Override Hierarchy
Parameters are resolved in this order (later wins):
-
Collection defaults - set in
create_content() -
Individual viz settings - set in
add_viz()
This means you can set sensible defaults for most charts, then override specific ones as needed:
# Default: horizontal percent bars in blue
content <- create_content(
data = gss,
type = "bar",
bar_type = "percent",
horizontal = TRUE,
color_palette = c("#3498DB")
) %>%
# Uses all defaults
add_viz(x_var = "degree", title = "Education") %>%
# Override: vertical instead of horizontal
add_viz(x_var = "race", title = "Race (vertical)", horizontal = FALSE) %>%
# Override: count instead of percent
add_viz(x_var = "sex", title = "Sex (count)", bar_type = "count")
print(content)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 3 items | β data: 2997 rows x 15 cols
#>
#> β’ [Viz] Education (bar) x=degree
#> β’ [Viz] Race (vertical) (bar) x=race
#> β’ [Viz] Sex (count) (bar) x=sexAny Parameter Can Be a Default
Any parameter you can pass to add_viz()
can be set as a default in create_content(). Common ones
include:
| Parameter | Description | Example Values |
|---|---|---|
type |
Visualization type |
"bar", "histogram",
"stackedbar", "timeline"
|
color_palette |
Colors for charts | c("#3498DB", "#E74C3C") |
bar_type |
Bar chart display |
"count", "percent",
"mean"
|
horizontal |
Flip chart orientation |
TRUE, FALSE
|
weight_var |
Survey weight column | "wtssps" |
drop_na_vars |
Remove NA values |
TRUE, FALSE
|
stacked_type |
Stacked bar display |
"count", "percent"
|
bins |
Histogram bins |
20, 30, 50
|
x_label |
Custom x-axis label | "Age (years)" |
y_label |
Custom y-axis label | "Number of Respondents" |
tooltip_suffix |
Text after tooltip values |
"%", " people"
|
error_bars |
Error bar type (for bar_type = "mean") |
"none", "sd", "se",
"ci"
|
value_var |
Numeric variable for means |
"score", "income"
|
See the Visualization Types section for all parameters available for each chart type.
π·οΈ Custom Labels and Tooltips
Every visualization supports custom axis labels and tooltip formatting. These help make your charts clearer and more professional.
Axis Labels
By default, dashboardr uses your variable names as axis
labels. Override them with x_label and
y_label:
# Without custom labels (uses variable names)
create_content(data = gss, type = "bar") %>%
add_viz(x_var = "degree", title = "Education Levels") %>%
preview()
# With custom labels (more polished)
create_content(data = gss, type = "bar") %>%
add_viz(
x_var = "degree",
title = "Education Levels",
x_label = "Highest Degree Earned",
y_label = "Number of Respondents"
) %>%
preview()For stacked charts, you can also set stack_label to
customize the legend title:
create_content(data = gss, type = "stackedbar") %>%
add_viz(
x_var = "degree",
stack_var = "sex",
title = "Education by Gender",
x_label = "Highest Degree",
y_label = "Count",
stack_label = "Gender"
) %>%
preview()Tooltip Customization
Tooltips are the interactive popups that appear when users hover over data points. Customize them with prefix and suffix options:
| Parameter | Description | Example |
|---|---|---|
tooltip_prefix |
Text before the value |
"Count: ", "$"
|
tooltip_suffix |
Text after the value |
"%", " respondents"
|
x_tooltip_suffix |
Text after x-axis value |
" years", " USD"
|
# Add units to tooltips
create_content(data = gss, type = "histogram") %>%
add_viz(
x_var = "age",
title = "Age Distribution",
x_label = "Age",
y_label = "Count",
tooltip_suffix = " respondents",
x_tooltip_suffix = " years old"
) %>%
preview()
# Percentage tooltips for stacked bars
create_content(data = gss, type = "stackedbar") %>%
add_viz(
x_var = "happy",
stack_var = "sex",
title = "Happiness by Gender",
stacked_type = "percent",
y_label = "Percentage",
tooltip_suffix = "%"
) %>%
preview()Tip: Labels and tooltip settings can also be set as
collection defaults in create_content(), so they apply to
all visualizations:
# Set tooltip suffix as a default for all charts
create_content(
data = gss,
type = "bar",
bar_type = "percent",
tooltip_suffix = "%",
y_label = "Percentage"
) %>%
add_viz(x_var = "degree", title = "Education") %>%
add_viz(x_var = "race", title = "Race") %>%
preview()β Combining Collections
The + Operator
Merge collections while preserving structure:
demographics <- create_content(data = gss, type = "bar") %>%
add_viz(x_var = "degree", title = "Education", tabgroup = "Demo")
attitudes <- create_content(data = gss, type = "bar") %>%
add_viz(x_var = "happy", title = "Happiness", tabgroup = "Attitudes")
combined <- demographics + attitudes
print(combined)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 2 items | β data: 2997 rows x 15 cols
#>
#> β― [Tab] Demo (1 viz)
#> β’ [Viz] Education (bar) x=degree
#> β― [Tab] Attitudes (1 viz)
#> β’ [Viz] Happiness (bar) x=happycombine_viz()
Same as + but in pipe-friendly form:
all_content <- demographics %>%
combine_viz(attitudes)
print(all_content)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 2 items | β data: 2997 rows x 15 cols
#>
#> β― [Tab] Demo (1 viz)
#> β’ [Viz] Education (bar) x=degree
#> β― [Tab] Attitudes (1 viz)
#> β’ [Viz] Happiness (bar) x=happyπ Visualization Types
dashboardr supports 11 visualization types. Each is optimized for different data patterns. For detailed documentation on each type, see the individual vignettes: - Bar Charts | Stacked Bars - Histograms | Density Plots | Box Plots - Timelines | Heatmaps | Scatter Plots - Treemaps | Maps
Bar Charts
Bar charts are the workhorse of categorical data. Use them when you want to compare counts or proportions across categories.
The simplest bar chart counts occurrences of each category:
create_content(data = gss, type = "bar") %>%
add_viz(x_var = "degree", title = "Education Levels") %>%
preview()Often youβll want percentages instead of raw counts. Set
bar_type = "percent" to show proportions that sum to
100%:
create_content(data = gss, type = "bar") %>%
add_viz(x_var = "race", title = "Race Distribution", bar_type = "percent") %>%
preview()To compare categories across groups, add group_var. This
creates side-by-side bars:
create_content(data = gss, type = "bar") %>%
add_viz(x_var = "degree", group_var = "sex", title = "Education by Sex") %>%
preview()For long category labels, flip to horizontal with
horizontal = TRUE:
create_content(data = gss, type = "bar") %>%
add_viz(x_var = "degree", title = "Education (Horizontal)", horizontal = TRUE) %>%
preview()Means with Error Bars
For numeric outcomes, use bar_type = "mean" with
error_bars to show statistical uncertainty:
# Sample data with numeric scores
score_data <- data.frame(
group = rep(c("Control", "Treatment"), each = 50),
score = c(rnorm(50, 70, 10), rnorm(50, 78, 12))
)
create_content(data = score_data, type = "bar") %>%
add_viz(
x_var = "group",
value_var = "score",
bar_type = "mean",
error_bars = "ci", # "sd", "se", or "ci"
title = "Mean Scores (95% CI)"
) %>%
preview()| Error Type | Parameter | Shows |
|---|---|---|
| Standard Deviation | error_bars = "sd" |
Spread of individual values |
| Standard Error | error_bars = "se" |
Precision of mean estimate |
| Confidence Interval | error_bars = "ci" |
Range likely to contain true mean |
See the Bar Chart vignette for more options including grouped means and error bar styling.
Stacked Bars
Stacked bars show composition - how a whole breaks down into parts.
Use stack_var to specify what fills each bar.
This shows the happiness distribution within each education level as raw counts:
create_content(data = gss, type = "stackedbar") %>%
add_viz(x_var = "degree", stack_var = "happy", title = "Happiness by Education") %>%
preview()For easier comparison across groups of different sizes, use
stacked_type = "percent". Now each bar sums to 100%, making
patterns clearer:
create_content(data = gss, type = "stackedbar") %>%
add_viz(x_var = "degree", stack_var = "happy", title = "Happiness by Education (%)",
stacked_type = "percent") %>%
preview()Horizontal stacked bars work well when you have many categories or long labels:
create_content(data = gss, type = "stackedbar") %>%
add_viz(x_var = "degree", stack_var = "happy", title = "Horizontal Stacked",
stacked_type = "percent", horizontal = TRUE) %>%
preview()See the Stacked Bar vignette for more options.
Histograms
Histograms show the distribution of continuous variables. The
bins parameter controls granularity - more bins show more
detail, fewer bins show smoother patterns.
create_content(data = gss, type = "histogram") %>%
add_viz(x_var = "age", title = "Age Distribution", bins = 25,
x_label = "Age (years)", y_label = "Frequency") %>%
preview()See the Histogram vignette for more options.
Density Plots
Density plots show smooth estimates of the distribution of a continuous variable. Theyβre useful when you want a cleaner view of the distribution shape compared to histograms.
create_content(data = gss, type = "density") %>%
add_viz(x_var = "age", title = "Age Distribution (Density)",
x_label = "Age (years)") %>%
preview()Add group_var to compare distributions across
groups:
create_content(data = gss, type = "density") %>%
add_viz(x_var = "age", group_var = "sex",
title = "Age Distribution by Sex") %>%
preview()See the Density vignette for more options.
Box Plots
Box plots (also called box-and-whisker plots) show the distribution of a numeric variable across categories. They display the median, quartiles, and outliers, making it easy to compare distributions.
create_content(data = gss, type = "boxplot") %>%
add_viz(x_var = "degree", y_var = "age",
title = "Age Distribution by Education Level",
x_label = "Highest Degree", y_label = "Age") %>%
preview()See the Box Plot vignette for more options.
Multiple Stacked Bars (Likert Scales)
When you have multiple survey questions with the same response scale
(like Likert items), use type = "stackedbar" with
x_vars to display them together for comparison. This is
perfect for βconfidence in institutionsβ batteries or agreement
scales.
Use x_vars for the question columns and
x_var_labels for readable labels. Note: These confidence
questions use a split-ballot design, so ~1/3 of respondents have NA
(question not asked). We use drop_na_vars = TRUE to exclude
those:
create_content(data = gss, type = "stackedbar", drop_na_vars = TRUE) %>%
add_viz(
x_vars = c("confinan", "conbus", "coneduc", "confed", "conmedic"),
x_var_labels = c("Banks & financial institutions",
"Major companies",
"Education",
"Federal government",
"Medicine"),
title = "Confidence in Institutions",
stacked_type = "percent",
horizontal = TRUE
) %>%
preview()See the Stacked Bar vignette for more options including multi-question mode.
Timeline
Timeline charts track how responses change over time. You need a time
variable (time_var) and a response variable
(y_var). Unlike other chart types, timelines need data
spanning multiple time periods.
create_content(data = gss_timeline, type = "timeline") %>%
add_viz(
time_var = "year",
y_var = "happy",
title = "Happiness Over Time",
chart_type = "line"
) %>%
preview()Use chart_type = "stacked_area" for a stacked area
chart, which emphasizes cumulative patterns:
create_content(data = gss_timeline, type = "timeline") %>%
add_viz(
time_var = "year",
y_var = "happy",
title = "Happiness Trends (Stacked Area)",
chart_type = "stacked_area"
) %>%
preview()See the Timeline vignette for more options.
Heatmap
Heatmaps visualize how a numeric value varies across two categorical dimensions, displayed as a color-coded grid. Each cell shows the aggregated value for that combination of categories.
Required parameters:
| Parameter | Description |
|---|---|
x_var |
Categorical variable for columns |
y_var |
Categorical variable for rows |
value_var |
Numeric variable to aggregate and color by |
How it works: The heatmap automatically aggregates
value_var for each unique combination of x_var
and y_var. By default, it calculates the
mean - so if you have 50 people with a bachelorβs degree who
are βvery happyβ, the cell shows their average age.
create_content(data = gss, type = "heatmap") %>%
add_viz(
x_var = "degree",
y_var = "happy",
value_var = "age",
title = "Average Age by Education & Happiness"
) %>%
preview()Key optional parameters:
| Parameter | Description | Default |
|---|---|---|
agg_fun |
Aggregation function | mean |
color_palette |
Two colors for gradient (low, high) | c("#FFFFFF", "#7CB5EC") |
color_min / color_max
|
Fixed color scale bounds | Auto from data |
x_order / y_order
|
Custom category ordering | Auto |
data_labels_enabled |
Show values in cells | TRUE |
weight_var |
Column for weighted aggregation | NULL |
Change the aggregation function with
agg_fun. Use any R function that takes a vector and returns
a single value:
# Median instead of mean
create_content(data = gss, type = "heatmap") %>%
add_viz(
x_var = "degree",
y_var = "happy",
value_var = "age",
agg_fun = median,
title = "Median Age by Education & Happiness"
) %>%
preview()Customize the color gradient with
color_palette - provide low and high colors:
create_content(data = gss, type = "heatmap") %>%
add_viz(
x_var = "degree",
y_var = "happy",
value_var = "age",
title = "Custom Colors (Red gradient)",
color_palette = c("#FFF5F0", "#67000D")
) %>%
preview()Use survey weights for proper weighted means:
create_content(data = gss, type = "heatmap") %>%
add_viz(
x_var = "degree",
y_var = "happy",
value_var = "age",
weight_var = "wtssps",
title = "Weighted Average Age"
) %>%
preview()See the Heatmap vignette for more options.
Scatter Plots
Scatter plots show relationships between two numeric variables. Each point represents one observation. Key parameters:
-
x_var- Variable for horizontal axis -
y_var- Variable for vertical axis
-
color_var- Optional grouping variable for colored points -
size_var- Optional variable to control point sizes -
show_trend- Add a trend line (TRUE/FALSE) -
alpha- Point transparency (0-1)
# Filter to respondents with valid education and children data
scatter_data <- gss %>%
filter(!is.na(educ), !is.na(childs))
create_content(data = scatter_data, type = "scatter") %>%
add_viz(
x_var = "educ",
y_var = "childs",
color_var = "sex",
title = "Education vs Number of Children",
x_label = "Years of Education",
y_label = "Number of Children",
alpha = 0.4
) %>%
preview()See the Scatter Plot vignette for more options.
Treemap
Treemaps display hierarchical data as nested rectangles. The size of each rectangle represents its value - larger rectangles mean larger values. Great for showing composition and proportions across many categories.
Important: Treemaps require pre-aggregated data with
a value column. You typically need to count() or
summarize() your data first.
Key parameters:
-
group_var- Primary grouping variable (creates the rectangles) -
subgroup_var- Optional secondary grouping for hierarchical treemaps -
value_var- Numeric column that determines rectangle size -
color_var- Optional variable for coloring (defaults to group_var)
# Treemaps need pre-aggregated data
degree_counts <- gss %>%
count(degree, name = "n")
create_content(data = degree_counts, type = "treemap") %>%
add_viz(
group_var = "degree",
value_var = "n",
title = "Education Distribution"
) %>%
preview()For hierarchical treemaps, add subgroup_var:
# Two-level hierarchy: degree within sex
degree_sex_counts <- gss %>%
count(sex, degree, name = "n")
create_content(data = degree_sex_counts, type = "treemap") %>%
add_viz(
group_var = "sex",
subgroup_var = "degree",
value_var = "n",
title = "Education by Sex"
) %>%
preview()See the Treemap vignette for more options.
Map
Geographic maps (choropleths) display data across regions using color intensity. Each region is shaded based on a numeric value, making it easy to see geographic patterns at a glance.
Key parameters:
| Parameter | Description |
|---|---|
value_var |
Numeric column for color intensity |
join_var |
Column with geographic codes (must match mapβs internal codes) |
map_type |
Map geography: "custom/world",
"countries/us/us-all", etc. |
color_palette |
Two colors for gradient (low, high) |
tooltip_vars |
Variables to show in hover tooltips |
Important: Maps require geographic identifier codes that match the mapβs internal region codes:
-
World maps: Use 2-letter ISO country codes
(
iso2c): βUSβ, βDEβ, βFRβ, etc. - US state maps: Use postal codes: βCAβ, βNYβ, βTXβ, etc.
# Load gapminder data and add ISO country codes
library(gapminder)
library(countrycode)
# Get latest year and convert country names to ISO codes
map_data <- gapminder %>%
filter(year == max(year)) %>%
mutate(iso2c = countrycode(country, "country.name", "iso2c")) %>%
filter(!is.na(iso2c))Now create a world map showing life expectancy:
create_content(data = map_data, type = "map") %>%
add_viz(
value_var = "lifeExp",
join_var = "iso2c",
map_type = "custom/world",
title = "Life Expectancy by Country (2007)",
color_palette = c("#fee5d9", "#a50f15")
) %>%
preview()Custom color palettes - use any two colors for the gradient:
create_content(data = map_data, type = "map") %>%
add_viz(
value_var = "gdpPercap",
join_var = "iso2c",
map_type = "custom/world",
title = "GDP per Capita",
color_palette = c("#f7fbff", "#08306b") # Light to dark blue
) %>%
preview()Available map types:
| Map Type | Region | Join Key |
|---|---|---|
"custom/world" |
World countries |
iso2c (2-letter ISO) |
"custom/world-highres" |
World (high resolution) | iso2c |
"countries/us/us-all" |
US states | Postal codes (βCAβ, βNYβ) |
"countries/de/de-all" |
German states | State codes |
"custom/europe" |
European countries | iso2c |
See the Map vignette for more options.
π Organizing with Tabgroups
Tabgroups create tabbed interfaces in your dashboard:
content <- create_content(data = gss, type = "bar") %>%
add_viz(x_var = "degree", title = "Education", tabgroup = "demographics") %>%
add_viz(x_var = "race", title = "Race", tabgroup = "demographics") %>%
add_viz(x_var = "happy", title = "Happiness", tabgroup = "attitudes") %>%
add_viz(x_var = "polviews", title = "Politics", tabgroup = "attitudes")
print(content)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 4 items | β data: 2997 rows x 15 cols
#>
#> β― [Tab] demographics (2 vizs)
#> β’ [Viz] Education (bar) x=degree
#> β’ [Viz] Race (bar) x=race
#> β― [Tab] attitudes (2 vizs)
#> β’ [Viz] Happiness (bar) x=happy
#> β’ [Viz] Politics (bar) x=polviewsNested Tabgroups
For complex dashboards, you can create multi-level tab
hierarchies using / as a separator:
nested <- create_content(data = gss, type = "bar") %>%
# Top-level: "Demographics" with two sub-tabs
add_viz(x_var = "degree", title = "Education Level",
tabgroup = "Demographics/Education") %>%
add_viz(x_var = "race", title = "Race Distribution",
tabgroup = "Demographics/Race") %>%
add_viz(x_var = "age", title = "Age Distribution",
tabgroup = "Demographics/Age") %>%
# Top-level: "Attitudes" with sub-tabs
add_viz(x_var = "happy", title = "General Happiness",
tabgroup = "Attitudes/Wellbeing") %>%
add_viz(x_var = "polviews", title = "Political Views",
tabgroup = "Attitudes/Politics")
print(nested)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 5 items | β data: 2997 rows x 15 cols
#>
#> β― [Tab] Demographics (3 tabs)
#> β― [Tab] Education (1 viz)
#> β’ [Viz] Education Level (bar) x=degree
#> β― [Tab] Race (1 viz)
#> β’ [Viz] Race Distribution (bar) x=race
#> β― [Tab] Age (1 viz)
#> β’ [Viz] Age Distribution (bar) x=age
#> β― [Tab] Attitudes (2 tabs)
#> β― [Tab] Wellbeing (1 viz)
#> β’ [Viz] General Happiness (bar) x=happy
#> β― [Tab] Politics (1 viz)
#> β’ [Viz] Political Views (bar) x=polviews
preview(nested)Custom Tab Labels
Replace tabgroup IDs with readable labels using
set_tabgroup_labels():
labeled <- create_content(data = gss, type = "bar") %>%
add_viz(x_var = "degree", title = "Education", tabgroup = "demo") %>%
add_viz(x_var = "happy", title = "Happiness", tabgroup = "attitudes") %>%
set_tabgroup_labels(
demo = "Demographics",
attitudes = "Attitudes & Values"
)
print(labeled)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 2 items | β data: 2997 rows x 15 cols
#>
#> β― [Tab] demo (1 viz)
#> β’ [Viz] Education (bar) x=degree
#> β― [Tab] attitudes (1 viz)
#> β’ [Viz] Happiness (bar) x=happyπ Content Blocks
Content blocks add non-visualization elements to your collections.
Text Blocks
add_text() is a flexible function for adding markdown
content. It has several smart features:
Multiple arguments become lines - Pass as many strings as you want, and they join with newlines:
create_content() %>%
add_text(
"## Survey Overview",
"",
"The General Social Survey (GSS) has been conducted since 1972.",
"It covers demographics, attitudes, and social behaviors."
) %>%
preview()The General Social Survey (GSS) has been conducted since 1972. It covers demographics, attitudes, and social behaviors.
Use empty strings for spacing - An empty
"" creates a paragraph break:
create_content() %>%
add_text(
"## Section One",
"",
"First paragraph of content.",
"",
"## Section Two",
"",
"Second paragraph with a gap above."
) %>%
preview()First paragraph of content.
Second paragraph with a gap above.
Full Markdown support - Headers, lists, bold, italic, links, and more:
text_example <- create_content() %>%
add_text(
"## Key Findings",
"",
"This analysis reveals **three important patterns**:",
"",
"1. Education correlates with happiness",
"2. Age distribution is *roughly normal*",
"3. Political views show [polarization](https://en.wikipedia.org/wiki/Political_polarization)",
"",
"### Methodology Note",
"",
"> Data weighted using GSS survey weights"
)
print(text_example)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 1 items | β no data
#>
#> βΉ [Text]This analysis reveals three important patterns:
- Education correlates with happiness
- Age distribution is roughly normal
- Political views show polarization
Data weighted using GSS survey weights
Works standalone or in pipes - Call it directly or chain it:
Callouts
Callouts draw attention to specific information with colored boxes and icons. Use them to highlight notes, tips, warnings, or critical information that readers shouldnβt miss.
Five types for different purposes:
| Type | Use for | Color |
|---|---|---|
note |
Additional context, background info | Blue |
tip |
Helpful suggestions, best practices | Green |
warning |
Potential issues, things to watch out for | Yellow |
caution |
Proceed carefully, possible problems | Orange |
important |
Critical information, must-read | Red |
callout_gallery <- create_content() %>%
add_callout("Notes provide additional context or information.", type = "note", title = "Note") %>%
add_callout("Tips offer helpful suggestions to improve workflow.", type = "tip", title = "Pro Tip") %>%
add_callout("Warnings alert users to potential issues.", type = "warning", title = "Warning") %>%
add_callout("Caution indicates something that needs careful attention.", type = "caution", title = "Caution") %>%
add_callout("Important highlights critical information.", type = "important", title = "Important")
print(callout_gallery)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 5 items | β no data
#>
#> β [Callout] Note
#> β [Callout] Pro Tip
#> β [Callout] Warning
#> β [Callout] Caution
#> β [Callout] ImportantNotes provide additional context or information.
Tips offer helpful suggestions to improve workflow.
Warnings alert users to potential issues.
Caution indicates something that needs careful attention.
Important highlights critical information.
Custom titles are optional - If you omit
title, the type name is used:
create_content() %>%
add_callout("Sample size is smaller than recommended for this analysis.", type = "warning") %>%
preview()Sample size is smaller than recommended for this analysis.
Practical example - Combine callouts with visualizations:
create_content(data = gss, type = "bar") %>%
add_callout("This chart shows unweighted counts. See methodology for weighted estimates.", type = "note") %>%
add_viz(x_var = "degree", title = "Education Distribution") %>%
add_callout("Education data may reflect selection bias in survey response rates.", type = "tip", title = "Interpretation Tip") %>%
preview()This chart shows unweighted counts. See methodology for weighted estimates.
Education data may reflect selection bias in survey response rates.
Cards
Styled content containers with optional titles:
card_example <- create_content() %>%
add_card(
title = "Key Finding",
text = "Education level shows a strong positive correlation with reported happiness levels across all demographic groups."
) %>%
add_card(
text = "Cards without titles work too. Great for quick content blocks."
)
print(card_example)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 2 items | β no data
#>
#> βΌ [Card] Key Finding
#> βΌ [Card]Education level shows a strong positive correlation with reported happiness levels across all demographic groups.
Cards without titles work too. Great for quick content blocks.
Accordions
Collapsible sections for supplementary or detailed content:
accordion_example <- create_content() %>%
add_accordion(
title = "Click to expand: Methodology",
text = "This analysis uses weighted survey data from NORC. Sample size: 21,788 respondents."
) %>%
add_accordion(
title = "Click to expand: Data Sources",
text = "General Social Survey (GSS), collected annually since 1972."
)
print(accordion_example)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 2 items | β no data
#>
#> β° [Accordion] Click to expand: Methodology
#> β° [Accordion] Click to expand: Data SourcesClick to expand: Methodology
This analysis uses weighted survey data from NORC. Sample size: 21,788 respondents.
Click to expand: Data Sources
General Social Survey (GSS), collected annually since 1972.
Quotes
Block quotes with optional attribution:
quote_example <- create_content() %>%
add_quote(
quote = "The only true wisdom is in knowing you know nothing.",
attribution = "Socrates"
)
print(quote_example)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 1 items | β no data
#>
#> β’ [quote]The only true wisdom is in knowing you know nothing.
Badges
Inline status indicators:
badge_example <- create_content() %>%
add_text("Status indicators:") %>%
add_badge("Complete", color = "success") %>%
add_badge("In Progress", color = "warning") %>%
add_badge("Not Started", color = "danger") %>%
add_badge("Info", color = "info") %>%
add_badge("Primary", color = "primary") %>%
add_badge("Secondary", color = "secondary")
print(badge_example)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 7 items | β no data
#>
#> βΉ [Text]
#> β’ [badge]
#> β’ [badge]
#> β’ [badge]
#> β’ [badge]
#> β’ [badge]
#> β’ [badge]Status indicators:
Metrics
Single KPI value boxes:
metric_example <- create_content() %>%
add_metric(
title = "Total Respondents",
value = "21,788",
icon = "ph:users"
)
print(metric_example)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 1 items | β no data
#>
#> β’ [metric] Total RespondentsValue Boxes
Custom-styled value boxes with branding:
value_box_example <- create_content() %>%
add_value_box(
title = "Revenue",
value = "$1.2M",
bg_color = "#27AE60"
)
print(value_box_example)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 1 items | β no data
#>
#> β’ [value_box] RevenueValue Box Rows
Multiple value boxes in a responsive row:
value_row_example <- create_content() %>%
add_value_box_row() %>%
add_value_box(title = "Users", value = "12,345", bg_color = "#3498DB") %>%
add_value_box(title = "Sessions", value = "45,678", bg_color = "#9B59B6") %>%
add_value_box(title = "Conversion", value = "3.2%", bg_color = "#E74C3C") %>%
end_value_box_row()
print(value_row_example)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 1 items | β no data
#>
#> β’ [value_box_row]Code Blocks
Syntax-highlighted code snippets:
code_example <- create_content() %>%
add_code(
code = "library(dashboardr)\n\ncreate_content(data = df) %>%\n add_viz(type = 'bar', x_var = 'category')",
language = "r"
)
print(code_example)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 1 items | β no data
#>
#> β’ [Code]
library(dashboardr)
create_content(data = df) %>%
add_viz(type = 'bar', x_var = 'category')
Images
Add images with optional captions. Use full URLs for images to ensure they display on GitHub Pages:
image_example <- create_content() %>%
add_image(
src = "https://favstats.github.io/dashboardr/reference/figures/logo.svg",
alt = "dashboardr Logo",
caption = "The dashboardr package logo",
width = "200px"
)
print(image_example)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 1 items | β no data
#>
#> β [Image]
image_example %>% preview()Tip: Always use absolute URLs (starting with
https://) for images in vignettes. Local file paths like"logo.png"work during development but wonβt display on GitHub Pages or pkgdown sites.
Videos
For local video files, use add_video() - but note these
wonβt work on GitHub Pages unless hosted elsewhere:
# Local video (works locally, not on GitHub)
create_content() %>%
add_video(
src = "presentation.mp4",
caption = "Project overview video"
)For video content, use YouTube or Vimeo embeds via
add_iframe() - this is more reliable than direct video
files:
# YouTube embed (recommended approach)
video_example <- create_content() %>%
add_iframe(
src = "https://www.youtube.com/embed/dQw4w9WgXcQ",
height = "315px"
)
print(video_example)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 1 items | β no data
#>
#> β’ [iframe]
video_example %>% preview()iframes
Embed external content like interactive maps, dashboards, or other web pages:
iframe_example <- create_content() %>%
add_iframe(
src = "https://www.openstreetmap.org/export/embed.html?bbox=-0.1%2C51.5%2C0.0%2C51.52",
height = "300px"
)
print(iframe_example)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 1 items | β no data
#>
#> β’ [iframe]
iframe_example %>% preview()Raw HTML
Insert custom HTML when needed:
html_example <- create_content() %>%
add_html('<div style="background: linear-gradient(to right, #667eea, #764ba2); color: white; padding: 20px; border-radius: 8px; text-align: center;"><h3>Custom HTML Block</h3><p>Style anything with raw HTML!</p></div>')
print(html_example)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 1 items | β no data
#>
#> β’ [html]Custom HTML Block
Style anything with raw HTML!
π Tables and Custom Charts
Beyond visualizations created with add_viz(), you can
embed tables and custom charts directly into content collections.
gt Tables
Use add_gt() to embed publication-quality tables created
with the gt package:
# Create a summary table
summary_data <- gss %>%
group_by(degree) %>%
summarise(
n = n(),
mean_age = round(mean(age, na.rm = TRUE), 1),
.groups = "drop"
)
gt_example <- create_content() %>%
add_text("### Summary Statistics by Education") %>%
add_gt(
gt::gt(summary_data) %>%
gt::cols_label(degree = "Education", n = "Count", mean_age = "Mean Age")
)
print(gt_example)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 2 items | β no data
#>
#> βΉ [Text]
#> β’ [gt]| Education | Count | Mean Age |
|---|---|---|
You can also pass a data frame directly - it will be converted to a gt table automatically:
simple_gt <- create_content() %>%
add_gt(head(summary_data, 3), caption = "Top 3 Education Levels")
simple_gt %>% preview()| degree | n | mean_age |
|---|---|---|
Reactable Tables
For interactive tables with sorting and filtering, use
add_reactable():
reactable_example <- create_content() %>%
add_text("### Interactive Summary Table") %>%
add_reactable(
reactable::reactable(summary_data, searchable = TRUE, striped = TRUE)
)
print(reactable_example)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 2 items | β no data
#>
#> βΉ [Text]
#> β’ [reactable]DT DataTables
For feature-rich interactive tables, use add_DT():
dt_example <- create_content() %>%
add_text("### DataTable with Search and Pagination") %>%
add_DT(summary_data, options = list(pageLength = 5))
print(dt_example)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 2 items | β no data
#>
#> βΉ [Text]
#> β’ [DT]Basic Tables
For simple tables without dependencies, use
add_table():
table_example <- create_content() %>%
add_table(head(summary_data, 3), caption = "Sample Data")
print(table_example)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 1 items | β no data
#>
#> β’ [table]| degree | n | mean_age |
|---|---|---|
| less than high school | 242 | 49.5 |
| high school | 1361 | 50 |
| associate/junior college | 277 | 49.6 |
Custom Highcharter Charts
When you need a visualization that goes beyond what
add_viz() offers, use add_hc() to embed any highcharter chart:
library(highcharter)
# Create a custom chart
custom_chart <- highchart() %>%
hc_chart(type = "pie") %>%
hc_title(text = "Education Distribution") %>%
hc_add_series(
name = "Count",
data = list(
list(name = "Less than HS", y = sum(gss$degree == "less than high school")),
list(name = "High School", y = sum(gss$degree == "high school")),
list(name = "Junior College", y = sum(gss$degree == "junior college")),
list(name = "Bachelor", y = sum(gss$degree == "bachelor")),
list(name = "Graduate", y = sum(gss$degree == "graduate"))
)
)
hc_example <- create_content() %>%
add_text("### Custom Pie Chart") %>%
add_hc(custom_chart)
print(hc_example)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 2 items | β no data
#>
#> βΉ [Text]
#> β’ [hc]This is useful for:
- Chart types not available in
add_viz()(pie charts, gauges, etc.) - Highly customized visualizations
- Integrating existing highcharter code
π Working with Pre-aggregated Data
While dashboardr was designed with survey data in mind (where you typically count or aggregate responses), it works equally well with data thatβs already aggregated.
Bar Charts with Pre-aggregated Data
Use the y_var parameter to specify a column containing
pre-computed values:
# Pre-aggregated data (e.g., from a database or API)
country_stats <- data.frame(
country = c("USA", "Germany", "France", "UK", "Japan"),
population_millions = c(331, 83, 67, 67, 126),
gdp_trillions = c(21.4, 3.8, 2.6, 2.8, 5.1)
)
# Use y_var to plot pre-aggregated values directly
preagg_bar <- create_content(data = country_stats) %>%
add_viz(
type = "bar",
x_var = "country",
y_var = "population_millions", # Pre-computed values
title = "Population by Country (Millions)",
x_order = c("USA", "Japan", "Germany", "UK", "France")
)
preagg_bar %>% preview()This also works for grouped bar charts:
# Pre-aggregated grouped data
quarterly_sales <- data.frame(
quarter = rep(c("Q1", "Q2", "Q3", "Q4"), each = 2),
region = rep(c("North", "South"), 4),
revenue = c(100, 80, 120, 95, 150, 110, 130, 100)
)
grouped_preagg <- create_content(data = quarterly_sales) %>%
add_viz(
type = "bar",
x_var = "quarter",
group_var = "region",
y_var = "revenue",
title = "Quarterly Revenue by Region"
)
grouped_preagg %>% preview()Stacked Bars with Pre-aggregated Data
The y_var parameter works the same way for stacked bar
charts:
# Pre-aggregated stacked data
satisfaction_data <- data.frame(
department = rep(c("Sales", "Engineering", "HR"), each = 3),
rating = rep(c("Satisfied", "Neutral", "Dissatisfied"), 3),
count = c(45, 30, 10, 60, 25, 15, 35, 20, 5)
)
stacked_preagg <- create_content(data = satisfaction_data) %>%
add_viz(
type = "stackedbar",
x_var = "department",
stack_var = "rating",
y_var = "count", # Pre-computed counts
title = "Employee Satisfaction by Department"
)
stacked_preagg %>% preview()Histograms with Pre-aggregated Data
For pre-binned histogram data:
# Pre-binned data (e.g., from a reporting system)
age_bins <- data.frame(
age_group = c("18-25", "26-35", "36-45", "46-55", "56-65", "65+"),
count = c(150, 280, 320, 290, 210, 180)
)
hist_preagg <- create_content(data = age_bins) %>%
add_viz(
type = "histogram",
x_var = "age_group",
y_var = "count", # Pre-computed bin counts
title = "Age Distribution"
)
hist_preagg %>% preview()Timelines with Pre-aggregated Data
Use agg = "none" to skip aggregation for timeline
data:
# Pre-aggregated time series
yearly_metrics <- data.frame(
year = c(2020, 2021, 2022, 2023),
value = c(1250, 1380, 1420, 1510)
)
timeline_preagg <- create_content(data = yearly_metrics) %>%
add_viz(
type = "timeline",
time_var = "year",
y_var = "value",
agg = "none", # Use values directly, no aggregation
title = "Yearly Performance Trend"
)
timeline_preagg %>% preview()Heatmaps with Pre-aggregated Data
Use pre_aggregated = TRUE to skip the aggregation
step:
# Pre-computed heatmap values (one row per cell)
correlation_data <- data.frame(
var1 = rep(c("Age", "Income", "Education"), each = 3),
var2 = rep(c("Age", "Income", "Education"), 3),
correlation = c(1.0, 0.35, 0.28, 0.35, 1.0, 0.52, 0.28, 0.52, 1.0)
)
heatmap_preagg <- create_content(data = correlation_data) %>%
add_viz(
type = "heatmap",
x_var = "var1",
y_var = "var2",
value_var = "correlation",
pre_aggregated = TRUE, # Skip aggregation
title = "Correlation Matrix",
color_min = -1,
color_max = 1
)
heatmap_preagg %>% preview()Treemaps with Pre-aggregated Data
Use pre_aggregated = TRUE to use values directly without
summing:
# Pre-aggregated hierarchical data
budget_data <- data.frame(
category = c("Marketing", "Marketing", "Engineering", "Engineering", "Operations"),
subcategory = c("Digital", "Events", "Frontend", "Backend", "Support"),
amount = c(50000, 30000, 80000, 120000, 45000)
)
treemap_preagg <- create_content(data = budget_data) %>%
add_viz(
type = "treemap",
group_var = "category",
subgroup_var = "subcategory",
value_var = "amount",
pre_aggregated = TRUE, # Use amounts directly
title = "Budget Allocation"
)
treemap_preagg %>% preview()π² Layout Helpers
Dividers
Visual separators between content sections:
divider_content <- create_content(data = gss, type = "bar") %>%
add_viz(x_var = "degree", title = "Education") %>%
add_divider() %>%
add_viz(x_var = "happy", title = "Happiness")
print(divider_content)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 3 items | β data: 2997 rows x 15 cols
#>
#> β’ [Viz] Education (bar) x=degree
#> β [Divider]
#> β’ [Viz] Happiness (bar) x=happySpacers
Add vertical spacing between elements:
spacer_example <- create_content() %>%
add_text("Content above") %>%
add_spacer(height = "3rem") %>%
add_text("Content below (after 3rem spacer)")
print(spacer_example)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 3 items | β no data
#>
#> βΉ [Text]
#> β’ [spacer]
#> βΉ [Text]Content above
Content below (after 3rem spacer)
ποΈ Previewing Content
Use preview() to quickly check your visualizations and
content blocks during development. It automatically validates your
visualization specs and catches errors like missing parameters or
invalid column names before rendering:
# Quick preview (fast, no Quarto)
content %>% preview()
# Full Quarto preview (slower, full features)
content %>% preview(quarto = TRUE)
# Save to specific location
content %>% preview(path = "my_preview.html")Limitations of Preview
Important:
preview()is a simplified rendering for quick checks during development. It does not show the final dashboard appearance.
What preview shows well:
- Individual visualizations and their data
- Basic tabgroup organization
- Content blocks (text, callouts, cards, etc.)
- Simple nested tabs
What preview does NOT support:
- Full dashboard navigation and layout
- Interactive inputs (dropdowns, sliders, checkboxes)
- Complex multi-page structures
- Dashboard theming and styling
- Sidebar navigation
- Mobile responsiveness
For a real view of your dashboard, you must run
generate_dashboard() and open the resulting Quarto
site:
dashboard <- create_dashboard("My Dashboard") %>%
add_page(my_page)
# Generate the full dashboard
generate_dashboard(dashboard)
# Then open _site/index.html in your browserThink of preview() as a βsanity checkβ for your charts
and content, not a representation of the final product.
β‘οΈ Next Steps
Once you have content, add it to a page:
create_page("Analysis", data = gss) %>%
add_content(demographics) %>%
add_content(attitudes)See vignette("pages") for page creation details.