Skip to content

Commit

Permalink
Introduce asFillContainer() and asFillItem()
Browse files Browse the repository at this point in the history
  • Loading branch information
cpsievert committed Oct 21, 2022
1 parent 10d245c commit d48c3f6
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 1 deletion.
3 changes: 2 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: htmltools
Type: Package
Title: Tools for HTML
Version: 0.5.3.9000
Version: 0.5.3.9001
Authors@R: c(
person("Joe", "Cheng", role = "aut", email = "[email protected]"),
person("Carson", "Sievert", role = c("aut", "cre"), email = "[email protected]", comment = c(ORCID = "0000-0002-4958-2844")),
Expand Down Expand Up @@ -36,6 +36,7 @@ RoxygenNote: 7.2.1
Encoding: UTF-8
Collate:
'colors.R'
'fill.R'
'html_dependency.R'
'html_escape.R'
'html_print.R'
Expand Down
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ export("htmlDependencies<-")
export(HTML)
export(a)
export(as.tags)
export(asFillContainer)
export(asFillItem)
export(attachDependencies)
export(br)
export(browsable)
Expand Down
104 changes: 104 additions & 0 deletions R/fill.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#' Allow tags to intelligently fill their container
#'
#' Create fill containers and items. If a fill item is a direct child of a fill
#' container with a fixed height, then the item is allowed to grow and shrink to
#' its container's size.
#'
#' @details `asFillContainer()` changes the CSS `display` property on the tag to
#' `flex`, which changes the way it does layout of it's direct children. Thus,
#' one should be careful not to mark a tag as a fill container when it needs
#' to rely on other `display` behavior.
#'
#' @param a [tag()] object.
#' @param ... arguments passed along to [tagAppendAttributes()].
#' @param height,width Any valid [CSS unit][htmltools::validateCssUnit] (e.g.,
#' height="200px").
#' @param asItem whether or not to also treat the container as an item. This is
#' useful if the tag wants to both be a direct child of a fill container and a
#' direct parent of a fill item.
#' @export
#' @examples
#'
#' tagz <- div(
#' id = "outer",
#' style = css(
#' height = "600px",
#' border = "3px red solid"
#' ),
#' div(
#' id = "inner",
#' style = css(
#' height = "400px",
#' border = "3px blue solid"
#' )
#' )
#' )
#'
#' # Inner doesn't fill outer
#' if (interactive()) browsable(tagz)
#'
#' tagz <- asFillContainer(tagz)
#' tagz <- asFillItem(tagz, .cssSelector = "#inner")
#'
#' # Inner does fill outer
#' if (interactive()) browsable(tagz)
#'
asFillContainer <- function(x, ..., height = NULL, width = NULL, asItem = FALSE) {
if (!inherits(x, "shiny.tag")) {
return(throwFillWarning(x))
}

x <- tagAppendAttributes(
x, class = "html-fill-container",
class = if (asItem) "html-fill-item",
style = css(
height = validateCssUnit(height),
width = validateCssUnit(width)
),
...
)

attachDependencies(x, fillDependencies(), append = TRUE)
}


#' @export
#' @rdname asFillContainer
asFillItem <- function(x, ..., height = NULL, width = NULL) {
if (!inherits(x, "shiny.tag")) {
return(throwFillWarning(x, "item"))
}

tagAppendAttributes(
x, class = "html-fill-item",
style = css(
height = validateCssUnit(height),
width = validateCssUnit(width)
),
...
)
}


fillDependencies <- function() {
htmlDependency(
name = "htmltools-fill",
version = get_package_version("htmltools"),
package = "htmltools",
src = "fill",
stylesheet = "fill.css"
)
}

throwFillWarning <- function(x, type = "container") {
rlang::warn(
paste0(
"Don't know how to treat an object of type '",
class(x)[1], "' as a fill ", type, ". ",
"Only a htmltools::tag() object may be treated as a fill ", type
),
class = "htmltools-fill-input"
)
x
}

12 changes: 12 additions & 0 deletions inst/fill/fill.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.html-fill-container {
display: flex;
flex-direction: column;
overflow: auto;
width: 100%;
}

.html-fill-container > .html-fill-item {
flex: var(--html-fill-flex, 1 1 auto);
overflow: auto;
width: 100%;
}
61 changes: 61 additions & 0 deletions man/asFillContainer.Rd

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

0 comments on commit d48c3f6

Please sign in to comment.