---
title: "Pages: Deep Dive"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{Pages: Deep Dive}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.width = 7,
fig.height = 5
)
```
This vignette covers **pages** - the second layer of dashboardr's architecture. For a quick overview, see `vignette("getting-started")`.
Throughout this vignette, we use the [General Social Survey (GSS)](https://gssr.io/) as example data. Click below to see the data loading code.
📦 **Data Loading Code** (click to expand)
```{r setup, message=FALSE, warning=FALSE}
library(dashboardr)
library(dplyr)
library(gssr)
library(haven)
# Load latest wave only
data(gss_all)
gss <- gss_all %>%
select(year, age, sex, race, degree, happy, polviews) %>%
filter(year == max(year, na.rm = TRUE)) %>%
# Filter to substantive responses (removes "don't know", "no answer", etc.)
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)
) %>%
mutate(
sex = droplevels(as_factor(sex)),
race = droplevels(as_factor(race)),
degree = droplevels(as_factor(degree)),
happy = droplevels(as_factor(happy)),
polviews = droplevels(as_factor(polviews))
)
```
## 📄 What is create_page()?
The `create_page()` function creates a **page object** - a named destination in your dashboard that users can navigate to. Every dashboard needs at least one page: the landing page.
```{r}
# Create a simple page
my_page <- create_page(
name = "Home",
data = gss,
type = "bar"
)
print(my_page)
```
Pages can hold all the same content as `create_content()` (visualizations, text, callouts, etc.), but they also carry **page-level metadata** like the page name, icon, and navbar position.
### 🆚 create_page() vs create_content()
Both functions create containers for visualizations and content, but they serve different purposes:
| | `create_content()` | `create_page()` |
|---|---|---|
| **Purpose** | Build reusable content blocks | Create a dashboard page |
| **Page metadata** | No | Yes (icons, navbar position, overlays) |
| **Data defaults** | Yes | Yes |
| **Use with `create_dashboard()`** | Must be added to a page first | Can be added directly |
**Think of it this way:**
- `create_content()` = building blocks (reusable pieces)
- `create_page()` = the destination (what users navigate to)
## 🔀 Two Workflows
### Workflow 1: Simple Dashboards (Direct)
For straightforward dashboards, add content directly to pages:
```{r}
# Everything in one chain
simple_page <- create_page("Analysis", data = gss, type = "bar") %>%
add_text("## Education Distribution", "", "How education levels are distributed.") %>%
add_viz(x_var = "degree", title = "Education Levels",
x_label = "", y_label = "Respondents",
color_palette = c("#3498DB")) %>%
add_callout("Data from GSS 2022", type = "note")
print(simple_page)
```
```{r}
simple_page %>% preview()
```
**When to use:** Quick dashboards, single-topic pages, prototyping.
### Workflow 2: Complex Dashboards (Modular)
For complex dashboards, build content separately, then assemble with `add_content()`:
```{r}
# Step 1: Build content pieces separately
intro_text <- create_content() %>%
add_text("## Overview", "", "Key findings from the General Social Survey.")
demographic_charts <- create_content(type = "bar", y_label = "Count") %>%
add_viz(x_var = "degree", title = "Education", tabgroup = "Demographics") %>%
add_viz(x_var = "race", title = "Race", tabgroup = "Demographics",
color_palette = c("#3498DB", "#E74C3C", "#27AE60"))
attitude_charts <- create_content(type = "bar", y_label = "Count") %>%
add_viz(x_var = "happy", title = "Happiness", tabgroup = "Attitudes",
color_palette = c("#27AE60", "#F39C12", "#E74C3C")) %>%
add_viz(x_var = "polviews", title = "Political Views", tabgroup = "Attitudes")
# Step 2: Assemble into page
complex_page <- create_page("Full Analysis", data = gss) %>%
add_content(intro_text) %>%
add_content(demographic_charts) %>%
add_content(attitude_charts)
print(complex_page)
```
```{r}
complex_page %>% preview()
```
**When to use:** Multi-section pages, reusable content, complex layouts.
**Why this approach?**
1. **Modularity** - Each content piece is self-contained and testable
2. **Reusability** - Share content across multiple pages
**Rule of thumb:**
- Same viz type, same styling → build directly on `create_page()`
- Different viz types, different defaults → use `create_content()` first
3. **Clarity** - Easier to understand page structure
4. **Maintainability** - Update one section without touching others
## 📄 Page Types
There's only one special page type in the API: **landing pages** (`is_landing_page = TRUE`). All other "page types" below are just examples of how you might configure pages with different content - the possibilities depend entirely on what you add!
### Landing Pages
The only true page type distinction. Landing pages are full-width welcome screens without sidebars:
```{r}
home <- create_page("Home", is_landing_page = TRUE) %>%
add_text(
"# Welcome to the GSS Dashboard",
"",
"Explore insights from the General Social Survey.",
"",
"## What You'll Find",
"",
"- **Demographics** - Age, education, race distributions",
"- **Attitudes** - Happiness, political views",
"",
"Click the tabs above to begin exploring!"
) %>%
add_callout("Data source: General Social Survey, NORC", type = "note")
print(home)
```
```{r}
home %>% preview()
```
### Example: Analysis Pages
Standard pages with data and visualizations - just add charts!
```{r}
analysis <- create_page("Analysis", 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")
print(analysis)
```
```{r}
analysis %>% preview()
```
### Example: Text-Only Pages
For documentation, methodology, or about sections - just add text!
```{r}
about <- create_page("About") %>%
add_text(
"## About This Dashboard",
"",
"Created using [dashboardr](https://github.com/favstats/dashboardr).",
"",
"### Methodology",
"",
"The GSS is a nationally representative survey conducted by NORC.",
"",
"### Contact",
"",
"For questions, contact the research team."
) %>%
add_accordion(
title = "Technical Details",
text = "Margin of error: +/- 3%. Confidence level: 95%."
)
print(about)
```
```{r}
about %>% preview()
```
### Example: Dashboard-Style Pages
Metrics at top, charts below - combine value boxes with visualizations!
```{r}
# Build dashboard content
dashboard_content <- create_content(data = gss, type = "bar") %>%
add_value_box_row() %>%
add_value_box(title = "Respondents", value = format(nrow(gss), big.mark = ","), bg_color = "#3498DB") %>%
add_value_box(title = "Variables", value = "7", bg_color = "#27AE60") %>%
end_value_box_row() %>%
add_divider() %>%
add_viz(x_var = "degree", title = "Education Distribution")
# Assemble page
dashboard_page <- create_page("Dashboard") %>%
add_content(dashboard_content)
print(dashboard_page)
```
```{r}
dashboard_page %>% preview()
```
## ⚙️ Page Settings
### Icons
Icons appear in the navbar next to page names, helping users quickly identify different sections of your dashboard. Use the `icon` parameter with an icon code from any [Iconify](https://icon-sets.iconify.design/) icon set:
```{r}
page_with_icon <- create_page("Charts", icon = "ph:chart-bar-fill", data = gss, type = "bar") %>%
add_viz(x_var = "degree", title = "Education")
print(page_with_icon)
```
Popular icons from [Phosphor Icons](https://phosphoricons.com/):
| Icon |
Code |
|
ph:house-fill |
|
ph:chart-bar-fill |
|
ph:chart-line |
|
ph:users-fill |
|
ph:info-fill |
|
ph:gear-fill |
See `vignette("advanced-features")` for more icon options and styling.
### Navbar Alignment
By default, pages appear on the left side of the navbar. Use `navbar_align = "right"` to push pages to the right side - useful for utility pages like "Settings", "About", or "Help" that shouldn't be the main focus:
```{r}
settings_page <- create_page("Settings", navbar_align = "right") %>%
add_text("This page appears on the right side of the navbar.")
print(settings_page)
```
### Page-Level Defaults
Just like with `create_content()`, you can set visualization defaults that apply to all charts on the page. Set them once in `create_page()`, and they flow through to all `add_viz()` calls. Individual visualizations can still override these defaults:
```{r}
styled_page <- create_page(
"Survey Results",
data = gss,
type = "bar",
color_palette = c("#3498DB"),
drop_na_vars = TRUE
) %>%
add_viz(x_var = "degree", title = "Education (default blue)") %>%
add_viz(x_var = "happy", title = "Happiness (custom red)", color_palette = c("#E74C3C"))
print(styled_page)
```
```{r}
styled_page %>% preview()
```
### Loading Overlays
For pages with many charts or complex visualizations, loading overlays provide visual feedback while content renders. The overlay covers the page with a spinner and optional message, then fades out once charts are ready. This improves perceived performance and prevents users from seeing partially-loaded content.
> **See it in action:** Check out the [Loading Overlay Demo](../live-demos/overlay/index.html) - reload to see all overlay themes in action.
**Note:** Loading overlays are only visible when viewing the generated dashboard (not in `preview()`). To see them in action, generate a dashboard with `generate_dashboard()` and open it in a browser.
```{r}
overlay_page <- create_page(
"With Overlay",
data = gss,
type = "bar",
overlay = TRUE,
overlay_theme = "glass",
overlay_text = "Loading visualizations...",
overlay_duration = 1500
) %>%
add_viz(x_var = "degree", title = "Education")
print(overlay_page)
```
#### Overlay Themes
| Theme | Description |
|-------|-------------|
| `"glass"` | Semi-transparent frosted glass effect (default) |
| `"light"` | Clean white background with subtle shadow |
| `"dark"` | Dark background, good for dark-themed dashboards |
| `"accent"` | Uses your dashboard's accent color |
#### Overlay Options
| Parameter | Description | Default |
|-----------|-------------|---------|
| `overlay` | Enable/disable loading overlay | `FALSE` |
| `overlay_theme` | Visual style | `"glass"` |
| `overlay_text` | Message shown during loading | `"Loading..."` |
| `overlay_duration` | Minimum display time (ms) | `1000` |
## 📑 Pagination
Pagination creates **page breaks** within a single navbar page, splitting content into scrollable sections.
```{r}
paginated <- create_page("Long Report", data = gss, type = "bar") %>%
add_text("## Section 1: Demographics") %>%
add_viz(x_var = "degree", title = "Education") %>%
add_viz(x_var = "race", title = "Race") %>%
add_pagination() %>%
add_text("## Section 2: Attitudes") %>%
add_viz(x_var = "happy", title = "Happiness") %>%
add_pagination() %>%
add_text("## Section 3: Summary") %>%
add_text("Key findings from this analysis...")
print(paginated)
```
| Context | Behavior |
|---------|----------|
| `preview()` | Content appears continuously (no breaks) |
| Generated dashboard | Creates separate scrollable sections |
**When to use:**
- Long analysis pages with distinct sections
- Report-style dashboards
- Sequential workflows
> **Note:** For truly separate pages in the navbar, use multiple `create_page()` calls instead.
## 👁️ Previewing Pages
Preview pages the same way as content collections:
```{r, eval=FALSE}
page %>% preview()
```
The same [preview limitations](content-collections.html#previewing-content) apply.
## 📊 Data Inheritance
When you set `data` on a page, content collections inherit it:
```{r}
# Content WITHOUT data
charts <- create_content(type = "bar") %>%
add_viz(x_var = "degree", title = "Education")
# Page WITH data - charts will use page's data
page <- create_page("Analysis", data = gss) %>%
add_content(charts)
print(page)
```
If a content collection has its own data, it takes precedence over page data.
## ➡️ Next Steps
Once you have pages, add them to a dashboard:
```r
create_dashboard(title = "GSS Explorer", output_dir = "output") %>%
add_pages(home, analysis, about) %>%
generate_dashboard(render = TRUE)
```
See `vignette("dashboards")` for dashboard creation details, and `vignette("advanced-features")` for tab styling and navbar customization.