Skip to content

Commit

Permalink
Add Card class and migrate card JavaScript to TypeScript (#557)
Browse files Browse the repository at this point in the history
Co-authored-by: Carson Sievert <[email protected]>
  • Loading branch information
gadenbuie and cpsievert authored May 15, 2023
1 parent 0cca4ce commit d3c3ad3
Show file tree
Hide file tree
Showing 17 changed files with 513 additions and 87 deletions.
13 changes: 7 additions & 6 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,21 @@

This significant release adds [sidebar layouts](https://rstudio.github.io/bslib/articles/sidebars.html), [accordions](https://rstudio.github.io/bslib/articles/sidebars.html#sidebar-accordions), and makes many improvements to make dashboard-like filling layouts easier to create.

Although `{bslib}` is still maturing, and will continue to receiving new UI features, we now see it as a viable replacement for `{shinydashboard}`.
Although `{bslib}` is still maturing, and will continue to receiving new UI features, we now see it as a viable replacement for `{shinydashboard}`.

## Breaking changes

* `card_body()` now provides the same behavior as `card_body_fill()` (i.e., it is both a fillable container and fill item) by default. And, now, since `card_body()` can do everything `card_body_fill()` can do, `card_body_fill()` has been deprecated. The main benefit of this change is that `card(full_screen = TRUE, ...)` with output(s) passed to `...` "just works" in an intuitive way. To revert to the previous behavior, set `fillable = FALSE` and `fill = FALSE` in calls to `card_body()` and set `wrapper = function(x) card_body(x, fillable = FALSE, fill = FALSE)` in calls to `card()`. (#498)
* Closed #375: `margin-top` is no longer included on header tags that aren't created via pandoc. If this negatively impacts spacing above headers, consider adding a suitable [utility class](https://rstudio.github.io/bslib/articles/utility-classes.html) (for example, change `shiny::titlePanel("My title")` to `tagAppendAttributes(titlePanel("My title"), class = "mt-3", .selector = "h2")`). (#396)
* `layout_column_wrap()`'s `fill` argument now controls whether or not the _layout container_ is allowed to grow/shrink to fit a fillable container (e.g., `page_fillable()`). It also gains a new `fillable` argument for controlling whether _UI elements_ are allowed to fill their row height. This is more consistent with the meaning of `fill` in other functions, like `card()`, `card_body()`, `layout_sidebar()`, etc. (#498)
* `page_fill()` (now called `page_fillable()`) had several breaking changes (listed below). If this breaks existing behavior, consider using `shiny::fillPage(theme = bslib::bs_theme(), ...)` instead of `page_fill()`.
* `page_fill()` (now called `page_fillable()`) had several breaking changes (listed below). If this breaks existing behavior, consider using `shiny::fillPage(theme = bslib::bs_theme(), ...)` instead of `page_fill()`.
* `page_fill()` now produces a `<body>` tag with `display:flex` (instead of `display:block`).
* `page_fill()` no longer fills the windows height on mobile (i.e., narrow screens) by default (set `fill_mobile = TRUE` to restore the old behavior).
* `page_fill()` no longer fills the windows height on mobile (i.e., narrow screens) by default (set `fill_mobile = TRUE` to restore the old behavior).
* `page_fill()` now adds `padding` and `gap` by default, set `padding = 0` and `gap = 0` to restore the old behavior.
* `page_navbar()` (and consequently `shiny::navbarPage()`) no longer implicitly wrap `header` and `footer` in an additional `shiny::fluidRow()` container for Bootstrap 5+ (i.e., `theme = bs_theme()`) usage. Similarly, `navs_bar()` no longer does this (for any version of Bootstrap). If this breaks existing behavior, consider wrapping the `header` and `footer` value(s) with `shiny::fluidRow()`). (#479)
* Closed #510: `card()` no longer includes `margin-bottom`. To revert the old behavior, add `class = "mb-3` to `card()`. (#542)
* Defaults for the following Bootstrap 5 Sass variables were changed to `null`: `$accordion-button-active-bg`, `$accordion-button-active-color`, and `$accordion-icon-active-color`. To restore the old behavior, do `bs_add_variables(theme, "accordion-button-active-bg" = "tint-color($component-active-bg, 90%)", "accordion-button-active-color" = "shade-color($primary, 10%)", "accordion-icon-active-color" = "$accordion-button-active-color", .where = "declarations")`. (#475)
* Closed #558: nested cards with `fullscreen = TRUE` now correctly and individually expand to fill the window. Tab focus behavior while in full screen mode has also been improved. (#557)

## New features

Expand Down Expand Up @@ -45,8 +46,8 @@ Although `{bslib}` is still maturing, and will continue to receiving new UI feat

* Adds a new `card()` API as well as `value_box()` and `layout_column_wrap()`. To learn more about this new functionality, refer to these new pkgdown articles:

* https://rstudio.github.io/bslib/articles/cards.html
* https://rstudio.github.io/bslib/articles/value-boxes.html
* https://rstudio.github.io/bslib/articles/cards.html
* https://rstudio.github.io/bslib/articles/value-boxes.html
* https://rstudio.github.io/bslib/articles/column-layout.html

# bslib 0.4.1
Expand Down Expand Up @@ -123,7 +124,7 @@ Small patch release to fix failing test on Solaris.

## Bug fixes

* Closed #236, #230, #242, #187, #215, #250: Addressed various cosmetic issues with CSS (#249).
* Closed #236, #230, #242, #187, #215, #250: Addressed various cosmetic issues with CSS (#249).
* Closed #289: collapsed navbar toggle now correctly floats to the right (#290).
* Closed [rstudio/flexdashboard#316](https://github.com/rstudio/flexdashboard/issues/316): fixed an issue with navbar nav spacing/alignment (#286).

Expand Down
73 changes: 21 additions & 52 deletions R/card.R
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,12 @@ card <- function(..., full_screen = FALSE, height = NULL, max_height = NULL, fil
height = validateCssUnit(height),
max_height = validateCssUnit(max_height)
),
"data-bslib-card-init" = NA,
!!!attribs,
!!!children,
if (full_screen) full_screen_toggle(),
card_js_init()
card_dependency(),
card_init_js()
)

tag <- bindFillRole(tag, container = TRUE, item = fill)
Expand Down Expand Up @@ -271,64 +273,31 @@ full_screen_toggle <- function() {
"data-bs-toggle" = "tooltip",
"data-bs-placement" = "bottom",
title = "Expand",
full_screen_toggle_icon(),
htmlDependency(
name = "bslib-card-full-screen",
version = get_package_version("bslib"),
package = "bslib",
src = "components",
script = "card-full-screen.js"
)
full_screen_toggle_icon()
)
}

card_dependency <- function() {
htmlDependency(
name = "bslib-card",
version = get_package_version("bslib"),
package = "bslib",
src = "components",
script = "card.min.js"
)
}

card_js_init <- function() {
tags$script("data-bslib-card-needs-init" = NA, HTML(
"
var thisScript = document.querySelector('script[data-bslib-card-needs-init]');
if (!thisScript) throw new Error('Failed to register card() resize observer');
thisScript.removeAttribute('data-bslib-card-needs-init');
var card = $(thisScript).parents('.card').last();
if (!card) throw new Error('Failed to register card() resize observer');
// Let Shiny know to trigger resize when the card size changes
// TODO: shiny could/should do this itself (rstudio/shiny#3682)
var resizeEvent = window.document.createEvent('UIEvents');
resizeEvent.initUIEvent('resize', true, false, window, 0);
var ro = new ResizeObserver(() => { window.dispatchEvent(resizeEvent); });
ro.observe(card[0]);
// Enable tooltips (for the expand icon)
var tooltipList = card[0].querySelectorAll('[data-bs-toggle=\"tooltip\"]');
tooltipList.forEach(function(x) { new bootstrap.Tooltip(x); });
// In some complex fill-based layouts with multiple outputs (e.g., plotly),
// shiny initializes with the correct sizing, but in-between the 1st and last
// renderValue(), the size of the output containers can change, meaning every
// output but the 1st gets initialized with the wrong size during their
// renderValue(); and then after the render phase, shiny won't know trigger a
// resize since all the widgets will return to their original size
// (and thus, Shiny thinks there isn't any resizing to do).
// We workaround that situation by manually triggering a resize on the binding
// when the output container changes (this way, if the size is different during
// the render phase, Shiny will know about it)
$(document).on('shiny:value', function(x) {
var el = x.binding.el;
if (card[0].contains(el) && !$(el).data('bslib-output-observer')) {
var roo = new ResizeObserver(x.binding.onResize);
roo.observe(el);
$(el).data('bslib-output-observer', true);
}
});
"
))
card_init_js <- function() {
tags$script(
`data-bslib-card-init` = NA,
HTML("bslib.Card.initializeAllCards();")
)
}

# via bsicons::bs_icon("arrows-fullscreen")
full_screen_toggle_icon <- function() {
if (is_installed("bsicons")) {
return(bsicons::bs_icon("arrows-fullscreen"))
}
HTML('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" class="bi bi-arrows-fullscreen " style="height:1em;width:1em;fill:currentColor;" aria-hidden="true" role="img" ><path fill-rule="evenodd" d="M5.828 10.172a.5.5 0 0 0-.707 0l-4.096 4.096V11.5a.5.5 0 0 0-1 0v3.975a.5.5 0 0 0 .5.5H4.5a.5.5 0 0 0 0-1H1.732l4.096-4.096a.5.5 0 0 0 0-.707zm4.344 0a.5.5 0 0 1 .707 0l4.096 4.096V11.5a.5.5 0 1 1 1 0v3.975a.5.5 0 0 1-.5.5H11.5a.5.5 0 0 1 0-1h2.768l-4.096-4.096a.5.5 0 0 1 0-.707zm0-4.344a.5.5 0 0 0 .707 0l4.096-4.096V4.5a.5.5 0 1 0 1 0V.525a.5.5 0 0 0-.5-.5H11.5a.5.5 0 0 0 0 1h2.768l-4.096 4.096a.5.5 0 0 0 0 .707zm-4.344 0a.5.5 0 0 1-.707 0L1.025 1.732V4.5a.5.5 0 0 1-1 0V.525a.5.5 0 0 1 .5-.5H4.5a.5.5 0 0 1 0 1H1.732l4.096 4.096a.5.5 0 0 1 0 .707z"></path></svg>')
}

Expand Down
2 changes: 1 addition & 1 deletion inst/components/accordion.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit d3c3ad3

Please sign in to comment.