bslib icon indicating copy to clipboard operation
bslib copied to clipboard

navsets not rendering correctly with quarto

Open kelly-sovacool opened this issue 1 year ago • 4 comments

navsets are rendering correctly in rmarkdown but not quarto. The tab/pill/etc appears as plain html, regardless of which navset_* is used.

rmarkdown

---
title: "bslib rmarkdown"
output: 
  html_document:
    theme:
      version: 5
---


```{r message = FALSE}
library(bslib)
library(ggplot2)
library(plotly)

p1 <- ggplot(mpg, aes(displ, hwy)) +
  geom_point()
p2 <- ggplot(mpg, aes(cty, hwy)) +
  geom_point()

navset_tab(nav_panel(title = 'one', ggplotly(p1)), 
           nav_panel(title = 'two', ggplotly(p2)))
```
image

quarto

---
title: "bslib quarto"
format: html
---


```{r message = FALSE}
library(bslib)
library(ggplot2)
library(plotly)

p1 <- ggplot(mpg, aes(displ, hwy)) +
  geom_point()
p2 <- ggplot(mpg, aes(cty, hwy)) +
  geom_point()

navset_tab(nav_panel(title = 'one', ggplotly(p1)), 
           nav_panel(title = 'two', ggplotly(p2)))
```
image

Versions

  • bslib 0.5.1.9000
  • quarto 1.3.450

kelly-sovacool avatar Oct 13 '23 19:10 kelly-sovacool

Thanks for opening this issue with such a clear reprex, @kelly-sovacool! At the moment, this is a known problem and something that we're actively thinking about how to solve.

The issue stems from how bslib creates the tab HTML, which follows the syntax of older versions of Bootstrap so that we can provide backwards compatibility for Shiny apps. In bslib and shiny we solve this by aligning the CSS of newer versions of Bootstrap with the older syntax.

But Quarto uses its own version of Bootstrap and suppresses anything from bslib, so our fixes can't currently be loaded in Quarto documents.


@cpsievert I'm starting to think that the bs3compat bundle should be a separate set of dependencies that we could attach directly to specific components, like navset_tab(). It's also worth noting that calling bs_theme_dependencies(bs_theme(preset = "bootstrap")) in a Quarto doc will add everything from our theme dependencies except Bootstrap, which is very specifically suppressed.

In fact, I can get pretty reasonable results by adding the following to the document (but note to anyone trying this that it loads Bootstrap twice, which isn't ideal):

bs_theme_dependencies(bs_theme(preset = "bootstrap")) |>
  lapply(function(x) {
    if (x$name == "bootstrap") {
      x$name <- "bootstrap-from-bslib"
    }
    x
  }) |>
  htmltools::tagList()

image

gadenbuie avatar Oct 17 '23 14:10 gadenbuie

I'm starting to think that the bs3compat bundle should be a separate set of dependencies that we could attach directly to specific components,

I agree that we should probably separate it out (and include it with the return value of bs_theme_dependencies()). Especially since the JS for it is already in a separate HTML dependency.

I'm not sure how I feel about attaching it at the component level, though. It'd obviously be useful for getting this particular example working, but a good chunk of the bs3compat is to target HTML/components that we aren't in control of.

I was thinking/hoping that we could detect whether tabs are being created in a Quarto doc (is there something like isTRUE(getOption('knitr.in.progress')) for Quarto?), then emit markup for BS5+ in that case. This would have the added benefit of working better with CSS written with BS5+ in mind (e.g., Bootswatch, Quarto styles, user code, etc)

cpsievert avatar Oct 17 '23 15:10 cpsievert

Here are the options set by quarto during render: https://github.com/quarto-dev/quarto-cli/blob/749a3527a8a79ccc1f601ce1f2b62dd2b90a7528/src/resources/rmd/execute.R#L255-L279

It looks like we could rely on !is.null(knitr::opts_knit$get("quarto.version")) as the signal that we're in the process of rendering for Quarto.

gadenbuie avatar Oct 17 '23 17:10 gadenbuie

EDIT: This is only occurring within the RStudio browser. When I view in a web browser the issue resolves. Maybe need to update my version of RStudio.

I'm having the same issue with shiny when running bslib::bs_theme_preview() or when running any other bslib themed shiny app. image

Is there a temporary workaround using something along the lines of @gadenbuie's quarto code?

bs_theme_dependencies(bs_theme(preset = "bootstrap")) |>
  lapply(function(x) {
    if (x$name == "bootstrap") {
      x$name <- "bootstrap-from-bslib"
    }
    x
  }) |>
  htmltools::tagList()

I'm not sure how to include/add that to how I currently make my theme

my_theme <- function(...) {
  style <- normalizePath("www/styles.scss")
  theme <- bslib::bs_theme(
    version = 5,
    preset = "bootstrap"
  )
  theme <- bslib::bs_add_rules(theme, sass::sass_file(style))
  theme
}

David-Rattray avatar Jan 04 '24 17:01 David-Rattray