rstudio/bslib

Ordering of variables in bs_theme()

Closed this issue · 3 comments

library(bslib)
#> 
#> Attaching package: 'bslib'
#> The following object is masked from 'package:utils':
#> 
#>     page

bs_theme(
  primary = "red",
  navbar_bg = "$primary"
) |>
  sass::as_sass() |>
  # show just the relevant lines for this reprex
  as.character() |>
  strsplit("\n") |>
  (\(x) x[[1]][3:5])()
#> [1] "$navbar_bg: $primary !default;" ""                              
#> [3] "$primary: #FF0000 !default;"

Created on 2024-12-02 with reprex v2.1.0

I see, this happens because ... comes before primary here

bslib/R/bs-theme.R

Lines 173 to 186 in 74a138c

bs_theme_update(
bundle, ...,
bg = bg, fg = fg,
primary = primary,
secondary = secondary,
success = success,
info = info,
warning = warning,
danger = danger,
base_font = base_font,
code_font = code_font,
heading_font = heading_font,
font_scale = font_scale
)

I'm guessing that's there to enable syntax like this:

bs_theme(
  blue = "#0000ff",
  primary = "$blue"
)

Alternatively, the other way around this is

bs_theme(navbar_bg = "$primary") |> bs_add_variables(primary = "red")
#> $primary: red !default;
#> $navbar_bg: $primary !default;

IIRC, the thinking is more along the lines of:

  1. Formal (named) arguments can have a 1-to-many (sometimes 1-to-1) Sass variable mapping. And, since they are they are a higher level of abstraction than Bootstrap variables, these should come as the 1st layer of defaults.
  2. Other variable definitions (...) should come as the 2nd layer of defaults since they should be allowed to overrule (1). And, since they are the 2nd layer, they get hoisted to the top.

The drawback to this approach is that, as you've highlighted here, you can't have "downstream" variable defaults reference "upstream" variables since they are defined yet. The main mechanism we added to workaround this problem is bs_add_variables(.where = "declarations"):

bs_theme(primary = "red") |>
  bs_add_variables("navbar-bg" = "$primary", .where = "declarations")

BTW, this section gets into this a bit more https://rstudio.github.io/bslib/articles/theming/index.html#theming-variables

Thanks for the context, this is helpful. I can see why it works the way that it does and I also can't help but wish that something like this would work:

output_format:
  html:
    theme:
      navbar-bg: $primary

I guess brand.yml gives us a chance to revisit this. Thanks for writing down your thoughts!