---
title: "Theming"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Theming}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>", eval = FALSE, purl = FALSE)
```

bslibdash ships a single brand theme, [`brand_bs_theme()`], that every
page constructor applies by default. This vignette shows how to use it
as-is, tweak individual Bootstrap variables, add your own SCSS, swap to
a different Bootswatch preset, and tune the theme interactively with
`bslib::bs_themer()`.

For the building blocks underneath, see the
[bslib theming articles](https://rstudio.github.io/bslib/articles/theming/).

## The default theme

`brand_bs_theme()` returns a `bslib::bs_theme()` built on Bootstrap 5
(`bootswatch = "bootstrap"`) with the bslibdash brand colour and typography
defaults. Component CSS is not baked into the theme - each bslibdash component
attaches its own theme-aware SCSS via `bslib::bs_dependency_defer()`, so
swapping `theme` does not drop bslibdash styles. Key variable defaults:

| Variable        | Value                          |
|-----------------|--------------------------------|
| `primary`       | `#0460A9`                      |
| `body-color`    | `#111827`                      |
| `border-radius` | `.75rem`                       |
| `font-family`   | System UI stack                |
| `enable-shadows`| `TRUE` (subtle, layered)       |

## Overriding theme variables

Use `bslib::bs_add_variables()` to override individual Bootstrap Sass
variables and pass the result to any page constructor:

```{r purl=FALSE}
library(shiny)
library(bslibdash)

theme <- brand_bs_theme() |>
  bslib::bs_add_variables(
    primary       = "#8B0000",
    `body-color`  = "#1F2937",
    `font-size-base` = "0.95rem"
  )

ui <- dashboardPage(
  header  = dashboardHeader(title = "Maroon dashboard"),
  sidebar = dashboardSidebar(),
  body    = dashboardBody(),
  theme   = theme
)
```

Component status colours (`primary`, `success`, ...) automatically pick
up the new variable values, so cards, buttons, badges and value boxes
re-skin together.

## Adding custom SCSS

Add bespoke rules with `bslib::bs_add_rules()`:

```{r purl=FALSE}
theme <- brand_bs_theme() |>
  bslib::bs_add_rules("
    .app-header { background: linear-gradient(90deg, #0460A9, #003a6e); }
    .app-footer { font-size: 0.85rem; }
  ")
```

## Switching the Bootswatch preset

```{r purl=FALSE}
theme <- bslib::bs_theme(version = 5, bootswatch = "flatly") |>
  bslib::bs_add_variables(primary = "#0460A9")

dashboardPage(
  header = dashboardHeader(title = "Flatly + brand blue"),
  sidebar = dashboardSidebar(),
  body = dashboardBody(h2("Flatly + brand blue")),
  theme = theme
)
```

Note: bslibdash component CSS is attached by the components themselves,
so any `bslib::bs_theme()` - including a plain `bslib::bs_theme(version = 5)`
- still renders the package's custom classes (`.bslibdash-value-box`,
`.bslibdash-info-box`, `.app-sidebar`, ...). Use `brand_bs_theme()` when you
want the bslibdash brand defaults; use your own `bs_theme()` when you do not.

## Real-time theming

`bslib::bs_themer()` works against bslibdash pages out of the box - call it
once from your server to interactively tune colours and typography
during development:

```{r purl=FALSE}
server <- function(input, output, session) {
  bslib::bs_themer()
}
```

See the bslib
[real-time theming article](https://rstudio.github.io/bslib/articles/theming/index.html#real-time)
for the underlying widget.

## Dynamic theming

`session$setCurrentTheme()` swaps the active `bs_theme()` at runtime
without a page reload, which makes it easy to let users flip between
light/dark variants or any other named presets. Because each bslibdash
component attaches its SCSS via `bslib::bs_dependency_defer()`, the
components automatically recompile against the new theme:

```{r purl=FALSE}
library(shiny)
library(bslib)
library(bslibdash)

themes <- list(
  light = brand_bs_theme(),
  dark  = bs_theme(
    version = 5,
    bg      = "#0B0F19",
    fg      = "#E5E7EB",
    primary = "#60A5FA"
  )
)

ui <- dashboardPage(
  title  = "Theme switcher",
  header = dashboardHeader(
    rightUi = radioButtons(
      "mode", NULL,
      choices = c("light", "dark"),
      inline  = TRUE
    )
  ),
  sidebar = dashboardSidebar(
    sidebarMenu(
      id = "sidebar",
      menuItem("Overview", tabName = "overview", icon = icon("house"))
    )
  ),
  body = dashboardBody(
    fluidRow(
      valueBox(1200, "Total sales",     icon = icon("graph-up"),             color = "success"),
      valueBox(53,   "Open issues",     icon = icon("exclamation-triangle"), color = "warning"),
      valueBox(8,    "Critical alerts", icon = icon("bell"),                 color = "danger")
    ),
    fluidRow(
      infoBox(title = "CPU usage", value = "48%",
              subtitle = "Average over last 5 min",
              icon = icon("cpu"), color = "primary"),
      infoBox(title = "Queue length", value = 17,
              subtitle = "Waiting jobs",
              icon = icon("inboxes"), color = "warning")
    ),
    fluidRow(
      box(title = "Status", width = 6, status = "primary",
          "All systems nominal."),
      box(title = "Notes",  width = 6, status = "info",
          collapsible = TRUE,
          "Toggle between light and dark in the header to see the theme swap.")
    )
  ),
  theme = themes$light
)

server <- function(input, output, session) {
  observeEvent(input$mode, {
    session$setCurrentTheme(themes[[input$mode]])
  })
}

shinyApp(ui, server)
```

Use the same pattern to expose any other curated set of presets (for
example, a Bootswatch picker) - just build the `bs_theme()` objects
ahead of time and hand the chosen one to `setCurrentTheme()`. The dark
variant above is built with `bs_theme(bg = ..., fg = ..., primary = ...)`
rather than `bs_add_variables()` on the brand theme because the former
makes bslib rederive a coherent palette (greys, borders, link colours,
secondary/tertiary backgrounds) from `bg`/`fg`, while the latter only
patches the named variables. For the underlying mechanics, see
[`?bslib::bs_dependency_defer`](https://rstudio.github.io/bslib/reference/bs_dependency.html).
