--- title: "Components" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Components} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", eval = FALSE ) ``` ```{r} library(shiny) library(bootstrict) ``` This article covers the Bootstrap component library: cards, alerts, badges, buttons, accordions, carousels, collapses, list groups, progress bars, spinners and placeholders. Navigation components (nav/tabs, navbar, breadcrumb, pagination, dropdown) have [their own article](navigation.html); overlays (modal, offcanvas, toast, tooltips) are in [Overlays](overlays.html). Some of these components are **interactive** — they report state as `input$id` and are driven from the server with an `update_bs_*()` helper. Those follow the same pattern throughout `bootstrict`; see [Overlays and server-driven interactivity](overlays.html) for the full story. ## Buttons `bs_button()` renders a Bootstrap button. It becomes a Shiny action button **only when given an `id`** — then `input$id` is the click count, exactly like `shiny::actionButton()`. Without an `id` it is an inert, styled button. ```{r} bs_button( id = NULL, label = NULL, ..., color = "primary", # a theme colour or "link" outline = FALSE, # .btn-outline-* size = NULL, # "sm" or "lg" disabled = FALSE, href = NULL, # set to render an styled as a button type = "button", # "button"/"submit"/"reset" class = NULL ) ``` ```{r} bs_button("go", "Go", color = "primary") bs_button(label = "Cancel", color = "secondary", outline = TRUE) ``` Group buttons with `bs_button_group()` (add `vertical = TRUE` for a column), and group groups with `bs_button_toolbar()`: ```{r} bs_button_group( bs_button(label = "Left"), bs_button(label = "Right") ) ``` The standalone Bootstrap close button (used inside dismissible components) is `bs_close_button()`. On a dark background use `white = TRUE`. ### Download buttons `bs_download_button()` and `bs_download_link()` wrap the Shiny originals. Shiny hardcodes the Bootstrap 3 class `.btn-default`, which has no Bootstrap 5 equivalent and leaves the button unstyled; these take `color` / `outline` / `size` like `bs_button()` instead. The server side stays a plain `shiny::downloadHandler()`. ```{r} ui <- bs_page( bs_container(bs_download_button("save", "Download CSV", color = "success")) ) server <- function(input, output, session) { output$save <- downloadHandler( filename = "data.csv", content = function(file) write.csv(mtcars, file) ) } ``` `icon` defaults to `NULL` rather than Shiny's Font Awesome icon, which is outside Bootstrap 5. ## Cards Cards are built from composable pieces. `bs_card()` is the container; the rest (`bs_card_header()`, `bs_card_body()`, `bs_card_title()`, `bs_card_subtitle()`, `bs_card_text()`, `bs_card_footer()`, `bs_card_link()`) map one-to-one to the Bootstrap card sub-elements. ```{r} bs_card( bs_card_header("Featured"), bs_card_body( bs_card_title("Card title"), bs_card_subtitle("A subtitle"), bs_card_text("Some quick example text to build on the card title."), bs_card_link("Read more", href = "#") ), bs_card_footer("Updated 3 mins ago") ) ``` `bs_card()` accepts `color=` (a background theme colour, `.text-bg-*`) and `border=` (a border colour). For images, `bs_card_img()` places a picture at the `"top"`, `"bottom"` or as an `"overlay"`; pair the overlay with `bs_card_img_overlay()` to float text on top. `bs_card_group()` snaps several cards into an equal-width attached grid. ```{r} bs_card_group( bs_card(bs_card_body("A")), bs_card(bs_card_body("B")) ) ``` ## Alerts `bs_alert()` is a coloured message box. `dismissible = TRUE` adds a close button and fade-out. ```{r} bs_alert("Well done! You read this important message.", color = "success") bs_alert("Heads up — check your settings.", color = "warning", dismissible = TRUE) ``` Inside an alert, `bs_alert_heading()` gives a matched heading and `bs_alert_link()` a colour-matched link: ```{r} bs_alert( color = "danger", bs_alert_heading("Something went wrong"), "Read the ", bs_alert_link("full log", href = "#"), " for details." ) ``` Give it an `id` and it becomes interactive: `input$id` is `TRUE` while the alert is on the page and `FALSE` once dismissed, and `close_bs_alert()` dismisses it from the server. Bootstrap removes the element, so an alert cannot be brought back — render it from a `renderUI()` if it has to come and go. ```{r} ui <- bs_page( bs_container( bs_alert("Saved.", id = "saved", color = "success", dismissible = TRUE), bs_button("dismiss", "Dismiss") ) ) server <- function(input, output, session) { observeEvent(input$dismiss, close_bs_alert("saved")) observe(message("alert still shown: ", input$saved)) } ``` ## Badges Small count/label pills: ```{r} bs_badge("New", color = "success") bs_badge("42", color = "danger", pill = TRUE) ``` ## Accordion (interactive) A vertically collapsing set of panels. The value(s) of the open panel(s) are reported as `input$id`, and you open/close them from the server with `update_bs_accordion()`. ```{r} bs_accordion( "acc", bs_accordion_panel("First", "Panel one body", value = "one"), bs_accordion_panel("Second", "Panel two body", value = "two"), open = "one" ) ``` - `open` accepts panel value(s), or `TRUE` (open all — only sensible with `multiple = TRUE`), or `FALSE`/`NULL` (none). - `multiple = TRUE` lets panels stay open independently ("always open"). - `flush = TRUE` renders edge-to-edge. ```{r} server <- function(input, output, session) { observe(print(input$acc)) # value(s) of open panel(s) observeEvent(input$go, update_bs_accordion("acc", open = "two")) } ``` ## Carousel (interactive) A slideshow of `bs_carousel_item()`s. The 0-based index of the active slide is reported as `input$id`; drive it with `update_bs_carousel()`. ```{r} bs_carousel( "demo", bs_carousel_item(bs_img("1.jpg"), active = TRUE, caption = "First slide"), bs_carousel_item(bs_img("2.jpg")) ) ``` - `indicators` / `controls` toggle the clickable dots and prev/next arrows. - `fade = TRUE` crossfades; `autoplay = TRUE` (default) auto-cycles; `interval` sets the cycle time in ms. - Exactly one item is `active` (the first is defaulted if you set none). ```{r} update_bs_carousel("demo", to = 2) # jump to a slide (0-based) update_bs_carousel("demo", slide = "next") ``` ## Collapse (interactive) A container that shows/hides content. Its state is reported as `input$id` (`TRUE` when visible). Toggle it from the UI with `bs_collapse_trigger()` (no server round trip) or from the server with `update_bs_collapse()`. ```{r} tagList( bs_collapse_trigger("more", "Toggle details"), bs_collapse("more", "Hidden content revealed on toggle.") ) ``` ```{r} update_bs_collapse("more", "show") # "toggle" (default), "show" or "hide" ``` ## List group (interactive) A flexible list that becomes **server-selectable** when you give it an `id`: the active item's `value` is reported as `input$id`, and `update_bs_list_group()` activates an item by value. ```{r} bs_list_group( "picker", bs_list_group_item("An item", value = "a", action = TRUE), bs_list_group_item("A second item", value = "b", action = TRUE) ) ``` Items can be plain (`
  • `), actionable (`action = TRUE` → a `