posit-dev / brand-yml

Unified branding with a single yaml file.
https://posit-dev.github.io/brand-yml/
MIT License
33 stars 4 forks source link

Formalize location of Bootstrap variables and settings #32

Open gadenbuie opened 1 month ago

gadenbuie commented 1 month ago

Currently, Quarto passes color.palette directly to Sass as Sass variables. This is certainly helpful; it means that users can do things like this

color:
  palette:
    charcoal-black: "#1A1A1A"
    navbar-bg: charcoal-black
    enable-rounded: "false"

However, it's problematic for a few reasons:

  1. I don't like the blending of concerns; this opens the door for color.palette to hold information that isn't about the actual color palette, which will be confusing to people using brand via the Python or R packages.

  2. I anticipate some changes to behavior for color in the Python and R packages that will specifically assume these values are colors. The biggest is that we plan to turn values in color.palette into $brand-{name}: {color} Sass (and CSS variables).

  3. I can also see adding utilities that will make a strong assumption that these values point to colors, e.g. using libraries to manipulate colors in R or Python.

  4. Finally, a smaller issue is that the type checking of color.palette requires values be strings, which means we need enable-rounded: "false" instead of enable-rounded: false.

I propose that we consolidate on a common place to pass variables to Bootstrap that can be picked up by both Shiny and Quarto: default.bootstrap. (This would also be useful for pkgdown, rmarkdown and more.) We'd reserve default.bootstrap.version to track required version (as a major version value, i.e. currently defaulting to 5). All other variables would be passed into the defaults layer.

The above example would become

color:
  palette:
    charcoal-black: "#1A1A1A"

defaults:
  bootstrap:
    version: 5 # optional
    navbar-bg: $brand-charcoal-black
    enable-rounded: false

Notice that a general principle of defaults is that once you're adding settings there, you're clearly targeting a specific output. So we can directly use Sass variables rather than relying on the color substitution we do in color and typography. Having a consistent pattern for accessing the brand color palette means defaults.bootstrap.navbar-bg can directly use $brand-charcoal-black.

gadenbuie commented 1 month ago

@cscheid I hope you don't mind; I implemented the above behavior in https://github.com/quarto-dev/quarto-cli/pull/11108

cscheid commented 1 month ago

@cscheid I hope you don't mind; I implemented the above behavior in quarto-dev/quarto-cli#11108

I don't mind at all. It's a longer PR so the review will take me a bit of time to think it through.

gadenbuie commented 1 month ago

@cscheid I alluded to this in the quarto PR, but this was part of the design documentation here: https://connect.posit.it/brand-yml/brand/color.html#additional-color-features. I'm working on cleaning up the docs now and this part will be clearer when we trim down to "just the implementation" and remove some of the design exploration.

Automatic color definitions

For specific outputs formats, we will automatically make the brand color palette available. In HTML/Bootstrap settings, for instance, this would mean creating $brand-{name} (Sass) and --brand-{name} (CSS) variables for each color in color.palette. We could similarly define the brand colors in LaTeX and Typst formats.

For example, using the following color palette definition

color:
  palette:
    blue: "#447099"
    orange: "#EE6331"
    gray: "#404041"
    white: "#FFFFFF"
    teal: "#419599"
    green: "#72994E"
    burgundy: "#9A4665"

would result in the following Sass for Bootstrap.

// Brand colors ---------
$brand-blue: #447099;
$brand-orange: #EE6331;
$brand-gray: #404041;
$brand-white: #FFFFFF;
$brand-teal: #419599;
$brand-green: #72994E;
$brand-burgundy: #9A4665;

:root {
  --brand-blue: #{$brand-blue};
  --brand-orange: #{$brand-orange};
  --brand-gray: #{$brand-gray};
  --brand-white: #{$brand-white};
  --brand-teal: #{$brand-teal};
  --brand-green: #{$brand-green};
  --brand-burgundy: #{$brand-burgundy};
}
cscheid commented 1 month ago

Great, thank you!

gadenbuie commented 2 weeks ago

We talked about this internally, but defaults.bootstrap being only variables seems like it will end up being too constraining. In Shiny implemented defaults.shiny.theme.{functions,defaults,mixins,rules}, and I think we should do something similar for defaults.bootstrap.

E.g. instead of

defaults:
  bootstrap:
    enable-rounded: false
    link-decoration: none

this would work

defaults:
  bootstrap:
    defaults:
      enable-rounded: false
      link-decoration: none
    rules: |
      h2 { color: pink }