---
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")
```
