--- title: "Theming a Shiny app with NDPalette" output: rmarkdown::html_vignette: toc: true vignette: > %\VignetteIndexEntry{Theming a Shiny app with NDPalette} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.align = "center", fig.width = 7, fig.height = 4.5, dpi = 96, out.width = "100%" ) library(NDPalette) has_ggplot2 <- requireNamespace("ggplot2", quietly = TRUE) if (has_ggplot2) { library(ggplot2) theme_set(theme_minimal(base_size = 12)) } knitr::opts_chunk$set(eval = has_ggplot2) ``` `NDPalette` carries the same Notre Dame colors through every layer of an interactive report, so a Shiny app's page chrome, its prose, and its figures all read as one brand palette. This vignette builds a small, complete app, explains the three pieces that do the theming, and closes with a showcase of every color the package provides, with notes on what each is for. It is an independent project, not affiliated with or endorsed by the University. A Shiny app themed with `NDPalette` rests on three pieces: 1. a **`bslib` theme** whose Bootstrap colors are pulled from the palette with `nd_color()`, so buttons, links, and headers are brand-colored; 2. the **`scale_*_nd()` scales**, so every figure is painted from the same palette; and 3. a **non-white background** from `nd_tints` or `nd_informal_tints`. # A complete example app The app below is shipped with the package. Run it with: ```{r run, eval = FALSE} shiny::runApp(system.file("examples", "nd-shiny-app", package = "NDPalette")) ``` Its full source (`inst/examples/nd-shiny-app/app.R`), shown straight from the installed file so it never drifts from what actually runs: ```{r app-source, echo = FALSE, comment = "", eval = TRUE} cat(readLines(system.file("examples", "nd-shiny-app", "app.R", package = "NDPalette")), sep = "\n") ``` Beyond the theming, the app lets you **switch among three page backgrounds** (plain white, the informal soft white, and the informal soft yellow) live with `session$setCurrentTheme()`, **shows the exact `bs_theme()` code** in a panel you can show or hide with a checkbox, with a **Copy** button that puts it on the clipboard, and a **Download palette (CSV)** button. Three small pieces do that work: ```{r app-extras, eval = FALSE} # 1. The three backgrounds (white, plus two soft informal tints): bg_choices <- c("White" = "#ffffff", "Soft white" = nd_informal_tints[["soft_white"]], "Soft yellow" = nd_informal_tints[["soft_yellow_light"]]) # 2. Re-theme live when the choice changes: observeEvent(input$bg, session$setCurrentTheme(nd_theme(bg_choices[[input$bg]]))) # 3. A copy-to-clipboard button for the shown code (plain HTML + JS): tags$button("Copy", class = "btn btn-sm btn-primary", onclick = "navigator.clipboard.writeText( document.getElementById('themecode').innerText)") ``` The three page backgrounds, side by side --- plain white and two soft informal tints, all carrying navy text. (For an even lighter touch, the `faint_white` and `faint_yellow` tints sit just off pure white.) ```{r bg-compare, eval = TRUE, echo = FALSE, fig.height = 2.2, fig.width = 9} bgs <- c("White" = "#ffffff", "Soft white" = unname(nd_informal_tints[["soft_white"]]), "Soft yellow" = unname(nd_informal_tints[["soft_yellow_light"]])) op <- par(mfrow = c(1, 3), mar = c(0, 0, 1.8, 0)) for (nm in names(bgs)) { plot.new(); plot.window(c(0, 1), c(0, 1)) rect(0, 0, 1, 1, col = bgs[[nm]], border = "grey80") title(sprintf("%s (%s)", nm, bgs[[nm]]), col.main = nd_color("navy")) text(0.5, 0.56, "Notre Dame", col = nd_color("navy"), font = 2, cex = 1.6) text(0.5, 0.40, "navy on a soft page", col = nd_color("navy")) } par(op) ``` # How the theming works ## A brand-colored `bslib` theme `bslib::bs_theme()` accepts colors for the Bootstrap roles. Pulling them from `nd_color()` ties the page chrome to the palette: navy foreground and primary, bright gold secondary, on a soft background. ```{r theme-code, eval = FALSE} nd_theme <- bslib::bs_theme( version = 5, bg = nd_informal_tints[["soft_yellow"]], # soft, non-white page fg = nd_color("navy"), primary = nd_color("navy"), secondary = nd_color("bright_gold") ) ``` For a more reserved page, use one of the official Warm Whites instead of the informal soft yellow, for example `bg = nd_tints[["warm_white"]]`. ## Brand-colored figures Inside `renderPlot()`, the `scale_*_nd()` scales paint the figure from the same palette the page uses. They take a `palette` argument, so the app's palette selector can switch a plot between the default Notre Dame colors and the colorblind-friendly ordering: ```{r fig-demo, fig.height = 4} set.seed(113) df <- data.frame(x = rnorm(120), y = rnorm(120), group = factor(rep(LETTERS[1:3], length.out = 120))) ggplot(df, aes(x, y, color = group)) + geom_point(size = 2, alpha = 0.85) + scale_color_nd(palette = "nd_cvd") + labs(color = NULL) ``` ## Reusing the R Markdown stylesheet For a Shiny app that leans on plain HTML rather than Bootstrap components, the package's R Markdown stylesheet can be included directly, which also sets the soft Warm White page background: ```{r includecss, eval = FALSE} ui <- fluidPage( shiny::includeCSS(nd_css_path()), titlePanel("My Notre Dame app") # ... ) ``` # All the colors, with details The app's palette selector exposes the three palettes; the catalog behind them is shown here in full, with a note on what each group is for. ## The default Notre Dame palette (`"nd"`) Thirteen data colors: six leading brand colors that read clearly on white, then seven former Notre Dame colors to extend the set past six. This is the palette `scale_*_nd()` uses by default. ```{r nd, eval = TRUE, fig.height = 1.8, fig.width = 9} pal <- nd_palette() named <- nd_colors[match(pal, nd_colors$hex), ] show_palette(pal, labels = named$name) ``` ## The colorblind-friendly ordering (`"nd_cvd"`) The same Notre Dame colors, reordered so the first several stay distinguishable under simulated deuteranopia, protanopia, and tritanopia. Ten anchors, leading with the CVD-safe ND Blue and Bright Gold. Reach for it with `scale_color_nd(palette = "nd_cvd")` when colorblind safety matters more than leading with the brand colors. ```{r cvd, eval = TRUE, fig.height = 1.8, fig.width = 9} show_palette(nd_palette(palette = "nd_cvd")) ``` ## The former Notre Dame colors (`"former"`) Seven historical brand colors, no longer in the current brand guide, kept to widen the categorical palette. They are approximate, legacy colors and should not be read as current Notre Dame colors. ```{r former, eval = TRUE, fig.height = 1.6, fig.width = 8} show_palette(nd_palette(palette = "former")) ``` ## Near-white brand tints and informal backgrounds `nd_tints` holds the four official near-white Notre Dame tints, for page or panel backgrounds, fills, and the light end of a sequential ramp. They are too light to read as data colors and are never returned by `nd_palette()`. ```{r tints, eval = TRUE} nd_tints ``` `nd_informal_tints` holds four warm backgrounds, from a light warm white to a warmer soft yellow. These are **not** Notre Dame brand colors; they are alternatives to a white background (the example app offers white, soft white, and soft yellow). ```{r informal, eval = TRUE} nd_informal_tints ``` ## The full color catalog `nd_colors` is the complete reference: every color the package knows about, labeled with its brand (University, Athletics, or none for the informal backgrounds) and its role. `nd_color()` pulls any of them out by name or by role. ```{r catalog, eval = TRUE} nd_colors ``` ```{r by-name, eval = TRUE} # The two current primaries, and a former color, by name. nd_color("navy", "metallic_gold", "maroon") # A whole role group. nd_color(role = "tint") ```