diff --git a/DESCRIPTION b/DESCRIPTION index 76d439115..ee13faf41 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -82,6 +82,7 @@ URL: https://rstudio.github.io/bslib/, https://github.com/rstudio/bslib BugReports: https://github.com/rstudio/bslib/issues Config/testthat/edition: 3 Config/Needs/routine: + chromote, desc, renv Config/Needs/website: diff --git a/R/navs-legacy.R b/R/navs-legacy.R index 617171dc5..bf079e835 100644 --- a/R/navs-legacy.R +++ b/R/navs-legacy.R @@ -2,59 +2,17 @@ #' #' Render a collection of [nav()] items into a container. #' +#' @includeRmd man/fragments/ex-navs_tab.Rmd +#' #' @param ... a collection of [nav()] items. #' @param id a character string used for dynamically updating the container (see [nav_select()]). #' @param selected a character string matching the `value` of a particular [nav()] item to selected by default. #' @param header UI element(s) ([tags]) to display _above_ the nav content. #' @param footer UI element(s) ([tags]) to display _below_ the nav content. -#' @export +#' #' @seealso [nav()], [nav_select()]. +#' @export #' @rdname navs -#' @examples -#' -#' library(shiny) -#' -#' nav_items <- function(prefix) { -#' list( -#' nav("a", paste(prefix, ": tab a content")), -#' nav("b", paste(prefix, ": tab b content")), -#' nav_item( -#' tags$a(icon("github"), "Shiny", href = "https://github.com/rstudio/shiny", target = "_blank") -#' ), -#' nav_spacer(), -#' nav_menu( -#' "Other links", align = "right", -#' nav("c", paste(prefix, ": tab c content")), -#' nav_item( -#' tags$a(icon("r-project"), "RStudio", href = "https://rstudio.com", target = "_blank") -#' ) -#' ) -#' ) -#' } -#' -#' if (interactive()) { -#' shinyApp( -#' page_navbar( -#' title = "page_navbar()", -#' bg = "#0062cc", -#' !!!nav_items("page_navbar()"), -#' footer = div( -#' style = "width:80%; margin: 0 auto", -#' h4("navs_tab()"), -#' navs_tab(!!!nav_items("navs_tab()")), -#' h4("navs_pill()"), -#' navs_pill(!!!nav_items("navs_pill()")), -#' h4("navs_tab_card()"), -#' navs_tab_card(!!!nav_items("navs_tab_card()")), -#' h4("navs_pill_card()"), -#' navs_pill_card(!!!nav_items("navs_pill_card()")), -#' h4("navs_pill_list()"), -#' navs_pill_list(!!!nav_items("navs_pill_list()")) -#' ) -#' ), -#' function(...) { } -#' ) -#' } navs_tab <- function(..., id = NULL, selected = NULL, header = NULL, footer = NULL) { tabs <- tabsetPanel_( diff --git a/man/figures/navs_pill.png b/man/figures/navs_pill.png new file mode 100644 index 000000000..c7a75863d Binary files /dev/null and b/man/figures/navs_pill.png differ diff --git a/man/figures/navs_pill_card.png b/man/figures/navs_pill_card.png new file mode 100644 index 000000000..0ac67cd68 Binary files /dev/null and b/man/figures/navs_pill_card.png differ diff --git a/man/figures/navs_pill_list.png b/man/figures/navs_pill_list.png new file mode 100644 index 000000000..396fe9552 Binary files /dev/null and b/man/figures/navs_pill_list.png differ diff --git a/man/figures/navs_tab-basic.png b/man/figures/navs_tab-basic.png new file mode 100644 index 000000000..76c258ff2 Binary files /dev/null and b/man/figures/navs_tab-basic.png differ diff --git a/man/figures/navs_tab.png b/man/figures/navs_tab.png new file mode 100644 index 000000000..c698d9abc Binary files /dev/null and b/man/figures/navs_tab.png differ diff --git a/man/figures/navs_tab_card.png b/man/figures/navs_tab_card.png new file mode 100644 index 000000000..8b3c6d96f Binary files /dev/null and b/man/figures/navs_tab_card.png differ diff --git a/man/figures/page_navbar.png b/man/figures/page_navbar.png new file mode 100644 index 000000000..3d19fb4c9 Binary files /dev/null and b/man/figures/page_navbar.png differ diff --git a/man/figures/rstudio-templates.png b/man/figures/rstudio-templates.png index 686821eb4..5d922e61f 100644 Binary files a/man/figures/rstudio-templates.png and b/man/figures/rstudio-templates.png differ diff --git a/man/fragments/.gitignore b/man/fragments/.gitignore new file mode 100644 index 000000000..2d19fc766 --- /dev/null +++ b/man/fragments/.gitignore @@ -0,0 +1 @@ +*.html diff --git a/man/fragments/ex-navs_tab.Rmd b/man/fragments/ex-navs_tab.Rmd new file mode 100644 index 000000000..22a8c6355 --- /dev/null +++ b/man/fragments/ex-navs_tab.Rmd @@ -0,0 +1,228 @@ +```{r setup, include = FALSE} +library(bslib) +## Screenshots are created during `devtools::document()` in CI +## or set to `TRUE` below to test or update locally +SCREENSHOT <- nzchar(Sys.getenv("CI", "")) || FALSE +``` + +```{r include = FALSE} +if (isTRUE(SCREENSHOT)) { + library(chromote) + b <- ChromoteSession$new(width = 800, height = 300, wait_ = TRUE) +} + +render_screenshot <- function(x, options) { + if (inherits(x, "bslib_fragment")) { + x <- attr(x, "bslib_page")(x) + } + x <- tagList( + x, + tags$head(tags$style(" + body { min-height: 300px; padding: 1rem } + .bslib-card .card-body { min-height: 200px; } + ")) + ) + tmpdir <- tempfile() + dir.create(tmpdir) + on.exit(unlink(tmpdir, recursive = TRUE)) + + tmpfile <- file.path(tmpdir, basename(tempfile(fileext = ".html"))) + save_html(x, tmpfile) + + file_out <- paste0(options$label, ".png") + + { + p <- b$Page$loadEventFired(wait_ = FALSE) + b$Page$navigate(paste0("file://", tmpfile), wait_ = FALSE) + b$wait_for(p) + } + + b$Runtime$evaluate( + "if ($('.dropdown-toggle').length > 0) $('.dropdown-toggle').dropdown('toggle')" + ) + b$screenshot(filename = file.path( + rprojroot::find_package_root_file(), + "man/figures/", file_out + )) + + invisible(file_out) +} + +include_screenshot <- function(x, options) { + file_name <- paste0(options$label, ".png") + alt <- options$fig.alt + if (is.null(alt)) { + alt <- sprintf("Screenshot of a %s() example.", options$label) + } + img <- sprintf('', file_name, alt) + knitr::asis_output(img) +} + +knitr::opts_chunk$set( + render = function(x, options) { + if (isTRUE(SCREENSHOT)) { + render_screenshot(x, options) + } + include_screenshot(x, options) + } +) +``` + +## A basic example + +This first example creates a simple tabbed navigation container with two tabs. +The tab name and the content of each tab are specified in the `nav()` calls +and `navs_tab()` creates the tabbed navigation around these two tabs. + +```{r navs_tab-basic, fig.alt = "Screenshot of a basic navs_tab() example."} +library(htmltools) + +navs_tab( + nav(title = "One", p("First tab content.")), + nav(title = "Two", p("Second tab content.")) +) +``` + +In the rest of the examples, we'll include links among the tabs (or pills) in the navigation controls. + +```{r echo = TRUE, eval = TRUE, results="hide"} +link_shiny <- tags$a(shiny::icon("github"), "Shiny", href = "https://github.com/rstudio/shiny", target = "_blank") +link_posit <- tags$a(shiny::icon("r-project"), "Posit", href = "https://posit.co", target = "_blank") +``` + +## `navs_tab()` + +You can fully customize the controls in the navigation component. +In this example, we've added a direct link to the Shiny repository using `nav_item()`. +We've also included a dropdown menu using `nav_menu()` +containing an option to select a third tab panel +and another direct link to Posit's website. +Finally, we've separated the primary tabs on the left +from the direct link and dropdown menu on the right +using `nav_spacer()`. + +```{r navs_tab} +navs_tab( + nav(title = "One", p("First tab content.")), + nav(title = "Two", p("Second tab content.")), + nav_spacer(), + nav_item(link_shiny), + nav_menu( + title = "Other links", + align = "right", + nav("Three", p("Third tab content")), + nav_item(link_posit) + ) +) +``` + +## `navs_pill()` + +`navs_pill()` creates a navigation container that behaves exactly like `navs_tab()`, +but the tab toggles are _pills_ or button-shaped. + +```{r navs_pill} +navs_pill( + nav(title = "One", p("First tab content.")), + nav(title = "Two", p("Second tab content.")), + nav_spacer(), + nav_item(link_shiny), + nav_menu( + title = "Other links", + align = "right", + nav("Three", p("Third tab content")), + nav_item(link_posit) + ) +) +``` + +## `navs_tab_card()` + +The tabbed navigation container can also be used in a `card()` component +thanks to `navs_tab_card()`. +Learn more about this approach in the +[article about Cards](https://pkgs.rstudio.com/bslib/articles/cards.html), +including how to add [a shared sidebar](https://pkgs.rstudio.com/bslib/articles/sidebars.html#multi-page-layout) +to all tabs in the card +using the `sidebar` argument of `navs_tab_card()`. + +```{r navs_tab_card} +navs_tab_card( + nav(title = "One", p("First tab content.")), + nav(title = "Two", p("Second tab content.")), + nav_spacer(), + nav_item(link_shiny), + nav_menu( + title = "Other links", + align = "right", + nav("Three", p("Third tab content")), + nav_item(link_posit) + ) +) +``` + +## `navs_pill_card()` + +Similar to `navs_pill()`, +`navs_pill_card()` provides a pill-shaped variant to `navs_tab_card()`. +You can use the `placement` argument to position the navbar +`"above"` or `"below"` the card body. + +```{r navs_pill_card} +navs_pill_card( + placement = "above", + nav(title = "One", p("First tab content.")), + nav(title = "Two", p("Second tab content.")), + nav_spacer(), + nav_item(link_shiny), + nav_menu( + title = "Other links", + align = "right", + nav("Three", p("Third tab content")), + nav_item(link_posit) + ) +) +``` + +## `navs_pill_list()` + +Furthermore, `navs_pill_list()` creates a vertical list of navigation controls +adjacent to, rather than on top of, the tab content panels. + +```{r navs_pill_list} +navs_pill_list( + nav(title = "One", p("First tab content.")), + nav(title = "Two", p("Second tab content.")), + nav_spacer(), + nav_item(link_shiny), + nav_menu( + title = "Other links", + align = "right", + nav("Three", p("Third tab content")), + nav_item(link_posit) + ) +) +``` + +## `page_navbar()` + +Finally, `page_navbar()` provides full-page navigation container +similar to `navs_tab()` but where each `nav()` is treated as a full page of content +and the navigation controls appear in a top-level navigation bar. + +```{r page_navbar} +page_navbar( + title = "My App", + bg = "#0062cc", + nav(title = "One", p("First page content.")), + nav(title = "Two", p("Second page content.")), + nav_spacer(), + nav_item(link_shiny), + nav_menu( + title = "Other links", + align = "right", + nav("Three", p("Third page content.")), + nav_item(link_posit) + ) +) +``` diff --git a/man/navs.Rd b/man/navs.Rd index de5151f21..0cf63cea2 100644 --- a/man/navs.Rd +++ b/man/navs.Rd @@ -136,50 +136,177 @@ together into one \code{wrapper} call (e.g. given \code{card("a", "b", card_body \description{ Render a collection of \code{\link[=nav]{nav()}} items into a container. } -\examples{ - -library(shiny) - -nav_items <- function(prefix) { - list( - nav("a", paste(prefix, ": tab a content")), - nav("b", paste(prefix, ": tab b content")), - nav_item( - tags$a(icon("github"), "Shiny", href = "https://github.com/rstudio/shiny", target = "_blank") - ), - nav_spacer(), - nav_menu( - "Other links", align = "right", - nav("c", paste(prefix, ": tab c content")), - nav_item( - tags$a(icon("r-project"), "RStudio", href = "https://rstudio.com", target = "_blank") - ) - ) +\details{ +\subsection{A basic example}{ + +This first example creates a simple tabbed navigation container with two +tabs. The tab name and the content of each tab are specified in the +\code{nav()} calls and \code{navs_tab()} creates the tabbed navigation around +these two tabs. + +\if{html}{\out{