Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Move ui.Theme.from_brand() Sass code into an .scss file #1792

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

gadenbuie
Copy link
Collaborator

The main goal is to move as much Sass code and logic out of Python and into a single _brand-yml.scss layer file, building on #1790.

There's a small amount of code insertion that still needs to happen, these places are marked in the Sass file with special comments, e.g.

/*-- scss:defaults --*/

/*-- insert(brand.color.palette:defaults) --*/
/*-- insert(brand.defaults:defaults) --*/
/*-- insert(brand.color:defaults) --*/
/*-- insert(brand.typography:defaults) --*/

As part of this, we now push a set of brand-specific Sass variables and primarily use these to set other values, e.g.

$brand_typography_base_family: Open Sans !default; // optional, added if brand.typography.base.family is present

// ... later ...
$brand_typography_base_family: null !default; // always included to prevent errors

// ... later ...
$font-family-base: $brand_typography_base_family !default; // Set Bootstrap variables

Note that we can't use the null !default set up for the Bootstrap core variables like $primary or $secondary etc. because the null value ends up infiltrating into places where it's not valid.

@gadenbuie gadenbuie requested a review from cpsievert December 4, 2024 20:24
Comment on lines 217 to 221
self._insert_sass("brand.color.palette:defaults", brand_color_palette_defaults)
self._insert_sass("brand.defaults:defaults", brand_bootstrap_defaults)
self._insert_sass("brand.color:defaults", brand_color_defaults)
self._insert_sass("brand.typography:defaults", brand_typography_defaults)
self._insert_sass("brand.color.palette:rules", brand_color_palette_rules)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any chance this could be done with .add_defaults() and .add_rules() instead of ._insert_sass()?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe? But it'd be a quite a bit more complicated and would reduce the portability of the Sass file. Obviously we can't add a new section without writing new Python/R code, but with this implementation we can adjust this Sass file directly without having to then carefully considering the order of operations that need to happen in the Python/R code.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also like that you can look at the Sass file and have a sense of the pieces that are going to be added.

Also string substitution isn't elegant but it's certainly easy to do in both Python and R and both implementations will basically be the same thing. It's likely that using the Sass layer mechanisms will work out to look pretty similar in both languages, but it certainly increases the context window of things you need to understand.

In other words, I'm going for a solution that, as much as possible, fits into one Sass file.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anyway, that's what I was thinking but I rewrote it to use standard Sass methods and I don't hate it. 4ddf0f5

Removes the `_insert_sass()` method to use standard `ui.Theme()` methods
shiny/ui/_theme_brand.py Outdated Show resolved Hide resolved
@gadenbuie gadenbuie requested a review from cpsievert December 4, 2024 22:21
shiny/ui/_theme_brand.py Outdated Show resolved Hide resolved
Comment on lines +76 to +79
$body-secondary-color: $brand_color_secondary !default;
$body-secondary: $brand_color_secondary !default;
$body-tertiary-color: $brand_color_tertiary !default;
$body-tertiary: $brand_color_tertiary !default;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe let's save this for another PR, but from a quick look, it seems $body-secondary and $body-tertiary don't exist?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a good chance I copied this from the Quarto implementation. I'll check.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines +211 to +212
# * brand.color.palette
# * brand.defaults (Brand-defined Bootstrap defaults)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would have expected the ordering here to be swapped (i.e., Bootstrap defaults first since they're the most specific). What's the rationale for the palette coming first?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The goal is to be able to say something like $navbar-bg: $brand-blue, which requires this order:

$brand-blue: "#2233ff";

$navbar-bg: $brand-blue;

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, ok, that feels worth it. A mention of that capability in the Sass would be great.

Copy link
Collaborator Author

@gadenbuie gadenbuie Dec 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

idk this feels a lot like the kind of comment that's explained by the code. brand.color.palette is only the brand's named colors and its Sass variables come before brand.defaults because otherwise you couldn't use them under brand.defaults. If it were the other way around, I think it'd need to be commented.

shiny/ui/_theme_brand.py Outdated Show resolved Hide resolved
Comment on lines 258 to 261
# Currently, brand.color fields are directly named after Bootstrap vars. If
# that changes, we'd need to use a map here. These values can't be set to
# `null !default` because they're used by maps in the Bootstrap mixins layer
# and cause errors if a color is `null` rather than non-existent.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup! Fixed in rstudio/bslib#1149

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants