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

Make ioslides_presentation() more themable via {bslib} and {sass} #2013

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

cpsievert
Copy link
Contributor

@cpsievert cpsievert commented Jan 20, 2021

This PR makes ioslides_presentation()'s CSS more aware of bslib::bs_theme()'s main colors & fonts. That is, you can now customize the main colors and fonts in the CSS behind ioslides_presentation() in a similar way to how we can now customize the Bootstrap CSS behind html_document() via {bslib}, for example:

---
title: "Hello themed IO Slides!"
output: 
  ioslides_presentation:
    theme:
      bg: "#101010"
      fg: "#FDF7F7"
      primary: "#ED79F9"
      base_font: !expr bslib::font_google("Prompt")
      code_font: !expr bslib::font_google("JetBrains Mono")
---

```{r setup, include=FALSE}
thematic::thematic_rmd()
```

## R Markdown

This is an R Markdown presentation. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see <http://rmarkdown.rstudio.com>.

When you click the **Knit** button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document.

Some inline `code`.

## Slide with Bullets

- Bullet 1
- Bullet 2
- Bullet 3

## Slide with R Output

```{r cars, echo = TRUE}
summary(cars)
```

## Slide with Plot

```{r pressure}
plot(pressure)
```

This also works with bslib+shiny's "real-time" theming capabilities:

---
title: "Hello themed IO Slides!"
output: 
 ioslides_presentation:
   theme: !expr bslib::bs_theme()
runtime: shiny
---

```{r setup, include=FALSE}
bslib::bs_themer()
thematic::thematic_shiny()
```

## R Markdown

This is an R Markdown presentation. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see <http://rmarkdown.rstudio.com>.

When you click the **Knit** button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document.

Some inline `code`.

## Slide with Bullets

- Bullet 1
- Bullet 2
- Bullet 3

## Slide with R Output

```{r cars, echo = TRUE}
summary(cars)
```

## Slide with Plot

```{r pressure}
renderPlot({
 plot(pressure)
})
```

@cpsievert
Copy link
Contributor Author

@cderv @yihui this one should be ready to merge if you feel it's worth taking on (and happy to answer any questions!)

@yihui yihui requested a review from cderv February 4, 2021 18:32
@apreshill
Copy link
Contributor

Hi @cpsievert -

This works nicely for me- thank you! I'm confused about how to change the text color though. I have:

---
title: "Hello themed IO Slides!"
output: 
  ioslides_presentation:
    theme:
      bg: "#f3e0e1"
      fg: "#0144a3"
      primary: "#0144a3"
      base_font: !expr bslib::font_google("Lato")
      heading_font: !expr bslib::font_google("Petrona")
      code_font: !expr bslib::font_google("DM Mono")
---

But in my knitted slides, the text is:

.title-slide hgroup h1 {
    font-size: 65px;
    line-height: 1.4;
    letter-spacing: -3px;
    color: #5f81bb; <- not my color
}

I am new to bslib, but looking at the docs it seems that fg should be affecting the color.

Copy link
Collaborator

@cderv cderv left a comment

Choose a reason for hiding this comment

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

Thanks for all this @cpsievert !

First let me say, It was a great way for me to dive on how bslib and sass integrates with a format. I think I understand it better now but it is not yet perfect. So, just to clarify for me: We don't really use bootstrap 4 here but only some of its variables that were integrated into the default.scss so that we can render a custom css. Is that right ? Would sass alone would have been enough to achieve the same ? But we use bs_dependency here, so does this mean that all boostrap is available in ioslide document ?

Back to the review: the comments I made below are mainly feedback to discuss. ioslides_presentation does not currently provide a theme argument, so I think we need to take care of checking that it is not to be confuse with the one from other format. In the case of ioslides, it mainly allow to pass variables to change the default CSS using bslib features. We should prevent / guide against the known usage for other formats usually for BS3. Also, it differs a bit with html_document because you can only pass a subset of variables - maybe we should be more verbose to guide users.

Regarding tests, I did with simple examples for now and it works well. I am not yet used to bootstrap variable, so it is not easy to see which variables change what, but the shiny app helps. I only found one difference in CSS not related to color so I have a question. (See below)

I assume you have tested this on several example documents like for html_document ?

When using thematic_shiny with your example, I have a bunch of warning in the R Markdown pane:

WARNING: Found no color leading to 3:1 contrast ratio against #F46D8D...
         on line 41:5 of ../../R/win-library/4.0/bslib/sass-utils/color-contrast.scss, in function `color-contrast`
         from line 7:10 of ../../R/win-library/4.0/bslib/lib/bs/scss/mixins/_buttons.scss, in mixin `button-variant`
         from line 75:14 of ../../R/win-library/4.0/bslib/lib/bs/scss/_buttons.scss
         from line 37:9 of stdin

Is this something related to this PR ? I installed the last dev version of bslib, thematic and sass.

Anyway, thanks for this PR and let's discuss the suggested changes and questions below.

#' \code{...} to ellipses.
#' @param theme a list of theming arguments (currently `bg`, `fg`, `primary`,
#' `success`, `warning`, `danger`, `base_font`, and `code_font` are supported,
#' see [bslib::bs_theme()] for more about these options)
Copy link
Collaborator

Choose a reason for hiding this comment

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

We don't use yet the markdown syntax by default in this package. So you need to use usual Rd syntax or set @md in this specific doc.

If we do the latter, we may take the opportunity to convert this whole help page.
The former is easier for you as this is one link.

# If bslib is relevant, we want to register a _deferred_ version of the CSS dependency so
# it can update in response to Shiny's session$setCurrentTheme() (e.g., bslib::bs_themer())
# https://rstudio.github.io/bslib/articles/theming.html#dynamic-theming-in-shiny
theme <- resolve_theme(theme)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I wonder if we should provide a more specific handling / checking of the theme argument for this specific format. ioslides_presentation had no argument before that because it did not support a theme as other formats. Introducing this argument may be confusing compared to other format because it will be different: Only a list to pass to bslib will be supported.

For example, using

  ioslides_presentation:
    theme: cerulean

will issue no warning or error. It will do nothing, so not harmful but some users could expect this to work as other formats. (even if the doc does not say so).

Maybe we can check early and warn that will have not effect (or stop and say only bslib is supported so a list.
Something like

Suggested change
theme <- resolve_theme(theme)
if (!is.null(theme) && is.character(theme)) {
stop("With 'ioslides_presentation', 'theme' only works with bslib package and must be a list.", call. = FALSE)
}
theme <- resolve_theme(theme)

We could also modify the resolve_theme function to add enforce_bslib = FALSE argument.
When set to TRUE, it would error if the theme provided is not a list to pass to bslib::bs_theme. (and not just return the match.arg among BS3 theme.

It could also be allow_bs3 = TRUE by default, that would do the above when set to FALSE.

We would have for this format.

Suggested change
theme <- resolve_theme(theme)
theme <- resolve_theme(theme, allow_bs3 = FALSE)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Using ioslides_presentation: theme: cerulean will issue no warning or error. It will do nothing, so not harmful but some users could expect this to work as other formats.

This does do something though -- it brings in Bootstrap! So, I don't think we want to introduce an error in this case -- I'm sure folks are relying on this functionality.

Comment on lines +490 to +491
theme <- resolve_theme(theme)
if (!is_bs_theme(theme)) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

We are already doing this on the outside of the function. As ioslides_presentation is not exported, can't we assume that theme argument is not NULL will always be a bslib compatible theme ?

Aim is just to avoid some duplication of logic in different places.

Comment on lines +505 to +507
if ("3" %in% theme_version(theme)) {
stop("`ioslides_presentation()` is not compatible with Bootstrap 3 (use version = 4 or higher)")
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I feel this should be tested in the format function ioslides_presentation directly when we detect bslib is in use.


/* line 62, ../scss/default.scss */
slides > slide {
color: mix($body-bg, $body-color, 47.5%);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is there a reason to have removed the font-size here ? Seems like a mistake as you removed font-family from other rules but not font-size

This cause the default theme to not have the same font size. I just tried for example:

  ioslides_presentation:
    theme:
      code_font: !expr bslib::font_google("JetBrains Mono")

to compare

Suggested change
color: mix($body-bg, $body-color, 47.5%);
font-size: 26px;
color: mix($body-bg, $body-color, 47.5%);

@cderv
Copy link
Collaborator

cderv commented Feb 8, 2021

@apreshill the CSS rule that will be processed by sass is this one:

.title-slide hgroup h1 {
  font-size: 65px;
  line-height: 1.4;
  letter-spacing: -3px;
  color: mix($body-bg, $body-color, 32%);
}

So color is a mix of bg and fg provided.

What was the color you expected ? Does the mix does not correspond ?

As a side note, I tried to test using this code, but it does not output the same color 😅 It must be more complexe than that with other variables in the mix.

> sass::sass(
+ list(list(`body-bg` = "#f3e0e1", `body-color` = "#0144a3"),
+ ".title-slide hgroup h1 {
+   font-size: 65px;
+   line-height: 1.4;
+   letter-spacing: -3px;
+   color: mix($body-bg, $body-color, 32%);
+ }"))
/* CSS */
.title-slide hgroup h1 {
  font-size: 65px;
  line-height: 1.4;
  letter-spacing: -3px;
  color: #4e76b7;
}

@cpsievert
Copy link
Contributor Author

cpsievert commented Feb 8, 2021

We don't really use bootstrap 4 here but only some of its variables that were integrated into the default.scss so that we can render a custom css. Is that right?

Yep, this PR is currently tying the ioslide's Sass variables to Bootstrap Sass variables, allowing us to compile the ioslide Sass with Bootstrap's variables. Thus, there is some implied risk that Bootstrap variables will change in a future version, but the variables we're listening to here ($body-bg, $body-color, etc) are so fundamental that I don't foresee that happening.

Would sass alone would have been enough to achieve the same?

No, but this is a direction worth thinking more seriously about, especially for Bootstrap-less HTML formats like ioslides, html_vignette, etc. Setting up a Sass-based color system that works without Bootstrap would be easy enough for this format, but you'd lose the font file importing that font_google()/font_link() provides. I've been thinking, though, that we should probably provide similar functions in the {sass} package itself.

But we use bs_dependency here, so does this mean that all bootstrap is available in ioslide document ?

Yea, that was the main thing I was torn about in this PR. That is, currently if you provide a theme, then you also get all of Bootstrap included, and there is currently no way to opt-out of that behavior. Seems like it'd be better to not include Bootstrap when theme is provided (for Bootstrap-less HTML formats like ioslides, html_vignette, etc), but have another argument to opt-in to including Bootstrap as well. Give me some time to think about this and we'll revisit this format as well as html_vignette in a future version of {rmarkdown}

When using thematic_shiny with your example, I have a bunch of warning in the R Markdown pane:

You're seeing rstudio/bslib#242

@cderv
Copy link
Collaborator

cderv commented Feb 8, 2021

Give me some time to think about this and we'll revisit this format as well as html_vignette in a future version of {rmarkdown}

No problem. We are not in a hurry for this, and I think we need to it right for those Bootstrap-less format to make it easy to use and easy to teach. Let's revisit later then and get some more feedback in the meantime.

@cderv cderv marked this pull request as draft February 9, 2022 15:44
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.

3 participants