This vignette covers advanced dashboardr features: interactive inputs, data filtering, batch creation, survey weights, icons, and navigation customization.
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) %>%
filter(year == max(year, na.rm = TRUE)) %>%
filter(
happy %in% 1:3,
polviews %in% 1:7,
!is.na(age), !is.na(sex), !is.na(race), !is.na(degree)
) %>%
mutate(
age = as.numeric(age), # Keep age as numeric for filter comparisons
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))
)Filters let you create multiple visualizations from the same dataset,
each showing a different subset. Instead of manually splitting your data
into separate data frames, you define the filter condition directly in
add_viz().
Without filters, youβd need to create separate datasets:
# Tedious approach - don't do this
males <- gss %>% filter(sex == 1)
females <- gss %>% filter(sex == 2)
create_content(data = males, type = "bar") %>%
add_viz(x_var = "happy", title = "Male")
create_content(data = females, type = "bar") %>%
add_viz(x_var = "happy", title = "Female")With filters, one dataset serves all visualizations:
Filters use Rβs formula syntax with a tilde (~). The
expression after ~ is evaluated against your data:
| Filter | Meaning |
|---|---|
~ sex == 1 |
Rows where sex equals 1 |
~ age > 30 |
Rows where age is greater than 30 |
~ race == "white" |
Rows where race is βwhiteβ |
~ age >= 18 & age <= 35 |
Rows where age is between 18 and 35 |
~ degree %in% c("bachelor", "graduate") |
Rows where degree is bachelor or graduate |
Show the same variable for different subgroups side by side:
filtered <- create_content(data = gss, type = "bar") %>%
add_viz(x_var = "happy", title = "Male", filter = ~ sex == "male", tabgroup = "Male") %>%
add_viz(x_var = "happy", title = "Female", filter = ~ sex == "female", tabgroup = "Female")
print(filtered)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 2 items | β data: 2997 rows x 8 cols
#>
#> β― [Tab] Male (1 viz)
#> β’ [Viz] Male (bar) x=happy +filter
#> β― [Tab] Female (1 viz)
#> β’ [Viz] Female (bar) x=happy +filterThis creates two charts in the same tabgroup - one filtered to males, one to females. Users can switch between them to compare happiness distributions.
Combine conditions with & (and) and |
(or). Here we create one tabgroup (βage_groupsβ) with three tabs, each
showing happiness for a different age range:
complex <- create_content(data = gss, type = "bar") %>%
add_viz(x_var = "happy", title = "Young Adults (18-35)",
filter = ~ age >= 18 & age <= 35, tabgroup = "Youngsters") %>%
add_viz(x_var = "happy", title = "Middle Age (36-55)",
filter = ~ age > 35 & age <= 55, tabgroup = "Middlers") %>%
add_viz(x_var = "happy", title = "Older Adults (55+)",
filter = ~ age > 55, tabgroup = "Olders")
print(complex)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 3 items | β data: 2997 rows x 8 cols
#>
#> β― [Tab] Youngsters (1 viz)
#> β’ [Viz] Young Adults (18-35) (bar) x=happy +filter
#> β― [Tab] Middlers (1 viz)
#> β’ [Viz] Middle Age (36-55) (bar) x=happy +filter
#> β― [Tab] Olders (1 viz)
#> β’ [Viz] Older Adults (55+) (bar) x=happy +filterWhen to use filter: - You want
completely separate charts for each group - Groups need different
titles, settings, or tabgroups - Youβre comparing the same variable
across subsets
When to use group_var: - You want
grouped bars within a single chart - Direct visual comparison in one
view
# Using filter: separate charts per group
create_content(data = gss, type = "bar") %>%
add_viz(x_var = "happy", title = "Happiness (Male)", filter = ~ sex == "male", tabgroup = "separate") %>%
add_viz(x_var = "happy", title = "Happiness (Female)", filter = ~ sex == "female", tabgroup = "separate") %>%
preview()# Using group_var: one chart with grouped bars
create_content(data = gss, type = "bar") %>%
add_viz(x_var = "happy", group_var = "sex", title = "Happiness by Sex") %>%
preview()When youβre comparing the same variable across multiple
groups, title_tabset creates a second level of
tabs:
tabgroup = the category (e.g.,
βHappinessβ, βEducationβ)title_tabset = the variant within that
category (e.g., βMaleβ, βFemaleβ)gender_comparison <- create_content(data = gss, type = "bar") %>%
# Happiness tabgroup with Male/Female sub-tabs
add_viz(x_var = "happy", title = "Happiness",
filter = ~ sex == "male", title_tabset = "Male", tabgroup = "happiness") %>%
add_viz(x_var = "happy", title = "Happiness",
filter = ~ sex == "female", title_tabset = "Female", tabgroup = "happiness") %>%
# Education tabgroup with Male/Female sub-tabs
add_viz(x_var = "degree", title = "Education",
filter = ~ sex == "male", title_tabset = "Male", tabgroup = "education") %>%
add_viz(x_var = "degree", title = "Education",
filter = ~ sex == "female", title_tabset = "Female", tabgroup = "education")
print(gender_comparison)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 4 items | β data: 2997 rows x 8 cols
#>
#> β― [Tab] happiness (2 vizs)
#> β’ [Viz] Happiness (bar) x=happy +filter
#> β’ [Viz] Happiness (bar) x=happy +filter
#> β― [Tab] education (2 vizs)
#> β’ [Viz] Education (bar) x=degree +filter
#> β’ [Viz] Education (bar) x=degree +filterWhen you need to create many similar visualizations,
add_vizzes() lets you do it in one call instead of
repeating add_viz() multiple times.
# Tedious and error-prone
create_content(data = gss, type = "bar") %>%
add_viz(x_var = "degree", title = "Education", tabgroup = "survey") %>%
add_viz(x_var = "race", title = "Race", tabgroup = "survey") %>%
add_viz(x_var = "happy", title = "Happiness", tabgroup = "survey") %>%
add_viz(x_var = "polviews", title = "Politics", tabgroup = "survey")With add_vizzes(), pass vectors for the parameters that
vary, and single values for parameters that stay the same:
vars <- c("degree", "race", "happy", "polviews")
labels <- c("Education", "Race", "Happiness", "Politics")
batch <- create_content(data = gss, type = "bar") %>%
add_vizzes(x_var = vars, title = labels, tabgroup = "survey")
print(batch)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 4 items | β data: 2997 rows x 8 cols
#>
#> β― [Tab] survey (4 vizs)
#> β’ [Viz] Education (bar) x=degree
#> β’ [Viz] Race (bar) x=race
#> β’ [Viz] Happiness (bar) x=happy
#> β’ [Viz] Politics (bar) x=polviewsVector parameters (vary per visualization): -
x_var, y_var, stack_var,
group_var, title, questions -
Must all have the same length
Scalar parameters (shared across all): -
type, color_palette, bar_type,
horizontal, tabgroup (if single value), etc. -
Applied to every visualization
Pass tabgroup as a vector to put each visualization in a
different tab:
create_content(data = gss, type = "bar") %>%
add_vizzes(
x_var = c("degree", "happy", "polviews"),
title = c("Education", "Happiness", "Politics"),
tabgroup = c("demographics", "wellbeing", "attitudes")
) %>%
preview()Interactive input widgets transform your dashboard from a static report into an exploratory data tool. Users can filter data, adjust parameters, and see visualizations update in real-time.
π See it in action: Check out the Inputs Demo to try all input types with real GSS data!
The input system connects user controls to data columns:
User selects "Bachelor's" in dropdown
β
filter_var = "degree" tells dashboardr which column to filter
β
Data is filtered to rows where degree == "Bachelor's"
β
All visualizations on the page update automatically
Basic pattern:
create_page("Analysis", data = my_data, type = "bar") %>%
add_input_row() %>%
add_input(input_id = "edu", label = "Education",
filter_var = "degree", options_from = "degree") %>%
end_input_row() %>%
add_viz(x_var = "happy", title = "Happiness") # Automatically filtered!Note: Inputs show as placeholders in
preview(). They become fully interactive when you rungenerate_dashboard(render = TRUE)and view in a browser.
| Type | Best For | Selection |
|---|---|---|
select_multiple |
Many categories (10+) | Multiple |
select_single |
Many categories, pick one | Single |
checkbox |
Few categories (3-6) | Multiple |
radio |
Mutually exclusive choices | Single |
slider |
Numeric ranges or ordered categories | Single value |
switch |
Toggle a series on/off | Boolean |
# Single selection
add_input(
input_id = "metric",
label = "Select Metric",
type = "select_single",
filter_var = "metric",
options = c("Sales", "Revenue", "Profit"),
default_selected = "Sales"
)
# Multiple selection
add_input(
input_id = "countries",
label = "Select Countries",
type = "select_multiple",
filter_var = "country",
options_from = "country", # Get options from data column
placeholder = "Choose countries..."
)For long lists, organize options into groups:
# Create grouped options (named list)
countries_by_region <- list(
"Europe" = c("Germany", "France", "UK", "Spain"),
"Asia" = c("China", "Japan", "India", "Korea"),
"Americas" = c("USA", "Canada", "Brazil", "Mexico")
)
add_input(
input_id = "country",
label = "Select Country",
type = "select_multiple",
filter_var = "country",
options = countries_by_region, # Grouped!
default_selected = c("USA", "Germany")
)Sliders work for numeric data or ordered categories:
# Numeric slider
add_input(
input_id = "year",
label = "Year",
type = "slider",
filter_var = "year",
min = 2010,
max = 2024,
step = 1,
value = 2020,
show_value = TRUE
)
# Slider with custom labels (for ordered categories)
add_input(
input_id = "decade",
label = "Starting Decade",
type = "slider",
filter_var = "decade",
min = 1,
max = 6,
step = 1,
value = 1,
labels = c("1970s", "1980s", "1990s", "2000s", "2010s", "2020s")
)Switches toggle a specific data series on/off. Unlike other inputs
that filter data, a switch with toggle_series controls
visibility of a named series in your chart:
Use add_input_row() to organize inputs horizontally:
create_page("Analysis", data = gss, type = "bar") %>%
# First row: main filters
add_input_row(style = "inline", align = "center") %>%
add_input(input_id = "edu", label = "Education",
filter_var = "degree", options_from = "degree",
width = "300px") %>%
add_input(input_id = "race", label = "Race",
type = "checkbox", filter_var = "race",
options_from = "race", inline = TRUE) %>%
end_input_row() %>%
# Second row: additional controls
add_input_row() %>%
add_input(input_id = "sex", label = "Gender",
type = "radio", filter_var = "sex",
options_from = "sex", inline = TRUE) %>%
end_input_row() %>%
add_viz(x_var = "happy", title = "Happiness Distribution")| Parameter | Description | Used With |
|---|---|---|
input_id |
Unique identifier | All |
label |
Display label | All |
type |
Input type | All |
filter_var |
Column to filter | All |
options |
Manual list of options | select, checkbox, radio |
options_from |
Column to get options from | select, checkbox, radio |
default_selected |
Pre-selected values | select, checkbox, radio |
min, max, step |
Range settings | slider |
value |
Default value | slider, switch |
labels |
Custom labels for slider positions | slider |
toggle_series |
Series name to show/hide | switch |
override |
Override other filters | switch |
inline |
Horizontal layout | checkbox, radio |
width |
Input width (CSS) | select |
placeholder |
Placeholder text | select |
help |
Help text below input | All |
Hereβs a full working example with multiple input types:
library(dashboardr)
library(dplyr)
library(gssr)
library(haven)
# Prepare data
data(gss_all)
gss_inputs <- gss_all %>%
select(year, age, sex, race, degree, happy, polviews) %>%
filter(year >= 2010, happy %in% 1:3,
!is.na(age), !is.na(sex), !is.na(race), !is.na(degree)) %>%
mutate(across(c(happy, degree, sex, race), ~droplevels(as_factor(.))))
# Create page with inputs
inputs_page <- create_page("Explorer", data = gss_inputs, type = "bar") %>%
add_text(
"## GSS Data Explorer",
"",
"Filter the data using the controls below. All charts update automatically."
) %>%
add_input_row() %>%
add_input(
input_id = "edu",
label = "Education Level",
type = "select_multiple",
filter_var = "degree",
options_from = "degree",
width = "250px"
) %>%
add_input(
input_id = "race",
label = "Race",
type = "checkbox",
filter_var = "race",
options_from = "race",
inline = TRUE
) %>%
end_input_row() %>%
add_input_row() %>%
add_input(
input_id = "sex",
label = "Gender",
type = "radio",
filter_var = "sex",
options_from = "sex",
inline = TRUE
) %>%
end_input_row() %>%
add_viz(x_var = "happy", title = "Happiness", tabgroup = "Results") %>%
add_viz(x_var = "polviews", title = "Political Views", tabgroup = "Results")
# Generate
create_dashboard(title = "GSS Explorer", output_dir = "gss_explorer") %>%
add_pages(inputs_page) %>%
generate_dashboard(render = TRUE, open = "browser")For sidebar dashboards where inputs control multiple visualizations, dashboardr supports client-side cross-tab filtering β charts rebuild instantly without server round-trips.
π See it in action: Check out the GSS Explorer Demo to see cross-tab filtering, conditional visibility, dynamic titles, and consistent colors all working together!
Use show_when to show or hide a visualization based on
the current sidebar input values. This lets you display different chart
types depending on user selections:
# Show a stacked bar for single-year views
add_viz(
type = "stackedbar",
x_var = "response",
stack_var = "group",
y_var = "n",
show_when = ~ time_period %in% c("2022", "2024") & breakdown != "Overall"
)
# Show a timeline for the "Over Time" view
add_viz(
type = "timeline",
time_var = "year",
y_var = "score",
show_when = ~ time_period == "Over Time"
)The show_when formula uses the same operators as R:
==, !=, %in%, combined with
& (and) and | (or). Hidden charts fully
collapse β no empty space left behind.
Chart titles can include {placeholder} tokens that are
automatically replaced with the current sidebar input value:
add_viz(
type = "stackedbar",
title = "{dimension}: {question} by {breakdown} ({time_period})",
...
)When the user selects βRaceβ in the sidebar, {breakdown}
becomes βRaceβ in the title. Placeholders are matched by
input_id.
Sometimes you need a placeholder whose value is derived from an input β not the input value itself. For example, showing which response value is tracked in a timeline (e.g., βLegalβ for marijuana, βFavorβ for death penalty).
Use title_map with a simple named vector:
# Pre-compute the mapping from your existing objects
key_response_map <- setNames(key_resp[question_var], names(question_var))
# Result: c("Marijuana Legalization" = "Legal", "Death Penalty" = "Favor", ...)
add_viz(
type = "timeline",
title = "{question}: % responding '{key_response}' by {breakdown}",
title_map = list(key_response = key_response_map),
...
)The system auto-detects which sidebar input the mapping corresponds
to β you just provide the named vector. When the user selects βMarijuana
Legalizationβ, {key_response} becomes βLegalβ.
By default, Highcharts assigns colors positionally. When stacked bars
and timelines add series in different orders, the same group gets
different colors. Fix this with a named
color_palette:
# Define once
group_colors <- c(
"Male" = "#F28E2B", "Female" = "#E15759",
"White" = "#EDC948", "Black" = "#59A14F", "Other" = "#76B7B2",
"18-29" = "#BAB0AC", "30-44" = "#9C755F", "45-59" = "#FF9DA7", "60+" = "#B07AA1"
)
# Use in both charts β "Male" is always #F28E2B
add_viz(type = "stackedbar", color_palette = group_colors, ...)
add_viz(type = "timeline", color_palette = group_colors, ...)Named palettes map colors by series name. Unnamed vectors
(c("#F28E2B", "#E15759")) still work as positional cycles
for backwards compatibility.
Control the order series appear in timeline charts:
add_viz(
type = "timeline",
group_var = "breakdown_value",
group_order = c("Male", "Female", "White", "Black", "Other"),
...
)This ensures the legend and series order matches across chart types.
Use rev() if the visual order needs to be reversed to match
a horizontal stacked barβs legend.
Survey data often requires weighting to produce population-representative estimates. Without weights, your sample might over- or under-represent certain groups.
Unweighted data shows your raw sample distribution - useful for understanding who responded, but may not reflect the actual population.
Weighted data adjusts for sampling design and non-response, giving you estimates that better represent the target population.
Set weight_var in create_content() to apply
weights to all visualizations. The GSS provides several weight
variables; wtssps is the recommended post-stratification
weight for recent years:
# Compare unweighted vs weighted
unweighted <- create_content(data = gss, type = "bar") %>%
add_viz(x_var = "degree", title = "Education (Unweighted)", tabgroup = "comparison")
weighted <- create_content(data = gss, type = "bar", weight_var = "wtssps") %>%
add_viz(x_var = "degree", title = "Education (Weighted)", tabgroup = "comparison")
# Combine to see the difference
(unweighted + weighted) %>% preview()Notice how the distributions differ - the weighted version adjusts for the fact that more educated people are typically overrepresented in survey samples.
When you set weight_var in
create_content(), it applies to all
visualizations in that collection:
# All three charts use the same weight
weighted_collection <- create_content(data = gss, type = "bar", weight_var = "wtssps") %>%
add_viz(x_var = "degree", title = "Education", tabgroup = "weighted") %>%
add_viz(x_var = "race", title = "Race", tabgroup = "weighted") %>%
add_viz(x_var = "happy", title = "Happiness", tabgroup = "weighted")
print(weighted_collection)
#> -- Content Collection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#> 3 items | β data: 2997 rows x 8 cols
#>
#> β― [Tab] weighted (3 vizs)
#> β’ [Viz] Education (bar) x=degree
#> β’ [Viz] Race (bar) x=race
#> β’ [Viz] Happiness (bar) x=happydashboardr provides a flexible 3-tier system for customizing chart tooltips, from quick tweaks to full control.
Add prefix or suffix text to tooltip values:
Use format strings with {placeholders} for more
control:
Available placeholders vary by chart type:
| Placeholder | Description | Charts |
|---|---|---|
{value} |
Primary value | All |
{category} |
X-axis category | bar, histogram, stackedbar |
{x}, {y} |
Coordinates | scatter, heatmap |
{series} |
Series name | Grouped charts |
{percent} |
Percentage | Percent-type charts |
{name} |
Point name | All |
Use the tooltip() helper for complete customization
including styling:
viz_bar(data = gss, x_var = "degree",
tooltip = tooltip(
format = "<b>{category}</b><br/>Count: {value}",
backgroundColor = "#f8f9fa",
borderColor = "#dee2e6",
borderRadius = 8,
style = list(fontSize = "14px")
))The tooltip() function exposes all Highcharts tooltip
options:
format - Format string with {placeholders}shared - Share tooltip across series (TRUE/FALSE)backgroundColor, borderColor,
borderRadius - Visual stylingstyle - CSS styles as a named listheader - Header format (use FALSE to hide)enabled - Enable/disable tooltips entirelyAll chart functions (viz_bar(),
viz_scatter(), viz_histogram(), etc.) support
the same tooltip parameters for consistent behavior across your
dashboard.
dashboardr uses Iconify for 200,000+ icons from 100+ icon sets.
Icons use the format set:icon-name:
| Set | Prefix | Style | Examples |
|---|---|---|---|
| Phosphor | ph: |
Clean, modern | ph:chart-line, ph:users-fill,
ph:gear-fill |
| Material Design | mdi: |
Google style | mdi:chart-bar, mdi:account-group |
| Bootstrap | bi: |
Bootstrap style | bi:graph-up, bi:people-fill |
| Font Awesome | fa: |
Classic | fa:chart-bar, fa:users |
Add icons to pages in the navbar:
Add icons to tab labels using Quarto shortcodes:
Use Quarto shortcodes in markdown text:
set:icon-nameCommon choices by purpose:
| Purpose | Recommended Icons |
|---|---|
| Home/Landing | ph:house-fill, ph:home |
| Charts/Analysis | ph:chart-line, ph:chart-bar-fill,
ph:graph |
| Users/Demographics | ph:users-fill, ph:user-circle |
| Settings/Config | ph:gear-fill, ph:sliders |
| Info/About | ph:info-fill, ph:question |
| Download/Export | ph:download-simple, ph:export |
| Time/Trends | ph:clock, ph:trend-up |
Pick one icon set and stick with it throughout your dashboard:
# Good: All Phosphor icons
create_page("Home", icon = "ph:house-fill")
create_page("Analysis", icon = "ph:chart-line")
create_page("About", icon = "ph:info-fill")
# Avoid: Mixed icon sets (inconsistent visual style)
create_page("Home", icon = "ph:house-fill")
create_page("Analysis", icon = "bi:graph-up") # Different set
create_page("About", icon = "mdi:information") # Another setModals are popup overlays that display additional content without navigating away from the current page. Theyβre perfect for showing detailed explanations, images, data tables, or supplementary information that users can access on demand.
Creating a modal requires two parts: 1. A trigger link that users click 2. The modal content that appears in the popup
Use add_modal() in your content pipeline, then reference
it with a markdown link:
content <- create_content() %>%
add_text(
"## Survey Results",
"",
"The response rate was 78%. [View methodology](#methodology){.modal-link}"
) %>%
add_modal(
modal_id = "methodology",
title = "Survey Methodology",
modal_content = "Data was collected via online questionnaire from March 1-15, 2024.
The sample was weighted to match national demographics."
)The {.modal-link} class on the markdown link tells
dashboardr to open the content as a modal instead of navigating to a new
page.
Show images in a modal - great for displaying full-size charts, diagrams, or photos:
content <- create_content() %>%
add_text("[View the survey question](#question-img){.modal-link}") %>%
add_modal(
modal_id = "question-img",
title = "Question Wording",
image = "question_screenshot.png",
image_width = "80%", # Control the image size
modal_content = "Respondents were shown this question as part of the survey."
)Pass a data.frame directly and it will be automatically converted to an HTML table:
# Show summary statistics in a modal
summary_data <- data.frame(
Metric = c("Mean", "Median", "SD", "N"),
Value = c(3.42, 3.5, 1.23, 1247)
)
content <- create_content() %>%
add_text("[View summary statistics](#stats){.modal-link}") %>%
add_modal(
modal_id = "stats",
title = "Summary Statistics",
modal_content = summary_data
)| Parameter | Description | Example |
|---|---|---|
modal_id |
Unique identifier (used in link) | "details", "chart-info" |
title |
Heading displayed at top of modal | "More Information" |
modal_content |
Text, HTML, or data.frame | "Description..." or my_df |
image |
Path or URL to an image | "images/chart.png" |
image_width |
Width of the image | "100%", "70%", "500px" |
You can add as many modals as needed - just ensure each has a unique
modal_id:
content <- create_content() %>%
add_text(
"## Results Overview",
"",
"- Demographics: [see details](#demo-modal){.modal-link}",
"- Methodology: [see details](#method-modal){.modal-link}",
"- Limitations: [see details](#limits-modal){.modal-link}"
) %>%
add_modal(
modal_id = "demo-modal",
title = "Demographics",
modal_content = "Sample was 52% female, median age 42..."
) %>%
add_modal(
modal_id = "method-modal",
title = "Methodology",
modal_content = "Online panel survey conducted..."
) %>%
add_modal(
modal_id = "limits-modal",
title = "Limitations",
modal_content = "This study has several limitations..."
)Hereβs a full example showing modals used with visualizations:
library(dashboardr)
library(dplyr)
# Create page with charts and modals for additional context
results_page <- create_page("Results", data = gss, type = "bar") %>%
add_text(
"## Survey Results",
"",
"These charts show key findings from our analysis.",
"[Learn about our methodology](#methodology){.modal-link}"
) %>%
add_viz(
x_var = "happy",
title = "Happiness Distribution",
tabgroup = "findings"
) %>%
add_text(
"",
"[View the original survey question](#question){.modal-link}"
) %>%
add_modal(
modal_id = "methodology",
title = "Survey Methodology",
modal_content = "<p>Data from the General Social Survey (GSS), a nationally
representative survey of US adults conducted since 1972.</p>
<p>Weights were applied to adjust for sampling design.</p>"
) %>%
add_modal(
modal_id = "question",
title = "Survey Question",
image = "happiness_question.png",
image_width = "70%",
modal_content = "Respondents were asked: 'Taken all together, how would you
say things are these days - would you say that you are very happy,
pretty happy, or not too happy?'"
)
# Generate the dashboard
create_dashboard(title = "GSS Analysis", output_dir = "gss_modals") %>%
add_page(results_page) %>%
generate_dashboard(render = TRUE)For more control, you can use the underlying helper functions directly:
enable_modals() - Adds the CSS/JS for modal
functionalitymodal_link(text, modal_id) - Creates a clickable
linkmodal_content(modal_id, ...) - Creates the modal
container# Using low-level functions (rarely needed)
library(htmltools)
# In a Quarto/R Markdown document:
enable_modals()
# Create a link
modal_link("Click for details", "my-modal", class = "btn btn-primary")
# Create the modal content
modal_content(
modal_id = "my-modal",
title = "Details",
image = "chart.png",
text = "This chart shows..."
)Most users should stick with add_modal() in their
pipelines for a cleaner workflow.
Customize the appearance of tabs within your pages using
tabset_theme and tabset_colors. Tab styling
affects how tabbed content (created via tabgroup) appears
to users.
Four built-in themes provide different visual styles for your tabs. Each theme changes the shape, spacing, and general appearance of the tab buttons.
| Theme | Description | Best For |
|---|---|---|
"default" |
Standard Quarto tabs with underline indicator | General use, compatibility |
"modern" |
Clean look with subtle backgrounds | Professional dashboards |
"pills" |
Rounded pill-shaped buttons | Friendly, approachable interfaces |
"minimal" |
Subtle text-only with hover effects | Content-focused designs |
# Modern theme
modern_page <- create_page("Modern", data = gss, type = "bar", tabset_theme = "modern") %>%
add_viz(x_var = "degree", title = "Education", tabgroup = "A") %>%
add_viz(x_var = "race", title = "Race", tabgroup = "B")
print(modern_page)
#> -- Page: Modern βββββββββββββββββββββββββββββββββββββββββββββββββ
#> β data: 2997 rows x 8 cols | default: bar
#> 2 items
#>
#> β― [Tab] A (1 viz)
#> β’ [Viz] Education (bar) x=degree
#> β― [Tab] B (1 viz)
#> β’ [Viz] Race (bar) x=raceNote: Tab themes are fully rendered in the generated dashboard. Use
generate_dashboard(render = TRUE)to see the complete styling.
Beyond the built-in themes, you can fully customize tab colors to
match your brand or create unique visual designs. Use
tabset_colors to define a custom color scheme.
The tabset_colors parameter accepts a named list with
the following color options:
| Parameter | Description | Default |
|---|---|---|
active_bg |
Background color of the selected tab | Theme-dependent |
active_text |
Text color of the selected tab | Theme-dependent |
inactive_bg |
Background color of unselected tabs | Transparent |
inactive_text |
Text color of unselected tabs | Gray |
hover_bg |
Background color when hovering | Light gray |
All colors can be specified as hex codes (e.g.,
"#3498DB"), RGB values (e.g.,
"rgb(52, 152, 219)"), or named colors (e.g.,
"steelblue").
# Blue theme
blue_tabs <- create_page(
"Blue Theme",
data = gss,
type = "bar",
tabset_theme = "pills",
tabset_colors = list(
active_bg = "#3498DB", # Active tab background
active_text = "#FFFFFF", # Active tab text
inactive_bg = "#ECF0F1", # Inactive tab background
inactive_text = "#7F8C8D", # Inactive tab text
hover_bg = "#BDC3C7" # Hover background
)
) %>%
add_viz(x_var = "degree", title = "Education", tabgroup = "demo") %>%
add_viz(x_var = "happy", title = "Happiness", tabgroup = "attitudes")
print(blue_tabs)
#> -- Page: Blue Theme βββββββββββββββββββββββββββββββββββββββββββββ
#> β data: 2997 rows x 8 cols | default: bar
#> 2 items
#>
#> β― [Tab] demo (1 viz)
#> β’ [Viz] Education (bar) x=degree
#> β― [Tab] attitudes (1 viz)
#> β’ [Viz] Happiness (bar) x=happyNote: Custom tab colors (like
tabset_colors) are only visible in the generated dashboard, not inpreview().
Match your organizationβs brand colors for a cohesive, professional
look. Start with your primary brand color for active_bg,
then derive the other colors from it (lighter versions for
inactive_bg and hover_bg):
# Corporate red theme
corporate <- create_page(
"Corporate",
data = gss,
type = "bar",
tabset_theme = "modern",
tabset_colors = list(
active_bg = "#C0392B", # Brand red
active_text = "#FFFFFF",
inactive_bg = "#FADBD8", # Light red
inactive_text = "#922B21",
hover_bg = "#E6B0AA"
)
) %>%
add_viz(x_var = "degree", title = "Education", tabgroup = "Q1") %>%
add_viz(x_var = "race", title = "Demographics", tabgroup = "Q2") %>%
add_viz(x_var = "happy", title = "Satisfaction", tabgroup = "Q3")
print(corporate)
#> -- Page: Corporate ββββββββββββββββββββββββββββββββββββββββββββββ
#> β data: 2997 rows x 8 cols | default: bar
#> 3 items
#>
#> β― [Tab] Q1 (1 viz)
#> β’ [Viz] Education (bar) x=degree
#> β― [Tab] Q2 (1 viz)
#> β’ [Viz] Demographics (bar) x=race
#> β― [Tab] Q3 (1 viz)
#> β’ [Viz] Satisfaction (bar) x=happyFor dashboards with dark backgrounds, use high-contrast colors to
ensure readability. The pills theme works particularly well
with dark designs because the rounded buttons create clear visual
boundaries:
# Dark theme
dark_tabs <- create_page(
"Dark Theme",
data = gss,
type = "bar",
tabset_theme = "pills",
tabset_colors = list(
active_bg = "#2ECC71", # Bright green accent
active_text = "#1A1A1A",
inactive_bg = "#2C3E50", # Dark background
inactive_text = "#95A5A6", # Muted text
hover_bg = "#34495E"
)
) %>%
add_viz(x_var = "degree", title = "Education", tabgroup = "Data") %>%
add_viz(x_var = "happy", title = "Results", tabgroup = "Analysis")
print(dark_tabs)
#> -- Page: Dark Theme βββββββββββββββββββββββββββββββββββββββββββββ
#> β data: 2997 rows x 8 cols | default: bar
#> 2 items
#>
#> β― [Tab] Data (1 viz)
#> β’ [Viz] Education (bar) x=degree
#> β― [Tab] Analysis (1 viz)
#> β’ [Viz] Results (bar) x=happyNote: Tab styling (custom colors, themes) is fully visible only in the generated dashboard. The
preview()function shows a simplified version without custom tab colors.
Warning: Lazy loading is currently experimental and may not work reliably in all browsers or configurations. Use with caution in production dashboards.
Lazy loading is a performance optimization technique that defers rendering charts and tab content until theyβre actually needed. Instead of loading everything when the page opens, content loads as the user scrolls to it or clicks on a tab. This can significantly improve initial page load times for dashboards with many visualizations.
Consider lazy loading if your dashboard has:
| Parameter | Description | Default |
|---|---|---|
lazy_load_charts |
Load charts only when scrolled into view | FALSE |
lazy_load_margin |
Distance from viewport to start loading (CSS units) | "200px" |
lazy_load_tabs |
Load tab content only when tab is clicked | FALSE |
Loading overlays provide visual feedback while content renders. They display a spinner or animation that disappears once the page is ready, creating a polished user experience.
See it in action: Check out the Loading Overlay Demo to experience loading overlays - reload to see the effect.
| Parameter | Description | Options |
|---|---|---|
overlay |
Enable loading overlay | TRUE / FALSE |
overlay_theme |
Visual style of the overlay | "light", "dark", "glass",
"accent" |
overlay_text |
Custom message to display | Any string |
overlay_duration |
Minimum display time (milliseconds) | e.g., 1500 |
Add a subtle βPowered by dashboardrβ badge to your dashboard footer. This is entirely optional but helps spread the word about dashboardr!
dashboard <- create_dashboard("my_project", "My Dashboard") %>%
add_pages(home, analysis, about) %>%
add_powered_by_dashboardr()Choose a style that fits your dashboardβs aesthetic:
| Style | Description |
|---|---|
"default" |
Subtle text with the dashboardr logo |
"minimal" |
Just text, no logo - most unobtrusive |
"badge" |
Rounded background badge - more visible |
Control how prominent the branding appears: