Skip to contents

Renders a representative sample of bslib and shiny markup under theme and returns the htmltools::htmlDependency() objects that markup attaches, deduplicated, minus the "bootstrap" and "jquery" dependencies the page function attaches itself (page_react() attaches Bootstrap only when it is given a theme). Attach the result to a shinyreact page, for example shinyreact::page_react(page_deps(app_theme), theme = app_theme), so the client gets exactly the CSS and JavaScript a matching bslib page would have attached on its own: sliderInput()'s ionRangeSlider skin, selectizeInput()'s selectize assets, bslib::accordion()'s and bslib::tooltip()'s Bootstrap bundles, and so on.

Usage

page_deps(theme = NULL, ..., components = NULL)

Arguments

theme

A bslib::bs_theme() object, or NULL for an app with no bslib theme. Pass the same theme the page gets. When not NULL, it is validated with bslib::is_bs_theme().

...

Additional tags to include in the dependency sample, unnamed (checked with rlang::check_dots_unnamed()). Use this for anything the default components sampler does not cover: a hosted third party widget (DT::DTOutput(), reactable::reactableOutput()), an icon pack, or a page-level element specific to one app.

components

Character vector of catalog sample names to render for their dependencies, or NULL (the default) to use every "tag" and "page" sample, which is deliberately generous: an unused dependency costs the page one extra download, while a missing one is a widget that renders unstyled. Pass character() to include no catalog samples at all, relying only on ....

Value

A list of htmltools::htmlDependency() objects, one per dependency name, keeping the highest version of each, and with no dependency named "bootstrap" or "jquery".

Details

"bootstrap" itself is dropped from the result because a shinyreact page already attaches its own theme through the page function's own theme= argument (or gets no theme at all); attaching it twice serves the compiled Bootstrap CSS from two dependency entries pointed at two separately compiled copies, which is wasted bytes at best and, if the two copies were compiled from different themes, a page that looks different depending on which <link> happens to load last.

The theme

theme, when supplied, is set with bslib::bs_global_set() for the duration of this call and restored on exit. Several bslib widgets, sliderInput()'s ionRangeSlider skin among them, resolve their CSS through bslib::bs_dependency_defer(), which reads the globally active theme at render time. Outside a running Shiny session, which is where this function usually runs, that would be bslib's stock theme.

Set a global theme with bs_global_set(), not bslib::bs_global_theme(): its first argument is a Bootstrap version number, so passing it a theme object builds a different, stock theme and drops custom fonts.

Examples

deps <- page_deps(bslib::bs_theme(version = 5))
length(deps)
#> [1] 12

# A themeless app still gets the widget dependencies it needs (the
# ionRangeSlider skin, selectize assets, and so on), just with no
# bslib/Bootstrap theme compiled in.
length(page_deps(theme = NULL)) > 0
#> [1] TRUE

if (FALSE) { # \dontrun{
# A real app, with a client built by Vite:
app_theme <- bslib::bs_theme(version = 5)
ui <- shinyreact::page_react(
  page_deps(app_theme),
  title = "Demo",
  theme = app_theme
)
} # }