├── .Rbuildignore ├── .gitignore ├── DESCRIPTION ├── LICENSE ├── LICENSE.md ├── NAMESPACE ├── R ├── accordion.R ├── alerts.R ├── badge.R ├── card.R ├── carousel.R ├── close.R ├── collapse.R ├── dependencies.R ├── dropdown.R ├── gallery.R ├── group.R ├── inputs.R ├── list.R ├── modal.R ├── offcanvas.R ├── placeholders.R ├── popover.R ├── progress.R ├── toast.R ├── tooltip.R └── utils.R ├── README.md ├── inst ├── app │ └── app.R └── assets │ ├── alert.js │ ├── carousel.js │ ├── color.js │ ├── modal.js │ ├── offcanvas.js │ ├── popover.js │ ├── progress.js │ ├── range.js │ ├── text-group.js │ ├── toast.js │ └── tooltip.js ├── makefile └── man ├── accordion.Rd ├── accordionItem.Rd ├── alert.Rd ├── alertHeading.Rd ├── alertServer.Rd ├── asPlaceholder.Rd ├── badge.Rd ├── buttonGroup.Rd ├── card.Rd ├── cardBody.Rd ├── cardHeader.Rd ├── cardText.Rd ├── cardTitle.Rd ├── carousel.Rd ├── carouselControls.Rd ├── carouselImg.Rd ├── carouselIndicators.Rd ├── carouselItem.Rd ├── closeButton.Rd ├── collapse.Rd ├── collapseButton.Rd ├── collapseContent.Rd ├── collapseLink.Rd ├── colorPickerInput.Rd ├── dropdownButton.Rd ├── floatingSelectInput.Rd ├── floatingTextAreaInput.Rd ├── floatingTextInput.Rd ├── gallery.Rd ├── get_dep.Rd ├── listGroup.Rd ├── listGroupItem.Rd ├── modal.Rd ├── modalBody.Rd ├── modalFooter.Rd ├── modalHeader.Rd ├── modalTitle.Rd ├── modalToggle.Rd ├── modalTrigger.Rd ├── offcanvas.Rd ├── offcanvasButton.Rd ├── offcanvasContent.Rd ├── offcanvasHeader.Rd ├── offcanvasLink.Rd ├── offcanvasServer.Rd ├── progress.Rd ├── progressBar.Rd ├── rangeInput.Rd ├── switchInput.Rd ├── textGroupInput.Rd ├── toast.Rd ├── toastContent.Rd ├── toastToggle.Rd ├── update_color_picker.Rd ├── update_progress.Rd ├── update_range.Rd ├── update_text_group.Rd ├── withPopover.Rd └── withTooltip.Rd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^LICENSE\.md$ 2 | ^dev$ 3 | ^makefile$ 4 | ^\.vscode$ 5 | ^test\.R$ 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dev/ 2 | .vscode 3 | test.R 4 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: bsutils 2 | Title: 'Shiny' Utilities for 'Bootstrap 5' 3 | Version: 0.0.0.9000 4 | Authors@R: 5 | c( 6 | person(given = "John", 7 | family = "Coene", 8 | role = c("aut", "cre"), 9 | email = "jcoenep@gmail.com", 10 | comment = c(ORCID = "0000-0002-6637-4107")), 11 | person(family = "Opifex", role = c("fnd")) 12 | ) 13 | Description: 'Shiny' utilities for 'Bootstrap 5' to create 14 | elements such as accordions, off-canvas, etc. 15 | License: MIT + file LICENSE 16 | Encoding: UTF-8 17 | Roxygen: list(markdown = TRUE) 18 | RoxygenNote: 7.3.1 19 | Imports: 20 | shiny, 21 | htmltools 22 | Suggests: 23 | bslib 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2022 2 | COPYRIGHT HOLDER: Opifex 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2022 Opifex 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | S3method(collapse,collapseTrigger) 4 | S3method(offcanvas,offcanvasTrigger) 5 | S3method(offcanvas,shiny.tag) 6 | export(accordion) 7 | export(accordionItem) 8 | export(alert) 9 | export(alertHeading) 10 | export(alert_hide) 11 | export(alert_show) 12 | export(asPlaceholder) 13 | export(badge) 14 | export(buttonGroup) 15 | export(card) 16 | export(cardBody) 17 | export(cardHeader) 18 | export(cardSubtitle) 19 | export(cardText) 20 | export(cardTitle) 21 | export(carousel) 22 | export(carouselImg) 23 | export(carouselItem) 24 | export(closeButton) 25 | export(collapse) 26 | export(collapseButton) 27 | export(collapseContent) 28 | export(collapseLink) 29 | export(colorPickerInput) 30 | export(dropdownButton) 31 | export(floatingSelectInput) 32 | export(floatingTextAreaInput) 33 | export(floatingTextInput) 34 | export(gallery) 35 | export(listGroup) 36 | export(listGroupItem) 37 | export(modal) 38 | export(modalBody) 39 | export(modalButton) 40 | export(modalFooter) 41 | export(modalHeader) 42 | export(modalLink) 43 | export(modalTitle) 44 | export(modal_hide) 45 | export(modal_show) 46 | export(modal_toggle) 47 | export(offcanvas) 48 | export(offcanvasButton) 49 | export(offcanvasButtonWithTooltip) 50 | export(offcanvasContent) 51 | export(offcanvasHeader) 52 | export(offcanvasLink) 53 | export(offcanvas_hide) 54 | export(offcanvas_show) 55 | export(offcanvas_toggle) 56 | export(progress) 57 | export(progressBar) 58 | export(rangeInput) 59 | export(switchInput) 60 | export(textGroupInput) 61 | export(toast) 62 | export(toastBody) 63 | export(toastHeader) 64 | export(toast_hide) 65 | export(toast_show) 66 | export(update_color_picker) 67 | export(update_progress) 68 | export(update_range) 69 | export(update_text_group) 70 | export(withPopover) 71 | export(withTooltip) 72 | import(shiny) 73 | importFrom(htmltools,attachDependencies) 74 | importFrom(htmltools,tagAppendAttributes) 75 | importFrom(htmltools,tagAppendChild) 76 | importFrom(htmltools,tagAppendChildren) 77 | importFrom(htmltools,tagGetAttribute) 78 | importFrom(utils,packageVersion) 79 | -------------------------------------------------------------------------------- /R/accordion.R: -------------------------------------------------------------------------------- 1 | #' Accordion 2 | #' 3 | #' Collapsible accordion made up of [accordionItem()]. 4 | #' 5 | #' @param ... Any number of [accordionItem()]. 6 | #' @param .id Id of accordion. 7 | #' @param .flush remove default background color, some 8 | #' borders, some rounded corners. 9 | #' 10 | #' @examples 11 | #' library(shiny) 12 | #' 13 | #' ui <- fluidPage( 14 | #' theme = bslib::bs_theme(version = 5L), 15 | #' accordion( 16 | #' accordionItem( 17 | #' .expanded = TRUE, 18 | #' "Something", 19 | #' p("Some content") 20 | #' ), 21 | #' accordionItem( 22 | #' "Something else", 23 | #' p("Some other content") 24 | #' ) 25 | #' ) 26 | #' ) 27 | #' 28 | #' server <- \(input, output, session){ 29 | #' 30 | #' } 31 | #' 32 | #' if(interactive()) 33 | #' shinyApp(ui, server) 34 | #' 35 | #' @import shiny 36 | #' 37 | #' @export 38 | accordion <- \( 39 | ..., 40 | .id = NULL, 41 | .flush = FALSE 42 | ) { 43 | fns <- list(...) 44 | 45 | if(length(fns) == 0L) 46 | stop("Must pass `accordionItem`") 47 | 48 | flush <- ifelse(.flush, "accordion-flush", "") 49 | id <- get_id(.id) 50 | 51 | fns |> 52 | lapply(\(fn) { 53 | fn(id) 54 | }) |> 55 | div( 56 | class = sprintf("accordion %s", flush), 57 | id = id 58 | ) 59 | } 60 | 61 | #' AccordionItem 62 | #' 63 | #' Accordion item to place within [accordion()]. 64 | #' 65 | #' @param label Label of the item. 66 | #' @param ... Elements to place in the body of the item. 67 | #' @param .id Id of item. 68 | #' @param .expanded Whether the element is initially expanded. 69 | #' @param .label_tag Tag to use for the label. 70 | #' 71 | #' @export 72 | accordionItem <- \( 73 | label, 74 | ..., 75 | .id = NULL, 76 | .expanded = FALSE, 77 | .label_tag = shiny::h2 78 | ) { 79 | if(missing(label)) 80 | stop("Missing `label`") 81 | 82 | id <- get_id(.id) 83 | 84 | toggled <- ifelse(.expanded, "show", "collapse") 85 | toggled_button <- ifelse(.expanded, "", "collapsed") 86 | 87 | \(parent_id) { 88 | div( 89 | class = "accordion-item", 90 | .label_tag( 91 | class = "accordion-header", 92 | tags$button( 93 | class = sprintf("accordion-button %s", toggled_button), 94 | type = "button", 95 | `data-bs-toggle` = "collapse", 96 | `data-bs-target` = sprintf("#%s", id), 97 | `aria-expanded` = tolower(.expanded), 98 | `aria-controls` = id, 99 | label 100 | ) 101 | ), 102 | div( 103 | id = id, 104 | class = sprintf("accordion-collapse collapse %s", toggled), 105 | `data-bs-parent` = sprintf("#%s", parent_id), 106 | div( 107 | class = "accordion-body", 108 | ... 109 | ) 110 | ) 111 | ) 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /R/alerts.R: -------------------------------------------------------------------------------- 1 | #' Alert 2 | #' 3 | #' @param id ID of alert useful to toggle from server with 4 | #' [alert_show()] or [alert_hide()]. 5 | #' @param ... Content of alert. 6 | #' @param class Additional classes, e.g.: `alert-success`. 7 | #' 8 | #' @examples 9 | #' alert( 10 | #' alertHeading("Header!"), 11 | #' shiny::p("Some content") 12 | #' ) 13 | #' 14 | #' @export 15 | alert <- \( 16 | ..., 17 | id = NULL, 18 | class = "" 19 | ) { 20 | tagList( 21 | get_dep("alert"), 22 | div( 23 | id = id, 24 | class = sprintf("alert %s", class), 25 | role = "alert", 26 | ... 27 | ) 28 | ) 29 | } 30 | 31 | #' Alert Heading 32 | #' 33 | #' Alert heading to be placed in [alert()]. 34 | #' 35 | #' @param heading A character string or an HTML tag. 36 | #' 37 | #' @importFrom htmltools tagAppendAttributes 38 | #' 39 | #' @export 40 | alertHeading <- \(heading){ 41 | if(is.character(heading)) 42 | return(h4(class = "alert-heading", heading)) 43 | 44 | tagAppendAttributes( 45 | heading, 46 | class = "alert-heading" 47 | ) 48 | } 49 | 50 | #' Toggle Alert 51 | #' 52 | #' Show or hide an alert. 53 | #' 54 | #' @param id ID of [alert()] to toggle. 55 | #' @param session A valid shiny session. 56 | #' 57 | #' @name alertServer 58 | #' @export 59 | alert_show <- \( 60 | id, 61 | session = shiny::getDefaultReactiveDomain() 62 | ) { 63 | session$sendCustomMessage( 64 | "alert-show", 65 | id 66 | ) 67 | } 68 | 69 | #' @rdname alertServer 70 | #' @export 71 | alert_hide <- \( 72 | id, 73 | session = shiny::getDefaultReactiveDomain() 74 | ) { 75 | session$sendCustomMessage( 76 | "alert-hide", 77 | id 78 | ) 79 | } 80 | -------------------------------------------------------------------------------- /R/badge.R: -------------------------------------------------------------------------------- 1 | #' Badge 2 | #' 3 | #' Badge. 4 | #' 5 | #' @param ... Content of the badge. 6 | #' @param color Background color of the badge. 7 | #' @param pill Whether to create a rounded badge. 8 | #' @param class Additional classes to passs to the badge. 9 | #' 10 | #' @export 11 | badge <- \( 12 | ..., 13 | color = c( 14 | "primary", 15 | "secondary", 16 | "success", 17 | "danger", 18 | "warning", 19 | "info", 20 | "light", 21 | "dark" 22 | ), 23 | pill = FALSE, 24 | class = "" 25 | ) { 26 | color <- match.arg(color) 27 | pill_class <- "" 28 | 29 | if(pill) 30 | pill_class <- "rounded-pill" 31 | 32 | cl <- sprintf( 33 | "badge bg-%s %s", 34 | color, 35 | pill_class 36 | ) 37 | 38 | span( 39 | class = cl, 40 | ... 41 | ) 42 | } -------------------------------------------------------------------------------- /R/card.R: -------------------------------------------------------------------------------- 1 | #' Card 2 | #' 3 | #' Card. 4 | #' 5 | #' @param ... Content, generally [cardBody()]. 6 | #' 7 | #' @examples 8 | #' card( 9 | #' cardHeader("Header"), 10 | #' cardBody( 11 | #' cardTitle("Title"), 12 | #' cardSubtitle("Subtitle"), 13 | #' cardText("The content of the card") 14 | #' ) 15 | #' ) 16 | #' 17 | #' @export 18 | card <- \( 19 | ... 20 | ) { 21 | div( 22 | class = "card", 23 | ... 24 | ) 25 | } 26 | 27 | #' Card Body 28 | #' 29 | #' Card body to be placed within [card()]. 30 | #' 31 | #' @param ... Content, HTML tags, [cardText()], [cardTitle()], 32 | #' or [cardSubtitle()]. 33 | #' 34 | #' @export 35 | cardBody <- \( 36 | ... 37 | ) { 38 | div( 39 | class = "card-body", 40 | ... 41 | ) 42 | } 43 | 44 | #' Card Text 45 | #' 46 | #' Card text to be placed in [cardBody()]. 47 | #' 48 | #' @param ... Content of the text. 49 | #' 50 | #' @export 51 | cardText <- \( 52 | ... 53 | ) { 54 | p( 55 | class = "card-text", 56 | ... 57 | ) 58 | } 59 | 60 | #' Card Title & Subtitle 61 | #' 62 | #' Card title and subtitle to be placed within [cardBody()]. 63 | #' 64 | #' @param content Content of the title or subtitle, either 65 | #' a character vector or an HTML header tag. 66 | #' 67 | #' @name cardTitle 68 | #' @export 69 | cardTitle <- \( 70 | content 71 | ) { 72 | if(missing(content)) 73 | stop("Missing `content`") 74 | 75 | if(is.character(content)) 76 | return(h5(content, class = "card-title")) 77 | 78 | tagAppendAttributes( 79 | content, 80 | class = "card-title" 81 | ) 82 | } 83 | 84 | #' @rdname cardTitle 85 | #' @export 86 | cardSubtitle <- \( 87 | content 88 | ) { 89 | if(missing(content)) 90 | stop("Missing `content`") 91 | 92 | if(is.character(content)) 93 | return(h6(content, class = "card-subtitle")) 94 | 95 | tagAppendAttributes( 96 | content, 97 | class = "card-subtitle" 98 | ) 99 | } 100 | 101 | #' Card Header 102 | #' 103 | #' Card header placed within [card()] before [cardBody()]. 104 | #' 105 | #' @param content Content of the title or subtitle, either 106 | #' a character vector or an HTML header tag. 107 | #' 108 | #' @importFrom htmltools tagAppendAttributes 109 | #' 110 | #' @export 111 | cardHeader <- \( 112 | content 113 | ) { 114 | if(missing(content)) 115 | stop("Missing `content`") 116 | 117 | if(is.character(content)) 118 | return(h5(content, class = "card-header")) 119 | 120 | tagAppendAttributes( 121 | content, 122 | class = "card-header" 123 | ) 124 | } 125 | -------------------------------------------------------------------------------- /R/carousel.R: -------------------------------------------------------------------------------- 1 | #' Carousel 2 | #' 3 | #' Carousel element. 4 | #' 5 | #' @param ... Slides of the carousel, see [carouselItem()]. 6 | #' @param id ID of carousel. 7 | #' @param class Additional class of the carousel. 8 | #' @param indicators Whether to show indicators. 9 | #' @param controls Whether to show control arrows. 10 | #' 11 | #' @examples 12 | #' library(shiny) 13 | #' 14 | #' ui <- fluidPage( 15 | #' theme = bslib::bs_theme(version = 5L), 16 | #' carousel( 17 | #' indicators = TRUE, 18 | #' controls = TRUE, 19 | #' carouselItem( 20 | #' h5("Hello"), 21 | #' class = "bg-primary rounded p-4" 22 | #' ), 23 | #' carouselItem( 24 | #' h5("World"), 25 | #' class = "bg-info rounded p-4" 26 | #' ) 27 | #' ) 28 | #' ) 29 | #' 30 | #' server <- \(input, output, session){ 31 | #' } 32 | #' 33 | #' if(interactive()) 34 | #' shinyApp(ui, server) 35 | #' 36 | #' @export 37 | carousel <- \( 38 | ..., 39 | id = NULL, 40 | class = "", 41 | controls = FALSE, 42 | indicators = FALSE 43 | ) { 44 | items <- list(...) 45 | id <- get_id(id) 46 | 47 | items[[1]] <- tagAppendAttributes( 48 | items[[1]], 49 | class = "active" 50 | ) 51 | 52 | inner <- div( 53 | class = "carousel-inner", 54 | items 55 | ) 56 | 57 | tagList( 58 | get_dep("carousel"), 59 | div( 60 | id = id, 61 | class = sprintf("bsutils-carousel carousel slide %s", class), 62 | `data-bs-ride` = "carousel", 63 | carouselIndicators(items, id, indicators), 64 | inner, 65 | carouselControls(controls, id) 66 | ) 67 | ) 68 | } 69 | 70 | #' Carousel Indicators 71 | #' 72 | #' Carousel indicators 73 | #' 74 | #' @param items list of [carouselItem()]. 75 | #' @param id Parent if of [carousel()]. 76 | #' @param show Whether to show the indicators. 77 | #' 78 | #' @keywords internal 79 | carouselIndicators <- \( 80 | items, 81 | id, 82 | show 83 | ) { 84 | if(!show) 85 | return() 86 | 87 | n <- length(items) 88 | lapply(1:n, \(i) { 89 | tags$button( 90 | type = "button", 91 | `data-bs-target` = sprintf("#%s", id), 92 | `data-bs-slide-to` = i - 1, 93 | class = if(i == 1) "active", 94 | `aria-current` = if(i == 1) "true" 95 | ) 96 | }) |> 97 | div( 98 | class = "carousel-indicators" 99 | ) 100 | } 101 | 102 | #' Carousel Controls 103 | #' 104 | #' Carousel control arrows. 105 | #' 106 | #' @param show Whether to show the control arrows. 107 | #' @param id ID of parent [carousel()]. 108 | #' 109 | #' @keywords internal 110 | carouselControls <- \( 111 | show, 112 | id 113 | ){ 114 | if(!show) 115 | return() 116 | 117 | tagList( 118 | tags$button( 119 | class = "carousel-control-prev", 120 | type = "button", 121 | `data-bs-target` = sprintf("#%s", id), 122 | `data-bs-slide` = "prev", 123 | tags$span( 124 | class = "carousel-control-prev-icon", 125 | `aria-hidden` = "true" 126 | ), 127 | tags$span( 128 | class = "visually-hidden", 129 | "Previous" 130 | ) 131 | ), 132 | tags$button( 133 | class = "carousel-control-next", 134 | type = "button", 135 | `data-bs-target` = sprintf("#%s", id), 136 | `data-bs-slide` = "next", 137 | tags$span( 138 | class = "carousel-control-next-icon", 139 | `aria-hidden` = "true" 140 | ), 141 | tags$span( 142 | class = "visually-hidden", 143 | "Next" 144 | ) 145 | ) 146 | ) 147 | } 148 | 149 | #' Carousel Item 150 | #' 151 | #' Carousel item to use within [carousel()]. 152 | #' 153 | #' @param ... Content of item. 154 | #' @param interval Number of milliseconds this item should be shown. 155 | #' @param class Additional classes. 156 | #' 157 | #' @export 158 | carouselItem <- \( 159 | ..., 160 | interval = NULL, 161 | class = "" 162 | ) { 163 | div( 164 | class = sprintf("carousel-item %s", class), 165 | `data-bs-interval` = interval, 166 | ... 167 | ) 168 | } 169 | 170 | #' Carousel Image 171 | #' 172 | #' Carousel image to use within [carouselItem()]. 173 | #' 174 | #' @param ... Passed to ``. 175 | #' @param class Additional classes. 176 | #' 177 | #' @export 178 | carouselImg <- \( 179 | ..., 180 | class = "" 181 | ) { 182 | tags$img( 183 | class = sprintf("d-block w-100 %s", class), 184 | ... 185 | ) 186 | } 187 | -------------------------------------------------------------------------------- /R/close.R: -------------------------------------------------------------------------------- 1 | #' Close Button 2 | #' 3 | #' Button to dismiss or close a component. 4 | #' 5 | #' @export 6 | closeButton <- \() { 7 | tags$button( 8 | type = "button", 9 | class = "btn-close", 10 | `aria-label` = "Close" 11 | ) 12 | } -------------------------------------------------------------------------------- /R/collapse.R: -------------------------------------------------------------------------------- 1 | #' Collapse 2 | #' 3 | #' Create a collapsible. 4 | #' 5 | #' @param trigger A [collapseButton()] or [collapseLink()]. 6 | #' @param content The offcanvas content as returned by 7 | #' [offcanvasContent()]. 8 | #' 9 | #' @examples 10 | #' library(shiny) 11 | #' 12 | #' ui <- fluidPage( 13 | #' theme = bslib::bs_theme(version = 5L), 14 | #' collapse( 15 | #' collapseLink( 16 | #' "Reveal" 17 | #' ), 18 | #' collapseContent( 19 | #' "Some collapsed content" 20 | #' ) 21 | #' ) 22 | #' ) 23 | #' 24 | #' server <- \(input, output, session){ 25 | #' 26 | #' } 27 | #' 28 | #' if(interactive()) 29 | #' shinyApp(ui, server) 30 | #' 31 | #' @importFrom htmltools tagGetAttribute 32 | #' 33 | #' @name collapse 34 | #' @export 35 | collapse <- \(trigger, content) UseMethod("collapse") 36 | 37 | #' @describeIn collapse Collapse wrapper 38 | #' @method collapse collapseTrigger 39 | #' @export 40 | collapse.collapseTrigger <- \( 41 | trigger, 42 | content 43 | ){ 44 | if(missing(trigger)) 45 | stop("Missing `trigger`") 46 | 47 | if(missing(content)) 48 | stop("Missing `content`") 49 | 50 | target_id <- tagGetAttribute(content, "id") 51 | 52 | tagList( 53 | trigger(target_id), 54 | content 55 | ) 56 | } 57 | 58 | #' Collapse Button 59 | #' 60 | #' Collapse button. 61 | #' 62 | #' @param ... Passed to the button. 63 | #' @param id Button id. 64 | #' @param class Additional classes to pass to the button. 65 | #' 66 | #' @examples 67 | #' library(shiny) 68 | #' 69 | #' ui <- fluidPage( 70 | #' theme = bslib::bs_theme(version = 5L), 71 | #' collapse( 72 | #' collapseButton( 73 | #' "Reveal" 74 | #' ), 75 | #' collapseContent( 76 | #' "Some collapsed content" 77 | #' ) 78 | #' ) 79 | #' ) 80 | #' 81 | #' server <- \(input, output, session){ 82 | #' 83 | #' } 84 | #' 85 | #' if(interactive()) 86 | #' shinyApp(ui, server) 87 | #' 88 | #' @export 89 | collapseButton <- \( 90 | ..., 91 | id = NULL, 92 | class = "" 93 | ){ 94 | id <- get_id(id) 95 | class <- sprintf("btn btn-default action-button %s", class) 96 | 97 | btn <- \(target_id){ 98 | class <- sprintf("btn btn-default %s", class) 99 | tags$button( 100 | id = id, 101 | class = class, 102 | `data-bs-toggle` = "collapse", 103 | role = "button", 104 | `aria-expanded` = "false", 105 | `aria-controls` = target_id, 106 | href = sprintf("#%s", target_id), 107 | ... 108 | ) 109 | } 110 | 111 | structure( 112 | btn, 113 | class = c("collapseTrigger", class(btn)) 114 | ) 115 | } 116 | 117 | #' Collapse Link 118 | #' 119 | #' Collapse link. 120 | #' 121 | #' @param ... Passed to the link. 122 | #' @param id Link id. 123 | #' @param class Additional class to pass to the link. 124 | #' 125 | #' @export 126 | #' @name collapseLink 127 | collapseLink <- \( 128 | ..., 129 | id = NULL, 130 | class = "" 131 | ){ 132 | id <- get_id(id) 133 | class <- sprintf("action-button %s", class) 134 | 135 | lnk <- \(target_id){ 136 | tags$a( 137 | id = id, 138 | `data-bs-toggle` = "collapse", 139 | `aria-expanded` = "false", 140 | `aria-controls` = target_id, 141 | href = sprintf("#%s", target_id), 142 | ... 143 | ) 144 | } 145 | 146 | structure( 147 | lnk, 148 | class = c("collapseTrigger", class(lnk)) 149 | ) 150 | } 151 | 152 | #' Collapse Content 153 | #' 154 | #' Collapse content, to pass to [collapseButton()] or 155 | #' [collapseLink()]. 156 | #' 157 | #' @param ... Content of the collapsible. 158 | #' @param .id Id of the element. 159 | #' 160 | #' @export 161 | collapseContent <- \( 162 | ..., 163 | .id = NULL 164 | ){ 165 | 166 | id <- get_id(.id) 167 | 168 | content <- div( 169 | class = "collapse", 170 | id = id, 171 | ... 172 | ) 173 | 174 | structure( 175 | content, 176 | class = c("collapseContent", class(content)) 177 | ) 178 | } 179 | -------------------------------------------------------------------------------- /R/dependencies.R: -------------------------------------------------------------------------------- 1 | #' Get Dependencies 2 | #' 3 | #' Get a dependency. 4 | #' 5 | #' @param name Name of dependency. 6 | #' 7 | #' @importFrom utils packageVersion 8 | #' 9 | #' @keywords internal 10 | get_dep <- \( 11 | name 12 | ) { 13 | htmltools::htmlDependency( 14 | name = sprintf("bsutils-%s", name), 15 | version = packageVersion("bsutils"), 16 | package = "bsutils", 17 | src = "assets", 18 | script = sprintf("%s.js", name) 19 | ) 20 | } 21 | -------------------------------------------------------------------------------- /R/dropdown.R: -------------------------------------------------------------------------------- 1 | #' Dropdown Button 2 | #' 3 | #' Dropdown buttons for [shiny::actionLink()]. 4 | #' 5 | #' @param label Label of the dropdown. 6 | #' @param ... [shiny::actionLink()] to place within the 7 | #' dropdown. 8 | #' @param id ID of parent dropdown. 9 | #' @param class Additional class for dropdown button. 10 | #' 11 | #' @examples 12 | #' library(shiny) 13 | #' 14 | #' ui <- fluidPage( 15 | #' theme = bslib::bs_theme(version = 5L), 16 | #' dropdownButton( 17 | #' "Buttons", 18 | #' actionLink("first", "First"), 19 | #' actionLink("second", "Second") 20 | #' ) 21 | #' ) 22 | #' 23 | #' server <- \(input, output, session){ 24 | #' 25 | #' } 26 | #' 27 | #' if(interactive()) 28 | #' shinyApp(ui, server) 29 | #' 30 | #' @importFrom htmltools tagAppendAttributes 31 | #' 32 | #' @export 33 | dropdownButton <- \( 34 | label, 35 | ..., 36 | id = NULL, 37 | class = "" 38 | ) { 39 | 40 | id <- get_id(id) 41 | class <- sprintf("btn btn-default dropdown-toggle %s", class) 42 | 43 | btns <- list(...) |> 44 | lapply(\(btn) { 45 | btn <- tagAppendAttributes(btn, class = "dropdown-item") 46 | tags$li(btn) 47 | }) 48 | 49 | div( 50 | class = "dropdown", 51 | tags$button( 52 | class = class, 53 | type = "button", 54 | `data-bs-toggle` = "dropdown", 55 | `aria-expanded` = "false", 56 | id = id, 57 | label 58 | ), 59 | tags$ul( 60 | class = "dropdown-menu", 61 | `aria-labelledby` = id, 62 | btns 63 | ) 64 | ) 65 | } -------------------------------------------------------------------------------- /R/gallery.R: -------------------------------------------------------------------------------- 1 | #' Gallery 2 | #' 3 | #' Demo of utilities. 4 | #' 5 | #' @export 6 | gallery <- \(){ 7 | shiny::shinyAppFile( 8 | system.file("app/app.R", package = "bsutils") 9 | ) 10 | } -------------------------------------------------------------------------------- /R/group.R: -------------------------------------------------------------------------------- 1 | #' Button Group 2 | #' 3 | #' Group of buttons. 4 | #' 5 | #' @param ... Any [shiny::actionButton()]. 6 | #' @param class Any additional class. 7 | #' 8 | #' @examples 9 | #' library(shiny) 10 | #' 11 | #' ui <- fluidPage( 12 | #' theme = bslib::bs_theme(version = 5L), 13 | #' buttonGroup( 14 | #' actionButton("first", "First", class = "btn-primary"), 15 | #' actionButton("second", "Second", class = "btn-warning"), 16 | #' actionButton("third", "Third", class = "btn-success") 17 | #' ) 18 | #' ) 19 | #' 20 | #' server <- \(input, output, session){ 21 | #' 22 | #' } 23 | #' 24 | #' if(interactive()) 25 | #' shinyApp(ui, server) 26 | #' 27 | #' @export 28 | buttonGroup <- \( 29 | ..., 30 | class = "" 31 | ) { 32 | div( 33 | class = sprintf("btn-group %s", class), 34 | ... 35 | ) 36 | } 37 | -------------------------------------------------------------------------------- /R/inputs.R: -------------------------------------------------------------------------------- 1 | #' Text Input Floating Label 2 | #' 3 | #' Text input with floating label. 4 | #' 5 | #' @param inputId ID of input. 6 | #' @param label Label of input. 7 | #' @param placeholder Placeholder value. 8 | #' @param value Value of input. 9 | #' @param ... Passed to input. 10 | #' 11 | #' @export 12 | floatingTextInput <- \( 13 | inputId, 14 | label, 15 | placeholder, 16 | value = "", 17 | ... 18 | ) { 19 | if(missing(inputId)) 20 | stop("Missing `inputId`") 21 | 22 | if(missing(label)) 23 | stop("Missing `label`") 24 | 25 | if(missing(placeholder)) 26 | stop("Missing `placeholder`") 27 | 28 | div( 29 | class = "form-floating", 30 | tags$input( 31 | id = inputId, 32 | type = "text", 33 | class = "form-control", 34 | placeholder = placeholder, 35 | value = value, 36 | ... 37 | ), 38 | tags$label( 39 | `for` = inputId, 40 | label 41 | ) 42 | ) 43 | } 44 | 45 | #' Text Area Input Floating Label 46 | #' 47 | #' Text area input with floating label. 48 | #' 49 | #' @param inputId ID of input. 50 | #' @param label Label of input. 51 | #' @param placeholder Placeholder value. 52 | #' @param value Value of input. 53 | #' @param ... Passed to input. 54 | #' 55 | #' @export 56 | floatingTextAreaInput <- \( 57 | inputId, 58 | label, 59 | placeholder, 60 | value = "", 61 | ... 62 | ) { 63 | if(missing(inputId)) 64 | stop("Missing `inputId`") 65 | 66 | if(missing(label)) 67 | stop("Missing `label`") 68 | 69 | if(missing(placeholder)) 70 | stop("Missing `placeholder`") 71 | 72 | div( 73 | class = "form-floating", 74 | tags$textarea( 75 | id = inputId, 76 | class = "form-control", 77 | placeholder = placeholder, 78 | value = value, 79 | ... 80 | ), 81 | tags$label( 82 | `for` = inputId, 83 | label 84 | ) 85 | ) 86 | } 87 | 88 | #' Select Floating Label 89 | #' 90 | #' Select input with floating label. 91 | #' 92 | #' @param inputId ID of input. 93 | #' @param label Label of input. 94 | #' @param choices Choices, named vector. 95 | #' @param ... Passed to input. 96 | #' 97 | #' @importFrom htmltools tagAppendChild 98 | #' 99 | #' @export 100 | floatingSelectInput <- \( 101 | inputId, 102 | label, 103 | choices = NULL, 104 | ... 105 | ) { 106 | if(missing(inputId)) 107 | stop("Missing `inputId`") 108 | 109 | if(missing(label)) 110 | stop("Missing `label`") 111 | 112 | select <- tags$select( 113 | id = inputId, 114 | class = "form-select", 115 | `aria-label` = label 116 | ) 117 | 118 | if(!is.null(choices)){ 119 | for(i in 1:length(choices)) { 120 | nm <- names(choices)[i] 121 | if(is.null(nm)) 122 | nm <- unname(choices[i]) 123 | 124 | opt <- tags$option( 125 | value = unname(choices[i]), 126 | nm 127 | ) 128 | select <- tagAppendChildren(select, opt) 129 | } 130 | } 131 | 132 | div( 133 | class = "form-floating", 134 | select, 135 | tags$label( 136 | `for` = inputId, 137 | label 138 | ) 139 | ) 140 | } 141 | 142 | #' Switch Input 143 | #' 144 | #' Switch input, similar to checkbox. 145 | #' 146 | #' @param inputId ID of input. 147 | #' @param label Label of input. 148 | #' @param checked Whether the input is initialised checked. 149 | #' @param ... Passed to input. 150 | #' 151 | #' @export 152 | switchInput <- \( 153 | inputId, 154 | label, 155 | checked = FALSE, 156 | ... 157 | ) { 158 | if(missing(inputId)) 159 | stop("Missing `inputId`") 160 | 161 | if(missing(label)) 162 | stop("Missing `label`") 163 | 164 | input <- tags$input( 165 | class = "form-check-input", 166 | type = "checkbox", 167 | id = inputId, 168 | ... 169 | ) 170 | 171 | if(checked) 172 | input <- tagAppendAttributes(input, checked = NA) 173 | 174 | div( 175 | class = "form-check form-switch", 176 | input, 177 | tags$label( 178 | class = "form-check-label", 179 | `for` = inputId, 180 | label 181 | ) 182 | ) 183 | } 184 | 185 | #' Color Picker Input 186 | #' 187 | #' Color picker input. 188 | #' 189 | #' @param inputId ID of input. 190 | #' @param value Initial value of the input. 191 | #' @param ... Passed to input. 192 | #' 193 | #' @export 194 | colorPickerInput <- \( 195 | inputId, 196 | value = NULL, 197 | ... 198 | ) { 199 | if(missing(inputId)) 200 | stop("Missing `inputId`") 201 | 202 | tagList( 203 | get_dep("color"), 204 | tags$input( 205 | type = "color", 206 | class = "form-control form-control-color bsutils-color", 207 | id = inputId, 208 | value = value, 209 | ... 210 | ) 211 | ) 212 | } 213 | 214 | #' Update Color Picker 215 | #' 216 | #' Update a [colorPickerInput()] from the server. 217 | #' 218 | #' @param id ID of input to update. 219 | #' @param value Value to set. 220 | #' @param session A valid shiny session. 221 | #' 222 | #' @export 223 | update_color_picker <- \( 224 | id, 225 | value, 226 | session = shiny::getDefaultReactiveDomain() 227 | ){ 228 | if(missing(id)) 229 | stop("Missing `id`") 230 | 231 | if(missing(value)) 232 | stop("Missing `value`") 233 | 234 | session$sendInputMessage(id, value) 235 | } 236 | 237 | #' Range Input 238 | #' 239 | #' A range input similar to a slider. 240 | #' 241 | #' @param id ID of input. 242 | #' @param label Label of input. 243 | #' @param value Initial value of input. 244 | #' @param min,max Minimum and maximum values of the range. 245 | #' @param step Step of range change. 246 | #' @param ... Passed to input. 247 | #' 248 | #' @export 249 | rangeInput <- \( 250 | id, 251 | label, 252 | value = 0L, 253 | ..., 254 | min = 0L, 255 | max = 100L, 256 | step = 1L 257 | ) { 258 | if(missing(id)) 259 | stop("Missing `id`") 260 | 261 | if(missing(label)) 262 | stop("Missing `label`") 263 | 264 | tagList( 265 | get_dep("range"), 266 | tags$label( 267 | label, 268 | `for` = id, 269 | class = "form-label" 270 | ), 271 | tags$input( 272 | type = "range", 273 | class = "form-range bsutils-range", 274 | id = id, 275 | value = value, 276 | min = min, 277 | max = max, 278 | step = step, 279 | ... 280 | ) 281 | ) 282 | } 283 | 284 | #' Update Range 285 | #' 286 | #' Update a [rangeInput()] from the server. 287 | #' 288 | #' @param id ID of input to update. 289 | #' @param session A valid shiny session. 290 | #' @param ... Elements to update, one or more of, 291 | #' `value`, `min`, and `max`. 292 | #' 293 | #' @export 294 | update_range <- \( 295 | id, 296 | ..., 297 | session = shiny::getDefaultReactiveDomain() 298 | ) { 299 | if(missing(id)) 300 | stop("Missing `id`") 301 | 302 | session$sendInputMessage( 303 | id, 304 | list(...) 305 | ) 306 | } 307 | 308 | #' Text Group Input 309 | #' 310 | #' Text group input. 311 | #' 312 | #' @param inputId ID of input. 313 | #' @param label Label of input. 314 | #' @param value Initial value of input. 315 | #' @param placeholder Placeholder for input. 316 | #' @param .position Position of the label. 317 | #' 318 | #' @importFrom htmltools tagAppendChildren attachDependencies 319 | #' 320 | #' @export 321 | textGroupInput <- \( 322 | inputId, 323 | label, 324 | value = "", 325 | placeholder = NULL, 326 | .position = c("left", "right") 327 | ) { 328 | if(missing(inputId)) 329 | stop("Missing `inputId`") 330 | 331 | if(missing(label)) 332 | stop("Missing `label`") 333 | 334 | .position <- match.arg(.position) 335 | 336 | input <- tags$input( 337 | id = inputId, 338 | value = value, 339 | placeholder = placeholder, 340 | class = "form-control bsutils-text-group" 341 | ) 342 | 343 | label <- span( 344 | class = "input-group-text", 345 | label 346 | ) 347 | 348 | wrapper <- div( 349 | class = "input-group" 350 | ) 351 | 352 | if(.position == "left") 353 | div <- tagAppendChildren( 354 | wrapper, 355 | label, 356 | input 357 | ) 358 | 359 | if(.position == "right") 360 | div <- tagAppendChildren( 361 | wrapper, 362 | input, 363 | label 364 | ) 365 | 366 | attachDependencies( 367 | div, 368 | get_dep("text-group") 369 | ) 370 | } 371 | 372 | #' Update Text Group Input 373 | #' 374 | #' Update [textGroupInput()]. 375 | #' 376 | #' @param id ID of input to update. 377 | #' @param ... Items to update; `value`, and/or `label`. 378 | #' @param session Valid shiny session. 379 | #' 380 | #' @export 381 | update_text_group <- \( 382 | id, 383 | ..., 384 | session = shiny::getDefaultReactiveDomain() 385 | ) { 386 | session$sendInputMessage( 387 | id, 388 | list( 389 | ... 390 | ) 391 | ) 392 | } 393 | -------------------------------------------------------------------------------- /R/list.R: -------------------------------------------------------------------------------- 1 | #' List Group 2 | #' 3 | #' List group, see [listGroupItem()]. 4 | #' 5 | #' @param ... Content of the list group, see [listGroupItem()]. 6 | #' 7 | #' @export 8 | listGroup <- \( 9 | ... 10 | ) { 11 | tags$ul( 12 | class = "list-group", 13 | ... 14 | ) 15 | } 16 | 17 | #' List Group Item 18 | #' 19 | #' Items for [listGroup()]. 20 | #' 21 | #' @param ... Content. 22 | #' @param class Additional classes. 23 | #' 24 | #' @export 25 | listGroupItem <- \( 26 | ..., 27 | class = "" 28 | ) { 29 | tags$li( 30 | class = sprintf("list-group-item %s", class), 31 | ... 32 | ) 33 | } -------------------------------------------------------------------------------- /R/modal.R: -------------------------------------------------------------------------------- 1 | #' Modal 2 | #' 3 | #' Create a modal in the UI. 4 | #' The modal is not down see [modal_show()], or 5 | #' [modal_toggle()] (from server). 6 | #' 7 | #' @param id ID of modal. 8 | #' @param ... Content of the modal, [modalBody()], 9 | #' [modalHeader()], [modalFooter()]. 10 | #' @param static_backdrop When backdrop is set to static, 11 | #' the modal will not close when clicking outside it. 12 | #' @param scrollable Whether to make the content scrollable. 13 | #' @param centered Whether to make the content vertically 14 | #' centered. 15 | #' @param size Size of the modal. 16 | #' 17 | #' @examples 18 | #' library(shiny) 19 | #' 20 | #' ui <- fluidPage( 21 | #' theme = bslib::bs_theme(version = 5L), 22 | #' actionButton("show", "Show modal"), 23 | #' modal( 24 | #' id = "modal", 25 | #' modalHeader( 26 | #' modalTitle("Title") 27 | #' ), 28 | #' modalBody( 29 | #' p("The content of the modal") 30 | #' ), 31 | #' modalFooter( 32 | #' p("The footer of the modal") 33 | #' ) 34 | #' ) 35 | #' ) 36 | #' 37 | #' server <- \(input, output, session){ 38 | #' observeEvent(input$show, { 39 | #' modal_show("modal") 40 | #' }) 41 | #' } 42 | #' 43 | #' if(interactive()) 44 | #' shinyApp(ui, server) 45 | #' 46 | #' @export 47 | modal <- \( 48 | id, 49 | ..., 50 | static_backdrop = FALSE, 51 | scrollable = FALSE, 52 | centered = FALSE, 53 | size = c( 54 | "default", 55 | "sm", 56 | "lg", 57 | "xl", 58 | "fullscreen", 59 | "fullscreen-sm-down", 60 | "fullscreen-md-down", 61 | "fullscreen-lg-down", 62 | "fullscreen-xl-down", 63 | "fullscreen-xxl-down" 64 | ) 65 | ) { 66 | if(missing(id)) 67 | stop("Missing `id`") 68 | 69 | size <- match.arg(size) 70 | 71 | dialog_class <- "modal-dialog" 72 | if(scrollable) 73 | dialog_class <- sprintf("%s modal-dialog-scrollable", dialog_class) 74 | 75 | if(centered) 76 | dialog_class <- sprintf("%s modal-dialog-centered", dialog_class) 77 | 78 | dialog_class <- sprintf("%s modal-%s", dialog_class, size) 79 | 80 | modal <- div( 81 | get_dep("modal"), 82 | class = "modal fade", 83 | id = id, 84 | tabindex = "-1", 85 | `aria-hidden` = "true", 86 | div( 87 | class = dialog_class, 88 | div( 89 | class = "modal-content", 90 | ... 91 | ) 92 | ) 93 | ) 94 | 95 | if(static_backdrop) 96 | modal <- modal |> 97 | tagAppendAttributes( 98 | `data-bs-backdrop` = "static" 99 | ) 100 | 101 | modal 102 | } 103 | 104 | #' Modal Header 105 | #' 106 | #' Header of a modal, place within [modal()]. 107 | #' 108 | #' @param ... Content. 109 | #' @param .close Whether to add the close button. 110 | #' 111 | #' @export 112 | modalHeader <- \( 113 | ..., 114 | .close = TRUE 115 | ) { 116 | if(!.close) 117 | return(div(class = "modal-header", ...)) 118 | 119 | div( 120 | class = "modal-header", 121 | ..., 122 | tags$button( 123 | type = "button", 124 | class = "btn-close", 125 | `data-bs-dismiss` = "modal", 126 | `aria-label` = "Close" 127 | ) 128 | ) 129 | } 130 | 131 | #' Modal Title 132 | #' 133 | #' Modal title, place within [modalHeader()]. 134 | #' 135 | #' @param title An HTML tag or a character vector of length 1. 136 | #' 137 | #' @export 138 | modalTitle <- \( 139 | title 140 | ) { 141 | if(inherits(title, "character")) 142 | return(h5(class = "modal-title", title)) 143 | 144 | tagAppendAttributes( 145 | title, 146 | class = "modal-title" 147 | ) 148 | } 149 | 150 | #' Modal Body 151 | #' 152 | #' Body of the modal, place within [modal()]. 153 | #' 154 | #' @param ... Content of the body. 155 | #' 156 | #' @export 157 | modalBody <- \( 158 | ... 159 | ) { 160 | div( 161 | class = "modal-body", 162 | ... 163 | ) 164 | } 165 | 166 | #' Modal Footer 167 | #' 168 | #' Footer of the modal, place within [modal()]. 169 | #' 170 | #' @param ... Content of the footer. 171 | #' 172 | #' @export 173 | modalFooter <- \( 174 | ... 175 | ) { 176 | div( 177 | class = "modal-footer", 178 | ... 179 | ) 180 | } 181 | 182 | #' Modal Toggle 183 | #' 184 | #' Show, hide, or toggle a modal from the server. 185 | #' 186 | #' @param id ID of the [modal()]. 187 | #' @param session A valid shiny session. 188 | #' 189 | #' @name modalToggle 190 | #' @export 191 | modal_show <- \( 192 | id, 193 | session = shiny::getDefaultReactiveDomain() 194 | ) { 195 | if(missing(id)) 196 | stop("Missing `id`") 197 | 198 | session$sendCustomMessage( 199 | "bsutils-modal", 200 | list( 201 | id = id, 202 | action = "show" 203 | ) 204 | ) 205 | } 206 | 207 | #' @rdname modalToggle 208 | #' @export 209 | modal_hide <- \( 210 | id, 211 | session = shiny::getDefaultReactiveDomain() 212 | ) { 213 | if(missing(id)) 214 | stop("Missing `id`") 215 | 216 | session$sendCustomMessage( 217 | "bsutils-modal", 218 | list( 219 | id = id, 220 | action = "hide" 221 | ) 222 | ) 223 | } 224 | 225 | #' @rdname modalToggle 226 | #' @export 227 | modal_toggle <- \( 228 | id, 229 | session = shiny::getDefaultReactiveDomain() 230 | ) { 231 | if(missing(id)) 232 | stop("Missing `id`") 233 | 234 | session$sendCustomMessage( 235 | "bsutils-modal", 236 | list( 237 | id = id, 238 | action = "toggle" 239 | ) 240 | ) 241 | } 242 | 243 | #' Modal Triggers 244 | #' 245 | #' Trigger open a modal with a button or a link, 246 | #' avoids goind through the server. 247 | #' 248 | #' @param target Target ID of the [modal()] to show. 249 | #' @param ... Content of link or button, generally a 250 | #' character vector of length 1. 251 | #' @param class Additional class to pass to the button. 252 | #' 253 | #' @name modalTrigger 254 | #' @export 255 | modalButton <- \( 256 | target, 257 | ..., 258 | class = "" 259 | ) { 260 | if(missing(target)) 261 | stop("Missing `target`") 262 | 263 | tags$button( 264 | class = sprintf("btn btn-default %s", class), 265 | `data-bs-toggle` = "modal", 266 | `data-bs-target` = sprintf("#%s", target), 267 | ... 268 | ) 269 | } 270 | 271 | #' @rdname modalTrigger 272 | #' @export 273 | modalLink <- \( 274 | target, 275 | ... 276 | ) { 277 | if(missing(target)) 278 | stop("Missing `target`") 279 | 280 | tags$button( 281 | `data-bs-toggle` = "modal", 282 | `data-bs-target` = sprintf("#%s", target), 283 | ... 284 | ) 285 | } -------------------------------------------------------------------------------- /R/offcanvas.R: -------------------------------------------------------------------------------- 1 | #' Offcanvas 2 | #' 3 | #' Create an offcanvas element. 4 | #' 5 | #' @param trigger A [collapseButton()], [collapseLink()], 6 | #' [shiny::actionButton()], [shiny::actionLink()]. 7 | #' @param content The offcanvas content as returned by 8 | #' [offcanvasContent()]. 9 | #' 10 | #' @examples 11 | #' library(shiny) 12 | #' 13 | #' ui <- fluidPage( 14 | #' theme = bslib::bs_theme(version = 5L), 15 | #' offcanvas( 16 | #' offcanvasButton( 17 | #' "Open" 18 | #' ), 19 | #' offcanvasContent( 20 | #' offcanvasHeader( 21 | #' "Off canvas" 22 | #' ), 23 | #' p( 24 | #' "Hello world" 25 | #' ) 26 | #' ) 27 | #' ) 28 | #' ) 29 | #' 30 | #' server <- \(input, output, session){ 31 | #' 32 | #' } 33 | #' 34 | #' if(interactive()) 35 | #' shinyApp(ui, server) 36 | #' 37 | #' @importFrom htmltools tagGetAttribute 38 | #' 39 | #' @name offcanvas 40 | #' @export 41 | offcanvas <- \(trigger, content) UseMethod("offcanvas") 42 | 43 | #' @describeIn offcanvas Offcanvas wrapper for [collapseButton()], [collapseLink()]. 44 | #' @method offcanvas offcanvasTrigger 45 | #' @export 46 | offcanvas.offcanvasTrigger <- \( 47 | trigger, 48 | content 49 | ){ 50 | if(missing(trigger)) 51 | stop("Missing `trigger`") 52 | 53 | if(missing(content)) 54 | stop("Missing `content`") 55 | 56 | target_id <- tagGetAttribute(content, "id") 57 | 58 | tagList( 59 | trigger(target_id), 60 | content 61 | ) 62 | } 63 | 64 | #' @describeIn offcanvas Offcanvas wrapper for [shiny::actionButton()], [shiny::actionLink()]. 65 | #' @method offcanvas shiny.tag 66 | #' @export 67 | offcanvas.shiny.tag <- \( 68 | trigger, 69 | content 70 | ){ 71 | if(missing(trigger)) 72 | stop("Missing `trigger`") 73 | 74 | if(missing(content)) 75 | stop("Missing `content`") 76 | 77 | tagList( 78 | trigger, 79 | content 80 | ) 81 | } 82 | 83 | #' Offcanvas Button 84 | #' 85 | #' Offcanvas button trigger. 86 | #' 87 | #' @param ... Passed to the button. 88 | #' @param id ID of the button. 89 | #' @param class Additional class to pass to the button. 90 | #' @inheritParams withTooltip 91 | #' 92 | #' @export 93 | offcanvasButton <- \( 94 | ..., 95 | id = NULL, 96 | class = "" 97 | ) { 98 | id <- get_id(id) 99 | class <- sprintf("btn btn-default action-button %s", class) 100 | 101 | btn <- \(target_id) { 102 | tags$button( 103 | id = id, 104 | class = class, 105 | type = "button", 106 | `data-bs-toggle` = "offcanvas", 107 | `data-bs-target` = sprintf("#%s", target_id), 108 | `aria-controls` = target_id, 109 | ... 110 | ) 111 | } 112 | 113 | structure( 114 | btn, 115 | class = c("offcanvasTrigger", class(btn)) 116 | ) 117 | } 118 | 119 | #' @rdname offcanvasButton 120 | #' @export 121 | offcanvasButtonWithTooltip <- \( 122 | ..., 123 | title, 124 | placement = c( 125 | "top", 126 | "right", 127 | "bottom", 128 | "left" 129 | ), 130 | id = NULL, 131 | class = "" 132 | ) { 133 | placement <- match.arg(placement) 134 | id <- get_id(id) 135 | class <- sprintf("btn btn-default action-button %s", class) 136 | 137 | btn <- \(target_id) { 138 | tags$span( 139 | `data-bs-toggle` = "offcanvas", 140 | `data-bs-target` = sprintf("#%s", target_id), 141 | `aria-controls` = target_id, 142 | tags$button( 143 | id = id, 144 | title = HTML(as.character(title)), 145 | class = class, 146 | type = "button", 147 | `data-bs-toggle` = "tooltip", 148 | ... 149 | ) 150 | ) |> 151 | htmltools::attachDependencies( 152 | get_dep("tooltip") 153 | ) 154 | } 155 | 156 | structure( 157 | btn, 158 | class = c("offcanvasTrigger", class(btn)) 159 | ) 160 | } 161 | 162 | #' Offcanvas Link 163 | #' 164 | #' Offcanvas link trigger. 165 | #' 166 | #' @param ... Passed to the button. 167 | #' @param id ID of the link. 168 | #' @param class Additional class to pass to the button. 169 | #' 170 | #' @export 171 | offcanvasLink <- \( 172 | ..., 173 | id = NULL, 174 | class = "" 175 | ) { 176 | id <- get_id(id) 177 | class <- sprintf("action-button %s", class) 178 | 179 | lnk <- \(target_id) { 180 | tags$a( 181 | id = id, 182 | class = class, 183 | `data-bs-toggle` = "offcanvas", 184 | `data-bs-target` = sprintf("#%s", target_id), 185 | `aria-controls` = target_id, 186 | ... 187 | ) 188 | } 189 | 190 | structure( 191 | lnk, 192 | class = c("offcanvasTrigger", class(lnk)) 193 | ) 194 | } 195 | 196 | #' Offcanvas Content 197 | #' 198 | #' Offcanvas content. 199 | #' 200 | #' @param ... Content of the offcanvas. 201 | #' @param id Id of the canvas. 202 | #' @param class Additional classes. 203 | #' @param .position Where the canvas should open. 204 | #' @param scroll Whether to allow scrolling the body. 205 | #' 206 | #' @export 207 | offcanvasContent <- \( 208 | ..., 209 | id = NULL, 210 | class = "", 211 | .position = c("start", "end", "top", "bottom"), 212 | scroll = TRUE 213 | ) { 214 | id <- get_id(id) 215 | position <- match.arg(.position) 216 | class <- sprintf("offcanvas offcanvas-%s %s", position, class) 217 | 218 | content <- div( 219 | get_dep("offcanvas"), 220 | class = class, 221 | tabindex = "-1", 222 | id = id, 223 | `data-bs-scroll` = tolower(scroll), 224 | div( 225 | class = "offcanvas-body", 226 | ... 227 | ) 228 | ) 229 | 230 | structure( 231 | content, 232 | class = c("offcanvasContent", class(content)) 233 | ) 234 | } 235 | 236 | #' Canvas Header 237 | #' 238 | #' Header for [offcanvasContent()]. 239 | #' 240 | #' @param header An HTML tag or a character string. 241 | #' 242 | #' @export 243 | offcanvasHeader <- \( 244 | header 245 | ) { 246 | if(missing(header)) 247 | stop("Missing `header`") 248 | 249 | if(is.character(header)) 250 | header <- h5(header) 251 | 252 | div( 253 | class = "offcanvas-header", 254 | header, 255 | tags$button( 256 | type = "button", 257 | class = "btn-close text-reset", 258 | `data-bs-dismiss` = "offcanvas", 259 | `aria-label` = "Close" 260 | ) 261 | ) 262 | } 263 | 264 | #' Offcanvas Server 265 | #' 266 | #' Toggle the offcanvas from the server. 267 | #' 268 | #' @param id ID of [offcanvasContent()]. 269 | #' @param session Valid shiny session. 270 | #' 271 | #' @name offcanvasServer 272 | #' @export 273 | offcanvas_show <- \( 274 | id, 275 | session = shiny::getDefaultReactiveDomain() 276 | ) { 277 | if(missing(id)) 278 | stop("Missing `id`") 279 | 280 | session$sendCustomMessage( 281 | "bsutils-offcanvas", 282 | list( 283 | id = id, 284 | action = "show" 285 | ) 286 | ) 287 | } 288 | 289 | #' @rdname offcanvasServer 290 | #' @export 291 | offcanvas_hide <- \( 292 | id, 293 | session = shiny::getDefaultReactiveDomain() 294 | ) { 295 | if(missing(id)) 296 | stop("Missing `id`") 297 | 298 | session$sendCustomMessage( 299 | "bsutils-offcanvas", 300 | list( 301 | id = id, 302 | action = "hide" 303 | ) 304 | ) 305 | } 306 | 307 | #' @rdname offcanvasServer 308 | #' @export 309 | offcanvas_toggle <- \( 310 | id, 311 | session = shiny::getDefaultReactiveDomain() 312 | ) { 313 | if(missing(id)) 314 | stop("Missing `id`") 315 | 316 | session$sendCustomMessage( 317 | "bsutils-offcanvas", 318 | list( 319 | id = id, 320 | action = "toggle" 321 | ) 322 | ) 323 | } 324 | -------------------------------------------------------------------------------- /R/placeholders.R: -------------------------------------------------------------------------------- 1 | #' As Placeholder 2 | #' 3 | #' Turn an element into a placeholder. 4 | #' 5 | #' @param el Element to turn into a placeholder. 6 | #' @param glow Whether the elements should glow. 7 | #' 8 | #' @examples 9 | #' shiny::p() |> 10 | #' asPlaceholder() 11 | #' 12 | #' shiny::actionButton("id", "") |> 13 | #' asPlaceholder() 14 | #' 15 | #' @export 16 | asPlaceholder <- \(el, glow = FALSE){ 17 | if(missing(el)) 18 | stop("Missing `el`") 19 | 20 | cls <- "placeholder" 21 | if(glow) 22 | cls <- paste0(cls, "-glow") 23 | 24 | htmltools::tagAppendAttributes( 25 | el, 26 | class = cls 27 | ) 28 | } -------------------------------------------------------------------------------- /R/popover.R: -------------------------------------------------------------------------------- 1 | #' Popover 2 | #' 3 | #' Add a popover to an element. 4 | #' 5 | #' @param el Element to place popover on. 6 | #' @param content Content of the popover. 7 | #' @param title Optional popover title. 8 | #' @param container container of the popover. 9 | #' @param placement Position of the popover. 10 | #' 11 | #' @export 12 | withPopover <- \( 13 | el, 14 | content, 15 | title = NULL, 16 | container = "body", 17 | placement = c( 18 | "top", 19 | "right", 20 | "bottom", 21 | "left" 22 | ) 23 | ) { 24 | if(missing(el)) 25 | stop("Missing `el`") 26 | 27 | if(missing(content)) 28 | stop("Missing `content`") 29 | 30 | placement <- match.arg(placement) 31 | 32 | el <- tagAppendAttributes( 33 | el, 34 | `data-bs-toggle` = "popover", 35 | `data-bs-content` = content, 36 | `data-bs-placement` = placement, 37 | `data-bs-container` = container 38 | ) 39 | 40 | if(!is.null(title)) 41 | el <- tagAppendAttributes( 42 | el, 43 | title = title 44 | ) 45 | 46 | htmltools::attachDependencies(el, get_dep("popover")) 47 | } -------------------------------------------------------------------------------- /R/progress.R: -------------------------------------------------------------------------------- 1 | #' Progress 2 | #' 3 | #' Progress bars. 4 | #' 5 | #' @param ... Progress bars as returned by [progressBar()]. 6 | #' @param id Parent id. 7 | #' 8 | #' @examples 9 | #' library(shiny) 10 | #' 11 | #' ui <- fluidPage( 12 | #' theme = bslib::bs_theme(version = 5L), 13 | #' actionButton( 14 | #' "rand", 15 | #' "Randomise" 16 | #' ), 17 | #' progress( 18 | #' progressBar(15, id = "bar") 19 | #' ) 20 | #' ) 21 | #' 22 | #' server <- \(input, output, session){ 23 | #' observeEvent(input$rand, { 24 | #' update_progress("bar", sample(10:99, 1)) 25 | #' }) 26 | #' } 27 | #' 28 | #' if(interactive()) 29 | #' shinyApp(ui, server) 30 | #' 31 | #' @export 32 | progress <- \( 33 | ..., 34 | id = NULL 35 | ) { 36 | div( 37 | class = "progress", 38 | ... 39 | ) 40 | } 41 | 42 | #' Progress Bar 43 | #' 44 | #' A progress bar to pass to [progress()]. 45 | #' 46 | #' @param value Value of progress bar. 47 | #' @param min,max Minimum and maximum values. 48 | #' @param id ID of progress bar. 49 | #' @param class Additional classes. 50 | #' 51 | #' @export 52 | progressBar <- \( 53 | value = 0L, 54 | min = 0L, 55 | max = 100L, 56 | id = NULL, 57 | class = "" 58 | ) { 59 | if(value < 0L || value > 100L) 60 | stop("`value` must be between 0 and 100") 61 | 62 | id <- get_id(id) 63 | val <- round((value / max) * 100) 64 | style <- sprintf("width: %s%%;", val) 65 | 66 | tagList( 67 | get_dep("progress"), 68 | div( 69 | id = id, 70 | class = sprintf("bsutils-progress progress-bar %s", class), 71 | role = "progressbar", 72 | style = style, 73 | `aria-valuenow` = value, 74 | `aria-valuemin` = min, 75 | `aria-valuemax` = max 76 | ) 77 | ) 78 | } 79 | 80 | #' Update Progress 81 | #' 82 | #' Update a [progressBar()]. 83 | #' 84 | #' @param id ID of progress bar to update. 85 | #' @param value Value to set the progress bar to. 86 | #' @param session A valid shiny session. 87 | #' 88 | #' @export 89 | update_progress <- \( 90 | id, 91 | value, 92 | session = shiny::getDefaultReactiveDomain() 93 | ){ 94 | if(missing(id)) 95 | stop("Missing `id`") 96 | 97 | if(missing(value)) 98 | stop("Missing `value`") 99 | 100 | session$sendInputMessage(id, value) 101 | } 102 | -------------------------------------------------------------------------------- /R/toast.R: -------------------------------------------------------------------------------- 1 | #' Toast 2 | #' 3 | #' Toast notifications. 4 | #' 5 | #' @param id ID of toast, used to show/hide from server. 6 | #' @param ... Content, generally [toastHeader()], [toastBody()]. 7 | #' @param class Any additional classes. 8 | #' @param position Position of the toast. 9 | #' 10 | #' @examples 11 | #' library(shiny) 12 | #' 13 | #' ui <- fluidPage( 14 | #' theme = bslib::bs_theme(version = 5L), 15 | #' toast( 16 | #' "toast", 17 | #' toastHeader( 18 | #' strong( 19 | #' "Toast", 20 | #' class = "me-auto" 21 | #' ) 22 | #' ), 23 | #' toastBody("The body of the toast!") 24 | #' ), 25 | #' h1("Hello"), 26 | #' actionButton("show", "Show toast"), 27 | #' actionButton("hide", "Hide toast") 28 | #' ) 29 | #' 30 | #' server <- \(input, output, session){ 31 | #' observeEvent(input$show, { 32 | #' toast_show("toast", auto_hide = FALSE) 33 | #' }) 34 | #' 35 | #' observeEvent(input$hide, { 36 | #' toast_hide("toast") 37 | #' }) 38 | #' } 39 | #' 40 | #' if(interactive()) 41 | #' shinyApp(ui, server) 42 | #' 43 | #' @export 44 | toast <- \( 45 | id, 46 | ..., 47 | class = "", 48 | position = c( 49 | "top-right", 50 | "top-left", 51 | "bottom-right", 52 | "bottom-left" 53 | ) 54 | ) { 55 | if(missing(id)) 56 | stop("Missing `id`") 57 | 58 | style <- get_position(position) 59 | 60 | tagList( 61 | get_dep("toast"), 62 | div( 63 | class = sprintf("position-fixed %s", style), 64 | div( 65 | class = sprintf("toast %s", class), 66 | role = "alert", 67 | `aria-live` = "assertive", 68 | `aria-atomic` = "true", 69 | id = id, 70 | ... 71 | ) 72 | ) 73 | ) 74 | } 75 | 76 | #' Toast Content 77 | #' 78 | #' Content of the toast to place within [toast()]. 79 | #' 80 | #' @param ... Content. 81 | #' @param class Any additional class. 82 | #' 83 | #' @name toastContent 84 | #' 85 | #' @export 86 | toastHeader <- \( 87 | ..., 88 | class = "" 89 | ) { 90 | div( 91 | class = sprintf("toast-header %s", class), 92 | ..., 93 | tags$button( 94 | type = "button", 95 | class = "btn-close", 96 | `data-bs-dismiss` = "toast", 97 | `aria-label` = "Close" 98 | ) 99 | ) 100 | } 101 | 102 | #' @rdname toastContent 103 | #' @export 104 | toastBody <- \( 105 | ..., 106 | class = "" 107 | ) { 108 | div( 109 | class = sprintf("toast-body %s", class), 110 | ... 111 | ) 112 | } 113 | 114 | #' Toast Toggle 115 | #' 116 | #' Show or hide a toast. 117 | #' 118 | #' @param id ID of [toast()] to toggle. 119 | #' @param animation Whether to animate the toast. 120 | #' @param auto_hide Whether to automatically hide the 121 | #' toast after `delay`. 122 | #' @param delay Milliseconds after which to hide the 123 | #' toast (if `auto_hide = TRUE`). 124 | #' @param session A valid shiny session. 125 | #' @param header,body Header and body of the toast 126 | #' to replace existing content. 127 | #' 128 | #' @name toastToggle 129 | #' 130 | #' @export 131 | toast_show <- \( 132 | id, 133 | header = NULL, 134 | body = NULL, 135 | animation = TRUE, 136 | auto_hide = TRUE, 137 | delay = 5000L, 138 | session = shiny::getDefaultReactiveDomain() 139 | ) { 140 | id <- namespace(session, id) 141 | 142 | if(!is.null(body)) 143 | body <- as.character(body) 144 | 145 | if(!is.null(header)) 146 | header <- as.character(header) 147 | 148 | session$sendCustomMessage( 149 | "bsutils-toast", 150 | list( 151 | id = id, 152 | action = "show", 153 | body = body, 154 | header = header, 155 | opts = list( 156 | animation = animation, 157 | autohide = auto_hide, 158 | delay = delay 159 | ) 160 | ) 161 | ) 162 | } 163 | 164 | #' @rdname toastToggle 165 | #' @export 166 | toast_hide <- \( 167 | id, 168 | session = shiny::getDefaultReactiveDomain() 169 | ) { 170 | id <- namespace(session, id) 171 | 172 | session$sendCustomMessage( 173 | "bsutils-toast", 174 | list( 175 | id = id, 176 | action = "hide", 177 | opts = list() 178 | ) 179 | ) 180 | } 181 | -------------------------------------------------------------------------------- /R/tooltip.R: -------------------------------------------------------------------------------- 1 | #' Tooltip 2 | #' 3 | #' Add a tooltip to an element. 4 | #' 5 | #' @param el Element. 6 | #' @param title HTML tag or character vector of length 1. 7 | #' @param placement Placement of the tooltip. 8 | #' 9 | #' @examples 10 | #' library(shiny) 11 | #' 12 | #' ui <- fluidPage( 13 | #' theme = bslib::bs_theme(version = 5L), 14 | #' withTooltip( 15 | #' span("plain"), 16 | #' "content" 17 | #' ), 18 | #' br(), 19 | #' withTooltip( 20 | #' span("HTML"), 21 | #' tagList( 22 | #' strong("HTML"), 23 | #' "content" 24 | #' ) 25 | #' ) 26 | #' ) 27 | #' 28 | #' server <- \(input, output, session){ 29 | #' } 30 | #' 31 | #' if(interactive()) 32 | #' shinyApp(ui, server) 33 | #' 34 | #' @export 35 | withTooltip <- \( 36 | el, 37 | title, 38 | placement = c( 39 | "top", 40 | "right", 41 | "bottom", 42 | "left" 43 | ) 44 | ) { 45 | placement <- match.arg(placement) 46 | tagAppendAttributes( 47 | el, 48 | title = HTML(as.character(title)), 49 | `data-bs-placement` = placement, 50 | `data-bs-toggle` = "tooltip", 51 | `data-bs-html` = "true" 52 | ) |> 53 | htmltools::attachDependencies( 54 | get_dep("tooltip") 55 | ) 56 | } -------------------------------------------------------------------------------- /R/utils.R: -------------------------------------------------------------------------------- 1 | make_id <- \(){ 2 | letters |> 3 | sample(10L) |> 4 | paste0(collapse = "") 5 | } 6 | 7 | get_id <- \(id = NULL) { 8 | if(!is.null(id)) 9 | return(id) 10 | 11 | make_id() 12 | } 13 | 14 | namespace <- \( 15 | session, 16 | id 17 | ) { 18 | ns <- session$ns(NULL) 19 | 20 | if(length(ns) == 0L) 21 | return(id) 22 | 23 | sprintf("%s-%s", ns, id) 24 | } 25 | 26 | get_position <- \( 27 | position = c( 28 | "top-right", 29 | "top-left", 30 | "bottom-right", 31 | "bottom-left" 32 | ) 33 | ) { 34 | position <- match.arg(position) 35 | 36 | if(position == "top-right") 37 | return("top-0 end-0") 38 | 39 | if(position == "top-left") 40 | return("top-0 start-0") 41 | 42 | if(position == "bottom-right") 43 | return("bottom-0 end-0") 44 | 45 | "bottom-0 start-0" 46 | } 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # bsutils 5 | 6 | UI utilities for Bootstrap 5 and Shiny. 7 | 8 | ## Installation 9 | 10 | ``` r 11 | # install.packages("devtools") 12 | devtools::install_github("JohnCoene/bsutils") 13 | ``` 14 | 15 | ## Utilities 16 | 17 | - Accordion 18 | - Alerts 19 | - Badge 20 | - Card 21 | - Carousel 22 | - Collapse 23 | - Color input 24 | - Dropdown 25 | - Floating select input 26 | - Floating text input 27 | - Floating textarea input 28 | - List group 29 | - Modal 30 | - Offcanvas 31 | - Placeholder 32 | - Popover 33 | - Progress 34 | - Range input 35 | - Switch input 36 | - Text group input 37 | - Toast 38 | - Tooltip 39 | 40 | ## Example 41 | 42 | Run `bsutils::gallery()` for a demo. 43 | 44 | Make sure you use __Bootstrap version 5__. 45 | 46 | ```r 47 | library(shiny) 48 | library(bsutils) 49 | 50 | ui <- fluidPage( 51 | theme = bslib::bs_theme(version = 5L), 52 | offcanvas( 53 | offcanvasButton( 54 | "Open" 55 | ), 56 | offcanvasContent( 57 | offcanvasHeader( 58 | "Off canvas" 59 | ), 60 | p( 61 | "Hello world" 62 | ) 63 | ) 64 | ) 65 | ) 66 | 67 | server <- \(input, output, session){} 68 | 69 | shinyApp(ui, server) 70 | ``` 71 | -------------------------------------------------------------------------------- /inst/app/app.R: -------------------------------------------------------------------------------- 1 | library(shiny) 2 | library(bsutils) 3 | 4 | code <- \(code) { 5 | tags$pre( 6 | tags$code( 7 | class = "language-r", 8 | code 9 | ) 10 | ) 11 | } 12 | 13 | ui <- navbarPage( 14 | "bsutils", 15 | theme = bslib::bs_theme(version = 5L), 16 | header = list( 17 | tags$link( 18 | href = "https://unpkg.com/prismjs@v1.x/themes/prism.css", 19 | rel = "stylesheet" 20 | ) 21 | ), 22 | tabPanel( 23 | "Accordion", 24 | fluidRow( 25 | column( 26 | 6, 27 | accordion( 28 | accordionItem( 29 | .expanded = TRUE, 30 | "Something", 31 | p("Some content") 32 | ), 33 | accordionItem( 34 | "Something else", 35 | p("Some other content") 36 | ), 37 | accordionItem( 38 | "Another thing", 39 | p("Some other item") 40 | ) 41 | ) 42 | ), 43 | column( 44 | 6, 45 | code( 46 | ' 47 | accordion( 48 | accordionItem( 49 | .expanded = TRUE, 50 | "Something", 51 | p("Some content") 52 | ), 53 | accordionItem( 54 | "Something else", 55 | p("Some other content") 56 | ), 57 | accordionItem( 58 | "Another thing", 59 | p("Some other item") 60 | ) 61 | )' 62 | ) 63 | ) 64 | ) 65 | ), 66 | tabPanel( 67 | "Carousel", 68 | carousel( 69 | indicators = TRUE, 70 | controls = TRUE, 71 | carouselItem( 72 | h5("First"), 73 | p("First carousel slide"), 74 | class = "bg-primary rounded p-4" 75 | ), 76 | carouselItem( 77 | h5("Second"), 78 | p("Second carousel slide"), 79 | class = "bg-info rounded p-4" 80 | ) 81 | ), 82 | code( 83 | ' 84 | carousel( 85 | indicators = TRUE, 86 | controls = TRUE, 87 | carouselItem( 88 | h5("First"), 89 | p("First carousel slide"), 90 | class = "bg-primary rounded p-4" 91 | ), 92 | carouselItem( 93 | h5("Second"), 94 | p("Second carousel slide"), 95 | class = "bg-info rounded p-4" 96 | ) 97 | )' 98 | ), 99 | tags$a( 100 | "Should I use a carousel?", 101 | href = "https://shouldiuseacarousel.com/", 102 | target = "_blank" 103 | ) 104 | ), 105 | tabPanel( 106 | "Collapsible", 107 | fluidRow( 108 | column( 109 | 6, 110 | collapse( 111 | collapseButton( 112 | "Reveal", 113 | id = "x" 114 | ), 115 | collapseContent( 116 | "Some collapsed content" 117 | ) 118 | ) 119 | ), 120 | column( 121 | 6, 122 | code( 123 | ' 124 | collapse( 125 | collapseButton( 126 | "Reveal", 127 | id = "x" 128 | ), 129 | collapseContent( 130 | "Some collapsed content" 131 | ) 132 | )' 133 | ) 134 | ) 135 | ) 136 | ), 137 | tabPanel( 138 | "Buttons", 139 | h4("Dropdown"), 140 | fluidRow( 141 | column( 142 | 6, 143 | dropdownButton( 144 | "Buttons", 145 | actionLink("first", "First"), 146 | actionLink("second", "Second"), 147 | actionLink("third", "Third") 148 | ) 149 | ), 150 | column( 151 | 6, 152 | code( 153 | ' 154 | dropdownButton( 155 | "Buttons", 156 | actionLink("first", "First"), 157 | actionLink("second", "Second"), 158 | actionLink("third", "Third") 159 | )' 160 | ) 161 | ) 162 | ), 163 | h4("Group"), 164 | buttonGroup( 165 | actionButton("first", "First", class = "btn-primary"), 166 | actionButton("second", "Second", class = "btn-warning"), 167 | actionButton("third", "Third", class = "btn-success") 168 | ), 169 | code( 170 | ' 171 | buttonGroup( 172 | actionButton("first", "First", class = "btn-primary"), 173 | actionButton("second", "Second", class = "btn-warning"), 174 | actionButton("third", "Third", class = "btn-success") 175 | )' 176 | ) 177 | ), 178 | tabPanel( 179 | "Offcanvas", 180 | offcanvas( 181 | offcanvasButton( 182 | "Open" 183 | ), 184 | offcanvasContent( 185 | offcanvasHeader( 186 | "Off canvas" 187 | ), 188 | p( 189 | "Hello world" 190 | ), 191 | plotOutput("plot") 192 | ) 193 | ), 194 | code( 195 | ' 196 | offcanvas( 197 | offcanvasButton( 198 | "Open" 199 | ), 200 | offcanvasContent( 201 | offcanvasHeader( 202 | "Off canvas" 203 | ), 204 | p( 205 | "Hello world" 206 | ), 207 | uiOutput("text") 208 | ) 209 | )' 210 | ), 211 | tags$script( 212 | src = "https://unpkg.com/prismjs@v1.x/components/prism-core.min.js" 213 | ), 214 | tags$script( 215 | src = "https://unpkg.com/prismjs@v1.x/plugins/autoloader/prism-autoloader.min.js" 216 | ) 217 | ), 218 | tabPanel( 219 | "Progress", 220 | actionButton( 221 | "rand", 222 | "Randomise" 223 | ), 224 | progress( 225 | progressBar(15, id = "bar") 226 | ), 227 | h4("UI"), 228 | code( 229 | ' 230 | actionButton( 231 | "rand", 232 | "Randomise" 233 | ), 234 | progress( 235 | progressBar(15, id = "bar") 236 | )' 237 | ), 238 | h4("Server"), 239 | code( 240 | ' 241 | observeEvent(input$rand, { 242 | update_progress("bar", sample(10:99, 1)) 243 | })' 244 | ) 245 | ), 246 | tabPanel( 247 | "Toast", 248 | toast( 249 | "toast", 250 | toastHeader( 251 | strong( 252 | "Toast", 253 | class = "me-auto" 254 | ) 255 | ), 256 | toastBody("The body of the toast!") 257 | ), 258 | h1("Hello"), 259 | actionButton("show", "Show toast"), 260 | actionButton("hide", "Hide toast"), 261 | h4("UI"), 262 | code( 263 | ' 264 | toast( 265 | "toast", 266 | toastHeader( 267 | strong( 268 | "Toast", 269 | class = "me-auto" 270 | ) 271 | ), 272 | toastBody("The body of the toast!") 273 | )' 274 | ), 275 | h4("Server"), 276 | code( 277 | ' 278 | observeEvent(input$show, { 279 | toast_show("toast", auto_hide = FALSE) 280 | }) 281 | 282 | observeEvent(input$hide, { 283 | toast_hide("toast") 284 | })' 285 | ) 286 | ), 287 | tabPanel( 288 | "Modal", 289 | actionButton("show_modal", "Show modal"), 290 | modal( 291 | id = "modal", 292 | modalHeader( 293 | modalTitle("Title") 294 | ), 295 | modalBody( 296 | p("The content of the modal") 297 | ), 298 | modalFooter( 299 | p("The footer of the modal") 300 | ) 301 | ), 302 | h4("UI"), 303 | code( 304 | ' 305 | modal( 306 | id = "modal", 307 | modalHeader( 308 | modalTitle("Title") 309 | ), 310 | modalBody( 311 | p("The content of the modal") 312 | ), 313 | modalFooter( 314 | p("The footer of the modal") 315 | ) 316 | )' 317 | ), 318 | h4("Server"), 319 | code( 320 | ' 321 | observeEvent(input$show, { 322 | modal_show("modal") 323 | })' 324 | ) 325 | ), 326 | tabPanel( 327 | "Tooltips", 328 | fluidRow( 329 | column( 330 | 4, 331 | withTooltip( 332 | span("plain"), 333 | "content" 334 | ) 335 | ), 336 | column( 337 | 8, 338 | code( 339 | ' 340 | withTooltip( 341 | span("plain"), 342 | "content" 343 | )' 344 | ) 345 | ) 346 | ), 347 | fluidRow( 348 | column( 349 | 4, 350 | withTooltip( 351 | span("HTML"), 352 | tagList( 353 | strong("HTML"), 354 | "content" 355 | ) 356 | ) 357 | ), 358 | column( 359 | 8, 360 | code( 361 | ' 362 | withTooltip( 363 | span("HTML"), 364 | tagList( 365 | strong("HTML"), 366 | "content" 367 | ) 368 | )' 369 | ) 370 | ) 371 | ) 372 | ), 373 | tabPanel( 374 | "List", 375 | fluidRow( 376 | column( 377 | 4, 378 | listGroup( 379 | listGroupItem("Item 1"), 380 | listGroupItem("Item 2"), 381 | listGroupItem("Item 3"), 382 | listGroupItem("Item 4") 383 | ) 384 | ), 385 | column( 386 | 8, 387 | code( 388 | ' 389 | listGroup( 390 | listGroupItem("Item 1"), 391 | listGroupItem("Item 2"), 392 | listGroupItem("Item 3"), 393 | listGroupItem("Item 4") 394 | )' 395 | ) 396 | ) 397 | ) 398 | ), 399 | tabPanel( 400 | "Popover", 401 | withPopover( 402 | span("click me"), 403 | "The content", 404 | "The title" 405 | ), 406 | code( 407 | ' 408 | withPopover( 409 | span("click me"), 410 | "The content", 411 | "The title" 412 | )' 413 | ) 414 | ), 415 | tabPanel( 416 | "Inputs", 417 | fluidRow( 418 | column( 419 | 6, 420 | floatingTextInput( 421 | "text", 422 | "Text input", 423 | "placeholder text" 424 | ) 425 | ), 426 | column( 427 | 6, 428 | code( 429 | ' 430 | floatingTextInput( 431 | "text", 432 | "Text input", 433 | "placeholder text" 434 | )' 435 | ) 436 | ) 437 | ), 438 | fluidRow( 439 | column( 440 | 6, 441 | floatingTextAreaInput( 442 | "textarea", 443 | "Text input", 444 | "placeholder text", 445 | style = "height: 10rem;" 446 | ) 447 | ), 448 | column( 449 | 6, 450 | code( 451 | ' 452 | floatingTextAreaInput( 453 | "textarea", 454 | "Text input", 455 | "placeholder text", 456 | style = "height: 10rem;" 457 | )' 458 | ) 459 | ) 460 | ), 461 | fluidRow( 462 | column( 463 | 6, 464 | floatingSelectInput( 465 | "select", 466 | "Select Something", 467 | letters 468 | ) 469 | ), 470 | column( 471 | 6, 472 | code( 473 | ' 474 | floatingSelectInput( 475 | "select", 476 | "Select Something", 477 | letters 478 | )' 479 | ) 480 | ) 481 | ), 482 | fluidRow( 483 | column( 484 | 6, 485 | switchInput( 486 | "switch", 487 | "Switch input" 488 | ) 489 | ), 490 | column( 491 | 6, 492 | code( 493 | ' 494 | switchInput( 495 | "switch", 496 | "Switch input" 497 | )' 498 | ) 499 | ) 500 | ), 501 | fluidRow( 502 | column( 503 | 6, 504 | colorPickerInput( 505 | "color", 506 | value = "#000000" 507 | ) 508 | ), 509 | column( 510 | 6, 511 | code( 512 | ' 513 | colorPickerInput( 514 | "color", 515 | value = "#000000" 516 | )' 517 | ) 518 | ) 519 | ), 520 | fluidRow( 521 | column( 522 | 6, 523 | rangeInput( 524 | "range", 525 | "A range input" 526 | ) 527 | ), 528 | column( 529 | 6, 530 | code( 531 | ' 532 | rangeInput( 533 | "range", 534 | "A range input" 535 | )' 536 | ) 537 | ) 538 | ), 539 | fluidRow( 540 | column( 541 | 6, 542 | textGroupInput( 543 | "textGroup", 544 | "@", 545 | placeholder = "username" 546 | ) 547 | ), 548 | column( 549 | 6, 550 | code( 551 | ' 552 | textGroupInput( 553 | "textGroup", 554 | "@", 555 | placeholder = "username" 556 | )' 557 | ) 558 | ) 559 | ) 560 | ) 561 | ) 562 | 563 | server <- \(input, output, session) { 564 | 565 | output$plot <- renderPlot({ 566 | plot(cars) 567 | }) 568 | 569 | observeEvent(input$rand, { 570 | update_progress("bar", sample(10:99, 1)) 571 | }) 572 | 573 | observeEvent(input$show, { 574 | toast_show("toast", auto_hide = FALSE) 575 | }) 576 | 577 | observeEvent(input$hide, { 578 | toast_hide("toast") 579 | }) 580 | 581 | observeEvent(input$show_modal, { 582 | modal_show("modal") 583 | }) 584 | 585 | observeEvent(input$text, { 586 | print(input$text) 587 | }) 588 | 589 | observeEvent(input$textarea, { 590 | print(input$textarea) 591 | }) 592 | 593 | observeEvent(input$select, { 594 | print(input$select) 595 | }) 596 | 597 | observeEvent(input$switch, { 598 | print(input$switch) 599 | }) 600 | 601 | observeEvent(input$color, { 602 | print(input$color) 603 | }) 604 | 605 | observeEvent(input$range, { 606 | print(input$range) 607 | }) 608 | 609 | observeEvent(input$textGroup, { 610 | print(input$textGroup) 611 | }) 612 | } 613 | 614 | shinyApp(ui, server) 615 | -------------------------------------------------------------------------------- /inst/assets/alert.js: -------------------------------------------------------------------------------- 1 | import 'shiny'; 2 | 3 | $(function() { 4 | Shiny.addCustomMessageHandler('alert-show', (msg) => { 5 | $(`#${msg}`).show(); 6 | }); 7 | 8 | Shiny.addCustomMessageHandler('alert-hide', (msg) => { 9 | $(`#${msg}`).hide(); 10 | }); 11 | }); -------------------------------------------------------------------------------- /inst/assets/carousel.js: -------------------------------------------------------------------------------- 1 | $(() => { 2 | $("body").on("slide.bs.carousel", ".bsutils-carousel", (event) => { 3 | $(event.target).trigger("shown"); 4 | }); 5 | }); 6 | -------------------------------------------------------------------------------- /inst/assets/color.js: -------------------------------------------------------------------------------- 1 | var color = new Shiny.InputBinding(); 2 | 3 | $.extend(color, { 4 | find: function(scope) { 5 | return $(scope).find(".bsutils-color"); 6 | }, 7 | getValue: function(el) { 8 | return $(el).val(); 9 | }, 10 | setValue: function(el, value) { 11 | $(el).val(value); 12 | $(el).change(); 13 | }, 14 | receiveMessage: function(el, value){ 15 | this.setValue(el, value); 16 | }, 17 | subscribe: function (el, callback) { 18 | $(el).on("change.bsutils-color", function(){ 19 | callback(true); 20 | }) 21 | }, 22 | unsubscribe: function(el) { 23 | $(el).off(".bsutils-color"); 24 | } 25 | }); 26 | 27 | Shiny.inputBindings.register(color, 'bsutils.color'); 28 | -------------------------------------------------------------------------------- /inst/assets/modal.js: -------------------------------------------------------------------------------- 1 | Shiny.addCustomMessageHandler('bsutils-modal', (msg) => { 2 | var modal = bootstrap.Modal.getOrCreateInstance( 3 | document.getElementById(msg.id), 4 | {}, 5 | ); 6 | 7 | if(msg.action == 'show'){ 8 | modal.show(); 9 | return; 10 | } 11 | 12 | if(msg.action == 'hide'){ 13 | modal.hide(); 14 | return; 15 | } 16 | 17 | modal.toggle(); 18 | }); -------------------------------------------------------------------------------- /inst/assets/offcanvas.js: -------------------------------------------------------------------------------- 1 | Shiny.addCustomMessageHandler('bsutils-offcanvas', (msg) => { 2 | let el = document.getElementById(msg.id); 3 | let canvas = bootstrap.Offcanvas.getOrCreateInstance(el, msg.opts); 4 | 5 | if(msg.action == "show") { 6 | canvas.show(); 7 | return; 8 | } 9 | 10 | if(msg.action == "hide") { 11 | canvas.hide(); 12 | return; 13 | } 14 | 15 | canvas.toggle(); 16 | }); 17 | -------------------------------------------------------------------------------- /inst/assets/popover.js: -------------------------------------------------------------------------------- 1 | $(document).on('shiny:connected', () => { 2 | setTimeout(() => { 3 | var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]')); 4 | var popoverList = popoverTriggerList.map(function (popoverTriggerEl) { 5 | return new bootstrap.Popover(popoverTriggerEl) 6 | }); 7 | }, 250); 8 | }); -------------------------------------------------------------------------------- /inst/assets/progress.js: -------------------------------------------------------------------------------- 1 | var progress = new Shiny.InputBinding(); 2 | 3 | $.extend(progress, { 4 | find: function(scope) { 5 | return $(scope).find(".bsutils-progress"); 6 | }, 7 | getValue: function(el) { 8 | return $(el).attr("aria-valuenow"); 9 | }, 10 | setValue: function(el, value) { 11 | let max = $(el).attr("aria-valuemax"); 12 | let val = Math.ceil((value / max) * 100); 13 | $(el).css('width', `${val}%`); 14 | $(el).attr("aria-valuenow", value).change(); 15 | }, 16 | receiveMessage: function(el, value){ 17 | this.setValue(el, value); 18 | }, 19 | subscribe: function (el, callback) { 20 | $(el).on("change.bsutils-progress", function(){ 21 | callback(true); 22 | }) 23 | }, 24 | unsubscribe: function(el) { 25 | $(el).off(".bsutils-progress"); 26 | } 27 | }); 28 | 29 | Shiny.inputBindings.register(progress, 'bsutils.progress'); 30 | -------------------------------------------------------------------------------- /inst/assets/range.js: -------------------------------------------------------------------------------- 1 | var range = new Shiny.InputBinding(); 2 | 3 | $.extend(range, { 4 | find: function(scope) { 5 | return $(scope).find(".bsutils-range"); 6 | }, 7 | getValue: function(el) { 8 | return parseInt($(el).val()); 9 | }, 10 | setValue: function(el, value) { 11 | $(el).val(value); 12 | $(el).change(); 13 | }, 14 | receiveMessage: function(el, msg){ 15 | if(msg.value) 16 | this.setValue(el, msg.value); 17 | 18 | if(msg.min) 19 | $(el).attr('min', msg.min); 20 | 21 | if(msg.max) 22 | $(el).attr('max', msg.max); 23 | }, 24 | subscribe: function (el, callback) { 25 | $(el).on("change.bsutils-range", function(){ 26 | callback(true); 27 | }) 28 | }, 29 | unsubscribe: function(el) { 30 | $(el).off(".bsutils-range"); 31 | } 32 | }); 33 | 34 | Shiny.inputBindings.register(range, 'bsutils.range'); 35 | 36 | -------------------------------------------------------------------------------- /inst/assets/text-group.js: -------------------------------------------------------------------------------- 1 | var textGroup = new Shiny.InputBinding(); 2 | 3 | $.extend(textGroup, { 4 | find: function(scope) { 5 | return $(scope).find(".bsutils-text-group"); 6 | }, 7 | getValue: function(el) { 8 | return $(el).val(); 9 | }, 10 | setValue: function(el, value) { 11 | $(el).val(value); 12 | }, 13 | receiveMessage: function(el, msg){ 14 | if(msg.value) 15 | this.setValue(el, msg.value); 16 | 17 | if(msg.label) 18 | $(el).siblings('span').text(msg.label); 19 | }, 20 | subscribe: function (el, callback) { 21 | $(el).on("keyup.bsutils-text-group input.bsutils-text-group", function(){ 22 | callback(true); 23 | }); 24 | 25 | $(el).on("change.bsutils-text-group", function(){ 26 | callback(false); 27 | }); 28 | }, 29 | unsubscribe: function(el) { 30 | $(el).off(".bsutils-text-group"); 31 | }, 32 | getRatePolicy: function(){ 33 | return { 34 | policy: 'debounce', 35 | delay: 250 36 | } 37 | } 38 | }); 39 | 40 | Shiny.inputBindings.register(textGroup, 'bsutils.bsutils-text-group'); 41 | 42 | 43 | -------------------------------------------------------------------------------- /inst/assets/toast.js: -------------------------------------------------------------------------------- 1 | Shiny.addCustomMessageHandler("bsutils-toast", (msg) => { 2 | let el = document.getElementById(msg.id); 3 | let toast = bootstrap.Toast.getOrCreateInstance(el, msg.opts); 4 | 5 | if (msg.body) { 6 | $(el).find(".toast-body").html(msg.body); 7 | } 8 | 9 | if (msg.header) { 10 | $(el).find(".toast-header").html(msg.header); 11 | } 12 | 13 | if (msg.action == "show") { 14 | toast.show(); 15 | return; 16 | } 17 | 18 | toast.hide(); 19 | }); 20 | -------------------------------------------------------------------------------- /inst/assets/tooltip.js: -------------------------------------------------------------------------------- 1 | setTimeout(() => { 2 | var tooltipTriggerList = [].slice.call( 3 | document.querySelectorAll('[data-bs-toggle="tooltip"]'), 4 | ); 5 | var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) { 6 | return new bootstrap.Tooltip(tooltipTriggerEl); 7 | }); 8 | }, 150); 9 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | install: check 2 | Rscript -e "devtools::install()" 3 | 4 | check: document 5 | Rscript -e "devtools::check()" 6 | 7 | document: 8 | Rscript -e "devtools::document()" 9 | 10 | test: 11 | Rscript -e "devtools::test()" 12 | 13 | run: 14 | Rscript test.R 15 | -------------------------------------------------------------------------------- /man/accordion.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/accordion.R 3 | \name{accordion} 4 | \alias{accordion} 5 | \title{Accordion} 6 | \usage{ 7 | accordion(..., .id = NULL, .flush = FALSE) 8 | } 9 | \arguments{ 10 | \item{...}{Any number of \code{\link[=accordionItem]{accordionItem()}}.} 11 | 12 | \item{.id}{Id of accordion.} 13 | 14 | \item{.flush}{remove default background color, some 15 | borders, some rounded corners.} 16 | } 17 | \description{ 18 | Collapsible accordion made up of \code{\link[=accordionItem]{accordionItem()}}. 19 | } 20 | \examples{ 21 | library(shiny) 22 | 23 | ui <- fluidPage( 24 | theme = bslib::bs_theme(version = 5L), 25 | accordion( 26 | accordionItem( 27 | .expanded = TRUE, 28 | "Something", 29 | p("Some content") 30 | ), 31 | accordionItem( 32 | "Something else", 33 | p("Some other content") 34 | ) 35 | ) 36 | ) 37 | 38 | server <- \(input, output, session){ 39 | 40 | } 41 | 42 | if(interactive()) 43 | shinyApp(ui, server) 44 | 45 | } 46 | -------------------------------------------------------------------------------- /man/accordionItem.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/accordion.R 3 | \name{accordionItem} 4 | \alias{accordionItem} 5 | \title{AccordionItem} 6 | \usage{ 7 | accordionItem( 8 | label, 9 | ..., 10 | .id = NULL, 11 | .expanded = FALSE, 12 | .label_tag = shiny::h2 13 | ) 14 | } 15 | \arguments{ 16 | \item{label}{Label of the item.} 17 | 18 | \item{...}{Elements to place in the body of the item.} 19 | 20 | \item{.id}{Id of item.} 21 | 22 | \item{.expanded}{Whether the element is initially expanded.} 23 | 24 | \item{.label_tag}{Tag to use for the label.} 25 | } 26 | \description{ 27 | Accordion item to place within \code{\link[=accordion]{accordion()}}. 28 | } 29 | -------------------------------------------------------------------------------- /man/alert.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/alerts.R 3 | \name{alert} 4 | \alias{alert} 5 | \title{Alert} 6 | \usage{ 7 | alert(..., id = NULL, class = "") 8 | } 9 | \arguments{ 10 | \item{...}{Content of alert.} 11 | 12 | \item{id}{ID of alert useful to toggle from server with 13 | \code{\link[=alert_show]{alert_show()}} or \code{\link[=alert_hide]{alert_hide()}}.} 14 | 15 | \item{class}{Additional classes, e.g.: \code{alert-success}.} 16 | } 17 | \description{ 18 | Alert 19 | } 20 | \examples{ 21 | alert( 22 | alertHeading("Header!"), 23 | shiny::p("Some content") 24 | ) 25 | 26 | } 27 | -------------------------------------------------------------------------------- /man/alertHeading.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/alerts.R 3 | \name{alertHeading} 4 | \alias{alertHeading} 5 | \title{Alert Heading} 6 | \usage{ 7 | alertHeading(heading) 8 | } 9 | \arguments{ 10 | \item{heading}{A character string or an HTML tag.} 11 | } 12 | \description{ 13 | Alert heading to be placed in \code{\link[=alert]{alert()}}. 14 | } 15 | -------------------------------------------------------------------------------- /man/alertServer.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/alerts.R 3 | \name{alertServer} 4 | \alias{alertServer} 5 | \alias{alert_show} 6 | \alias{alert_hide} 7 | \title{Toggle Alert} 8 | \usage{ 9 | alert_show(id, session = shiny::getDefaultReactiveDomain()) 10 | 11 | alert_hide(id, session = shiny::getDefaultReactiveDomain()) 12 | } 13 | \arguments{ 14 | \item{id}{ID of \code{\link[=alert]{alert()}} to toggle.} 15 | 16 | \item{session}{A valid shiny session.} 17 | } 18 | \description{ 19 | Show or hide an alert. 20 | } 21 | -------------------------------------------------------------------------------- /man/asPlaceholder.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/placeholders.R 3 | \name{asPlaceholder} 4 | \alias{asPlaceholder} 5 | \title{As Placeholder} 6 | \usage{ 7 | asPlaceholder(el, glow = FALSE) 8 | } 9 | \arguments{ 10 | \item{el}{Element to turn into a placeholder.} 11 | 12 | \item{glow}{Whether the elements should glow.} 13 | } 14 | \description{ 15 | Turn an element into a placeholder. 16 | } 17 | \examples{ 18 | shiny::p() |> 19 | asPlaceholder() 20 | 21 | shiny::actionButton("id", "") |> 22 | asPlaceholder() 23 | 24 | } 25 | -------------------------------------------------------------------------------- /man/badge.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/badge.R 3 | \name{badge} 4 | \alias{badge} 5 | \title{Badge} 6 | \usage{ 7 | badge( 8 | ..., 9 | color = c("primary", "secondary", "success", "danger", "warning", "info", "light", 10 | "dark"), 11 | pill = FALSE, 12 | class = "" 13 | ) 14 | } 15 | \arguments{ 16 | \item{...}{Content of the badge.} 17 | 18 | \item{color}{Background color of the badge.} 19 | 20 | \item{pill}{Whether to create a rounded badge.} 21 | 22 | \item{class}{Additional classes to passs to the badge.} 23 | } 24 | \description{ 25 | Badge. 26 | } 27 | -------------------------------------------------------------------------------- /man/buttonGroup.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/group.R 3 | \name{buttonGroup} 4 | \alias{buttonGroup} 5 | \title{Button Group} 6 | \usage{ 7 | buttonGroup(..., class = "") 8 | } 9 | \arguments{ 10 | \item{...}{Any \code{\link[shiny:actionButton]{shiny::actionButton()}}.} 11 | 12 | \item{class}{Any additional class.} 13 | } 14 | \description{ 15 | Group of buttons. 16 | } 17 | \examples{ 18 | library(shiny) 19 | 20 | ui <- fluidPage( 21 | theme = bslib::bs_theme(version = 5L), 22 | buttonGroup( 23 | actionButton("first", "First", class = "btn-primary"), 24 | actionButton("second", "Second", class = "btn-warning"), 25 | actionButton("third", "Third", class = "btn-success") 26 | ) 27 | ) 28 | 29 | server <- \(input, output, session){ 30 | 31 | } 32 | 33 | if(interactive()) 34 | shinyApp(ui, server) 35 | 36 | } 37 | -------------------------------------------------------------------------------- /man/card.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/card.R 3 | \name{card} 4 | \alias{card} 5 | \title{Card} 6 | \usage{ 7 | card(...) 8 | } 9 | \arguments{ 10 | \item{...}{Content, generally \code{\link[=cardBody]{cardBody()}}.} 11 | } 12 | \description{ 13 | Card. 14 | } 15 | \examples{ 16 | card( 17 | cardHeader("Header"), 18 | cardBody( 19 | cardTitle("Title"), 20 | cardSubtitle("Subtitle"), 21 | cardText("The content of the card") 22 | ) 23 | ) 24 | 25 | } 26 | -------------------------------------------------------------------------------- /man/cardBody.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/card.R 3 | \name{cardBody} 4 | \alias{cardBody} 5 | \title{Card Body} 6 | \usage{ 7 | cardBody(...) 8 | } 9 | \arguments{ 10 | \item{...}{Content, HTML tags, \code{\link[=cardText]{cardText()}}, \code{\link[=cardTitle]{cardTitle()}}, 11 | or \code{\link[=cardSubtitle]{cardSubtitle()}}.} 12 | } 13 | \description{ 14 | Card body to be placed within \code{\link[=card]{card()}}. 15 | } 16 | -------------------------------------------------------------------------------- /man/cardHeader.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/card.R 3 | \name{cardHeader} 4 | \alias{cardHeader} 5 | \title{Card Header} 6 | \usage{ 7 | cardHeader(content) 8 | } 9 | \arguments{ 10 | \item{content}{Content of the title or subtitle, either 11 | a character vector or an HTML header tag.} 12 | } 13 | \description{ 14 | Card header placed within \code{\link[=card]{card()}} before \code{\link[=cardBody]{cardBody()}}. 15 | } 16 | -------------------------------------------------------------------------------- /man/cardText.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/card.R 3 | \name{cardText} 4 | \alias{cardText} 5 | \title{Card Text} 6 | \usage{ 7 | cardText(...) 8 | } 9 | \arguments{ 10 | \item{...}{Content of the text.} 11 | } 12 | \description{ 13 | Card text to be placed in \code{\link[=cardBody]{cardBody()}}. 14 | } 15 | -------------------------------------------------------------------------------- /man/cardTitle.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/card.R 3 | \name{cardTitle} 4 | \alias{cardTitle} 5 | \alias{cardSubtitle} 6 | \title{Card Title & Subtitle} 7 | \usage{ 8 | cardTitle(content) 9 | 10 | cardSubtitle(content) 11 | } 12 | \arguments{ 13 | \item{content}{Content of the title or subtitle, either 14 | a character vector or an HTML header tag.} 15 | } 16 | \description{ 17 | Card title and subtitle to be placed within \code{\link[=cardBody]{cardBody()}}. 18 | } 19 | -------------------------------------------------------------------------------- /man/carousel.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/carousel.R 3 | \name{carousel} 4 | \alias{carousel} 5 | \title{Carousel} 6 | \usage{ 7 | carousel(..., id = NULL, class = "", controls = FALSE, indicators = FALSE) 8 | } 9 | \arguments{ 10 | \item{...}{Slides of the carousel, see \code{\link[=carouselItem]{carouselItem()}}.} 11 | 12 | \item{id}{ID of carousel.} 13 | 14 | \item{class}{Additional class of the carousel.} 15 | 16 | \item{controls}{Whether to show control arrows.} 17 | 18 | \item{indicators}{Whether to show indicators.} 19 | } 20 | \description{ 21 | Carousel element. 22 | } 23 | \examples{ 24 | library(shiny) 25 | 26 | ui <- fluidPage( 27 | theme = bslib::bs_theme(version = 5L), 28 | carousel( 29 | indicators = TRUE, 30 | controls = TRUE, 31 | carouselItem( 32 | h5("Hello"), 33 | class = "bg-primary rounded p-4" 34 | ), 35 | carouselItem( 36 | h5("World"), 37 | class = "bg-info rounded p-4" 38 | ) 39 | ) 40 | ) 41 | 42 | server <- \(input, output, session){ 43 | } 44 | 45 | if(interactive()) 46 | shinyApp(ui, server) 47 | 48 | } 49 | -------------------------------------------------------------------------------- /man/carouselControls.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/carousel.R 3 | \name{carouselControls} 4 | \alias{carouselControls} 5 | \title{Carousel Controls} 6 | \usage{ 7 | carouselControls(show, id) 8 | } 9 | \arguments{ 10 | \item{show}{Whether to show the control arrows.} 11 | 12 | \item{id}{ID of parent \code{\link[=carousel]{carousel()}}.} 13 | } 14 | \description{ 15 | Carousel control arrows. 16 | } 17 | \keyword{internal} 18 | -------------------------------------------------------------------------------- /man/carouselImg.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/carousel.R 3 | \name{carouselImg} 4 | \alias{carouselImg} 5 | \title{Carousel Image} 6 | \usage{ 7 | carouselImg(..., class = "") 8 | } 9 | \arguments{ 10 | \item{...}{Passed to \verb{}.} 11 | 12 | \item{class}{Additional classes.} 13 | } 14 | \description{ 15 | Carousel image to use within \code{\link[=carouselItem]{carouselItem()}}. 16 | } 17 | -------------------------------------------------------------------------------- /man/carouselIndicators.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/carousel.R 3 | \name{carouselIndicators} 4 | \alias{carouselIndicators} 5 | \title{Carousel Indicators} 6 | \usage{ 7 | carouselIndicators(items, id, show) 8 | } 9 | \arguments{ 10 | \item{items}{list of \code{\link[=carouselItem]{carouselItem()}}.} 11 | 12 | \item{id}{Parent if of \code{\link[=carousel]{carousel()}}.} 13 | 14 | \item{show}{Whether to show the indicators.} 15 | } 16 | \description{ 17 | Carousel indicators 18 | } 19 | \keyword{internal} 20 | -------------------------------------------------------------------------------- /man/carouselItem.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/carousel.R 3 | \name{carouselItem} 4 | \alias{carouselItem} 5 | \title{Carousel Item} 6 | \usage{ 7 | carouselItem(..., interval = NULL, class = "") 8 | } 9 | \arguments{ 10 | \item{...}{Content of item.} 11 | 12 | \item{interval}{Number of milliseconds this item should be shown.} 13 | 14 | \item{class}{Additional classes.} 15 | } 16 | \description{ 17 | Carousel item to use within \code{\link[=carousel]{carousel()}}. 18 | } 19 | -------------------------------------------------------------------------------- /man/closeButton.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/close.R 3 | \name{closeButton} 4 | \alias{closeButton} 5 | \title{Close Button} 6 | \usage{ 7 | closeButton() 8 | } 9 | \description{ 10 | Button to dismiss or close a component. 11 | } 12 | -------------------------------------------------------------------------------- /man/collapse.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/collapse.R 3 | \name{collapse} 4 | \alias{collapse} 5 | \alias{collapse.collapseTrigger} 6 | \title{Collapse} 7 | \usage{ 8 | collapse(trigger, content) 9 | 10 | \method{collapse}{collapseTrigger}(trigger, content) 11 | } 12 | \arguments{ 13 | \item{trigger}{A \code{\link[=collapseButton]{collapseButton()}} or \code{\link[=collapseLink]{collapseLink()}}.} 14 | 15 | \item{content}{The offcanvas content as returned by 16 | \code{\link[=offcanvasContent]{offcanvasContent()}}.} 17 | } 18 | \description{ 19 | Create a collapsible. 20 | } 21 | \section{Methods (by class)}{ 22 | \itemize{ 23 | \item \code{collapse(collapseTrigger)}: Collapse wrapper 24 | 25 | }} 26 | \examples{ 27 | library(shiny) 28 | 29 | ui <- fluidPage( 30 | theme = bslib::bs_theme(version = 5L), 31 | collapse( 32 | collapseLink( 33 | "Reveal" 34 | ), 35 | collapseContent( 36 | "Some collapsed content" 37 | ) 38 | ) 39 | ) 40 | 41 | server <- \(input, output, session){ 42 | 43 | } 44 | 45 | if(interactive()) 46 | shinyApp(ui, server) 47 | 48 | } 49 | -------------------------------------------------------------------------------- /man/collapseButton.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/collapse.R 3 | \name{collapseButton} 4 | \alias{collapseButton} 5 | \title{Collapse Button} 6 | \usage{ 7 | collapseButton(..., id = NULL, class = "") 8 | } 9 | \arguments{ 10 | \item{...}{Passed to the button.} 11 | 12 | \item{id}{Button id.} 13 | 14 | \item{class}{Additional classes to pass to the button.} 15 | } 16 | \description{ 17 | Collapse button. 18 | } 19 | \examples{ 20 | library(shiny) 21 | 22 | ui <- fluidPage( 23 | theme = bslib::bs_theme(version = 5L), 24 | collapse( 25 | collapseButton( 26 | "Reveal" 27 | ), 28 | collapseContent( 29 | "Some collapsed content" 30 | ) 31 | ) 32 | ) 33 | 34 | server <- \(input, output, session){ 35 | 36 | } 37 | 38 | if(interactive()) 39 | shinyApp(ui, server) 40 | 41 | } 42 | -------------------------------------------------------------------------------- /man/collapseContent.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/collapse.R 3 | \name{collapseContent} 4 | \alias{collapseContent} 5 | \title{Collapse Content} 6 | \usage{ 7 | collapseContent(..., .id = NULL) 8 | } 9 | \arguments{ 10 | \item{...}{Content of the collapsible.} 11 | 12 | \item{.id}{Id of the element.} 13 | } 14 | \description{ 15 | Collapse content, to pass to \code{\link[=collapseButton]{collapseButton()}} or 16 | \code{\link[=collapseLink]{collapseLink()}}. 17 | } 18 | -------------------------------------------------------------------------------- /man/collapseLink.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/collapse.R 3 | \name{collapseLink} 4 | \alias{collapseLink} 5 | \title{Collapse Link} 6 | \usage{ 7 | collapseLink(..., id = NULL, class = "") 8 | } 9 | \arguments{ 10 | \item{...}{Passed to the link.} 11 | 12 | \item{id}{Link id.} 13 | 14 | \item{class}{Additional class to pass to the link.} 15 | } 16 | \description{ 17 | Collapse link. 18 | } 19 | -------------------------------------------------------------------------------- /man/colorPickerInput.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/inputs.R 3 | \name{colorPickerInput} 4 | \alias{colorPickerInput} 5 | \title{Color Picker Input} 6 | \usage{ 7 | colorPickerInput(inputId, value = NULL, ...) 8 | } 9 | \arguments{ 10 | \item{inputId}{ID of input.} 11 | 12 | \item{value}{Initial value of the input.} 13 | 14 | \item{...}{Passed to input.} 15 | } 16 | \description{ 17 | Color picker input. 18 | } 19 | -------------------------------------------------------------------------------- /man/dropdownButton.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/dropdown.R 3 | \name{dropdownButton} 4 | \alias{dropdownButton} 5 | \title{Dropdown Button} 6 | \usage{ 7 | dropdownButton(label, ..., id = NULL, class = "") 8 | } 9 | \arguments{ 10 | \item{label}{Label of the dropdown.} 11 | 12 | \item{...}{\code{\link[shiny:actionButton]{shiny::actionLink()}} to place within the 13 | dropdown.} 14 | 15 | \item{id}{ID of parent dropdown.} 16 | 17 | \item{class}{Additional class for dropdown button.} 18 | } 19 | \description{ 20 | Dropdown buttons for \code{\link[shiny:actionButton]{shiny::actionLink()}}. 21 | } 22 | \examples{ 23 | library(shiny) 24 | 25 | ui <- fluidPage( 26 | theme = bslib::bs_theme(version = 5L), 27 | dropdownButton( 28 | "Buttons", 29 | actionLink("first", "First"), 30 | actionLink("second", "Second") 31 | ) 32 | ) 33 | 34 | server <- \(input, output, session){ 35 | 36 | } 37 | 38 | if(interactive()) 39 | shinyApp(ui, server) 40 | 41 | } 42 | -------------------------------------------------------------------------------- /man/floatingSelectInput.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/inputs.R 3 | \name{floatingSelectInput} 4 | \alias{floatingSelectInput} 5 | \title{Select Floating Label} 6 | \usage{ 7 | floatingSelectInput(inputId, label, choices = NULL, ...) 8 | } 9 | \arguments{ 10 | \item{inputId}{ID of input.} 11 | 12 | \item{label}{Label of input.} 13 | 14 | \item{choices}{Choices, named vector.} 15 | 16 | \item{...}{Passed to input.} 17 | } 18 | \description{ 19 | Select input with floating label. 20 | } 21 | -------------------------------------------------------------------------------- /man/floatingTextAreaInput.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/inputs.R 3 | \name{floatingTextAreaInput} 4 | \alias{floatingTextAreaInput} 5 | \title{Text Area Input Floating Label} 6 | \usage{ 7 | floatingTextAreaInput(inputId, label, placeholder, value = "", ...) 8 | } 9 | \arguments{ 10 | \item{inputId}{ID of input.} 11 | 12 | \item{label}{Label of input.} 13 | 14 | \item{placeholder}{Placeholder value.} 15 | 16 | \item{value}{Value of input.} 17 | 18 | \item{...}{Passed to input.} 19 | } 20 | \description{ 21 | Text area input with floating label. 22 | } 23 | -------------------------------------------------------------------------------- /man/floatingTextInput.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/inputs.R 3 | \name{floatingTextInput} 4 | \alias{floatingTextInput} 5 | \title{Text Input Floating Label} 6 | \usage{ 7 | floatingTextInput(inputId, label, placeholder, value = "", ...) 8 | } 9 | \arguments{ 10 | \item{inputId}{ID of input.} 11 | 12 | \item{label}{Label of input.} 13 | 14 | \item{placeholder}{Placeholder value.} 15 | 16 | \item{value}{Value of input.} 17 | 18 | \item{...}{Passed to input.} 19 | } 20 | \description{ 21 | Text input with floating label. 22 | } 23 | -------------------------------------------------------------------------------- /man/gallery.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/gallery.R 3 | \name{gallery} 4 | \alias{gallery} 5 | \title{Gallery} 6 | \usage{ 7 | gallery() 8 | } 9 | \description{ 10 | Demo of utilities. 11 | } 12 | -------------------------------------------------------------------------------- /man/get_dep.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/dependencies.R 3 | \name{get_dep} 4 | \alias{get_dep} 5 | \title{Get Dependencies} 6 | \usage{ 7 | get_dep(name) 8 | } 9 | \arguments{ 10 | \item{name}{Name of dependency.} 11 | } 12 | \description{ 13 | Get a dependency. 14 | } 15 | \keyword{internal} 16 | -------------------------------------------------------------------------------- /man/listGroup.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/list.R 3 | \name{listGroup} 4 | \alias{listGroup} 5 | \title{List Group} 6 | \usage{ 7 | listGroup(...) 8 | } 9 | \arguments{ 10 | \item{...}{Content of the list group, see \code{\link[=listGroupItem]{listGroupItem()}}.} 11 | } 12 | \description{ 13 | List group, see \code{\link[=listGroupItem]{listGroupItem()}}. 14 | } 15 | -------------------------------------------------------------------------------- /man/listGroupItem.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/list.R 3 | \name{listGroupItem} 4 | \alias{listGroupItem} 5 | \title{List Group Item} 6 | \usage{ 7 | listGroupItem(..., class = "") 8 | } 9 | \arguments{ 10 | \item{...}{Content.} 11 | 12 | \item{class}{Additional classes.} 13 | } 14 | \description{ 15 | Items for \code{\link[=listGroup]{listGroup()}}. 16 | } 17 | -------------------------------------------------------------------------------- /man/modal.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/modal.R 3 | \name{modal} 4 | \alias{modal} 5 | \title{Modal} 6 | \usage{ 7 | modal( 8 | id, 9 | ..., 10 | static_backdrop = FALSE, 11 | scrollable = FALSE, 12 | centered = FALSE, 13 | size = c("default", "sm", "lg", "xl", "fullscreen", "fullscreen-sm-down", 14 | "fullscreen-md-down", "fullscreen-lg-down", "fullscreen-xl-down", 15 | "fullscreen-xxl-down") 16 | ) 17 | } 18 | \arguments{ 19 | \item{id}{ID of modal.} 20 | 21 | \item{...}{Content of the modal, \code{\link[=modalBody]{modalBody()}}, 22 | \code{\link[=modalHeader]{modalHeader()}}, \code{\link[=modalFooter]{modalFooter()}}.} 23 | 24 | \item{static_backdrop}{When backdrop is set to static, 25 | the modal will not close when clicking outside it.} 26 | 27 | \item{scrollable}{Whether to make the content scrollable.} 28 | 29 | \item{centered}{Whether to make the content vertically 30 | centered.} 31 | 32 | \item{size}{Size of the modal.} 33 | } 34 | \description{ 35 | Create a modal in the UI. 36 | The modal is not down see \code{\link[=modal_show]{modal_show()}}, or 37 | \code{\link[=modal_toggle]{modal_toggle()}} (from server). 38 | } 39 | \examples{ 40 | library(shiny) 41 | 42 | ui <- fluidPage( 43 | theme = bslib::bs_theme(version = 5L), 44 | actionButton("show", "Show modal"), 45 | modal( 46 | id = "modal", 47 | modalHeader( 48 | modalTitle("Title") 49 | ), 50 | modalBody( 51 | p("The content of the modal") 52 | ), 53 | modalFooter( 54 | p("The footer of the modal") 55 | ) 56 | ) 57 | ) 58 | 59 | server <- \(input, output, session){ 60 | observeEvent(input$show, { 61 | modal_show("modal") 62 | }) 63 | } 64 | 65 | if(interactive()) 66 | shinyApp(ui, server) 67 | 68 | } 69 | -------------------------------------------------------------------------------- /man/modalBody.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/modal.R 3 | \name{modalBody} 4 | \alias{modalBody} 5 | \title{Modal Body} 6 | \usage{ 7 | modalBody(...) 8 | } 9 | \arguments{ 10 | \item{...}{Content of the body.} 11 | } 12 | \description{ 13 | Body of the modal, place within \code{\link[=modal]{modal()}}. 14 | } 15 | -------------------------------------------------------------------------------- /man/modalFooter.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/modal.R 3 | \name{modalFooter} 4 | \alias{modalFooter} 5 | \title{Modal Footer} 6 | \usage{ 7 | modalFooter(...) 8 | } 9 | \arguments{ 10 | \item{...}{Content of the footer.} 11 | } 12 | \description{ 13 | Footer of the modal, place within \code{\link[=modal]{modal()}}. 14 | } 15 | -------------------------------------------------------------------------------- /man/modalHeader.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/modal.R 3 | \name{modalHeader} 4 | \alias{modalHeader} 5 | \title{Modal Header} 6 | \usage{ 7 | modalHeader(..., .close = TRUE) 8 | } 9 | \arguments{ 10 | \item{...}{Content.} 11 | 12 | \item{.close}{Whether to add the close button.} 13 | } 14 | \description{ 15 | Header of a modal, place within \code{\link[=modal]{modal()}}. 16 | } 17 | -------------------------------------------------------------------------------- /man/modalTitle.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/modal.R 3 | \name{modalTitle} 4 | \alias{modalTitle} 5 | \title{Modal Title} 6 | \usage{ 7 | modalTitle(title) 8 | } 9 | \arguments{ 10 | \item{title}{An HTML tag or a character vector of length 1.} 11 | } 12 | \description{ 13 | Modal title, place within \code{\link[=modalHeader]{modalHeader()}}. 14 | } 15 | -------------------------------------------------------------------------------- /man/modalToggle.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/modal.R 3 | \name{modalToggle} 4 | \alias{modalToggle} 5 | \alias{modal_show} 6 | \alias{modal_hide} 7 | \alias{modal_toggle} 8 | \title{Modal Toggle} 9 | \usage{ 10 | modal_show(id, session = shiny::getDefaultReactiveDomain()) 11 | 12 | modal_hide(id, session = shiny::getDefaultReactiveDomain()) 13 | 14 | modal_toggle(id, session = shiny::getDefaultReactiveDomain()) 15 | } 16 | \arguments{ 17 | \item{id}{ID of the \code{\link[=modal]{modal()}}.} 18 | 19 | \item{session}{A valid shiny session.} 20 | } 21 | \description{ 22 | Show, hide, or toggle a modal from the server. 23 | } 24 | -------------------------------------------------------------------------------- /man/modalTrigger.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/modal.R 3 | \name{modalTrigger} 4 | \alias{modalTrigger} 5 | \alias{modalButton} 6 | \alias{modalLink} 7 | \title{Modal Triggers} 8 | \usage{ 9 | modalButton(target, ..., class = "") 10 | 11 | modalLink(target, ...) 12 | } 13 | \arguments{ 14 | \item{target}{Target ID of the \code{\link[=modal]{modal()}} to show.} 15 | 16 | \item{...}{Content of link or button, generally a 17 | character vector of length 1.} 18 | 19 | \item{class}{Additional class to pass to the button.} 20 | } 21 | \description{ 22 | Trigger open a modal with a button or a link, 23 | avoids goind through the server. 24 | } 25 | -------------------------------------------------------------------------------- /man/offcanvas.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/offcanvas.R 3 | \name{offcanvas} 4 | \alias{offcanvas} 5 | \alias{offcanvas.offcanvasTrigger} 6 | \alias{offcanvas.shiny.tag} 7 | \title{Offcanvas} 8 | \usage{ 9 | offcanvas(trigger, content) 10 | 11 | \method{offcanvas}{offcanvasTrigger}(trigger, content) 12 | 13 | \method{offcanvas}{shiny.tag}(trigger, content) 14 | } 15 | \arguments{ 16 | \item{trigger}{A \code{\link[=collapseButton]{collapseButton()}}, \code{\link[=collapseLink]{collapseLink()}}, 17 | \code{\link[shiny:actionButton]{shiny::actionButton()}}, \code{\link[shiny:actionButton]{shiny::actionLink()}}.} 18 | 19 | \item{content}{The offcanvas content as returned by 20 | \code{\link[=offcanvasContent]{offcanvasContent()}}.} 21 | } 22 | \description{ 23 | Create an offcanvas element. 24 | } 25 | \section{Methods (by class)}{ 26 | \itemize{ 27 | \item \code{offcanvas(offcanvasTrigger)}: Offcanvas wrapper for \code{\link[=collapseButton]{collapseButton()}}, \code{\link[=collapseLink]{collapseLink()}}. 28 | 29 | \item \code{offcanvas(shiny.tag)}: Offcanvas wrapper for \code{\link[shiny:actionButton]{shiny::actionButton()}}, \code{\link[shiny:actionButton]{shiny::actionLink()}}. 30 | 31 | }} 32 | \examples{ 33 | library(shiny) 34 | 35 | ui <- fluidPage( 36 | theme = bslib::bs_theme(version = 5L), 37 | offcanvas( 38 | offcanvasButton( 39 | "Open" 40 | ), 41 | offcanvasContent( 42 | offcanvasHeader( 43 | "Off canvas" 44 | ), 45 | p( 46 | "Hello world" 47 | ) 48 | ) 49 | ) 50 | ) 51 | 52 | server <- \(input, output, session){ 53 | 54 | } 55 | 56 | if(interactive()) 57 | shinyApp(ui, server) 58 | 59 | } 60 | -------------------------------------------------------------------------------- /man/offcanvasButton.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/offcanvas.R 3 | \name{offcanvasButton} 4 | \alias{offcanvasButton} 5 | \alias{offcanvasButtonWithTooltip} 6 | \title{Offcanvas Button} 7 | \usage{ 8 | offcanvasButton(..., id = NULL, class = "") 9 | 10 | offcanvasButtonWithTooltip( 11 | ..., 12 | title, 13 | placement = c("top", "right", "bottom", "left"), 14 | id = NULL, 15 | class = "" 16 | ) 17 | } 18 | \arguments{ 19 | \item{...}{Passed to the button.} 20 | 21 | \item{id}{ID of the button.} 22 | 23 | \item{class}{Additional class to pass to the button.} 24 | 25 | \item{title}{HTML tag or character vector of length 1.} 26 | 27 | \item{placement}{Placement of the tooltip.} 28 | } 29 | \description{ 30 | Offcanvas button trigger. 31 | } 32 | -------------------------------------------------------------------------------- /man/offcanvasContent.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/offcanvas.R 3 | \name{offcanvasContent} 4 | \alias{offcanvasContent} 5 | \title{Offcanvas Content} 6 | \usage{ 7 | offcanvasContent( 8 | ..., 9 | id = NULL, 10 | class = "", 11 | .position = c("start", "end", "top", "bottom"), 12 | scroll = TRUE 13 | ) 14 | } 15 | \arguments{ 16 | \item{...}{Content of the offcanvas.} 17 | 18 | \item{id}{Id of the canvas.} 19 | 20 | \item{class}{Additional classes.} 21 | 22 | \item{.position}{Where the canvas should open.} 23 | 24 | \item{scroll}{Whether to allow scrolling the body.} 25 | } 26 | \description{ 27 | Offcanvas content. 28 | } 29 | -------------------------------------------------------------------------------- /man/offcanvasHeader.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/offcanvas.R 3 | \name{offcanvasHeader} 4 | \alias{offcanvasHeader} 5 | \title{Canvas Header} 6 | \usage{ 7 | offcanvasHeader(header) 8 | } 9 | \arguments{ 10 | \item{header}{An HTML tag or a character string.} 11 | } 12 | \description{ 13 | Header for \code{\link[=offcanvasContent]{offcanvasContent()}}. 14 | } 15 | -------------------------------------------------------------------------------- /man/offcanvasLink.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/offcanvas.R 3 | \name{offcanvasLink} 4 | \alias{offcanvasLink} 5 | \title{Offcanvas Link} 6 | \usage{ 7 | offcanvasLink(..., id = NULL, class = "") 8 | } 9 | \arguments{ 10 | \item{...}{Passed to the button.} 11 | 12 | \item{id}{ID of the link.} 13 | 14 | \item{class}{Additional class to pass to the button.} 15 | } 16 | \description{ 17 | Offcanvas link trigger. 18 | } 19 | -------------------------------------------------------------------------------- /man/offcanvasServer.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/offcanvas.R 3 | \name{offcanvasServer} 4 | \alias{offcanvasServer} 5 | \alias{offcanvas_show} 6 | \alias{offcanvas_hide} 7 | \alias{offcanvas_toggle} 8 | \title{Offcanvas Server} 9 | \usage{ 10 | offcanvas_show(id, session = shiny::getDefaultReactiveDomain()) 11 | 12 | offcanvas_hide(id, session = shiny::getDefaultReactiveDomain()) 13 | 14 | offcanvas_toggle(id, session = shiny::getDefaultReactiveDomain()) 15 | } 16 | \arguments{ 17 | \item{id}{ID of \code{\link[=offcanvasContent]{offcanvasContent()}}.} 18 | 19 | \item{session}{Valid shiny session.} 20 | } 21 | \description{ 22 | Toggle the offcanvas from the server. 23 | } 24 | -------------------------------------------------------------------------------- /man/progress.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/progress.R 3 | \name{progress} 4 | \alias{progress} 5 | \title{Progress} 6 | \usage{ 7 | progress(..., id = NULL) 8 | } 9 | \arguments{ 10 | \item{...}{Progress bars as returned by \code{\link[=progressBar]{progressBar()}}.} 11 | 12 | \item{id}{Parent id.} 13 | } 14 | \description{ 15 | Progress bars. 16 | } 17 | \examples{ 18 | library(shiny) 19 | 20 | ui <- fluidPage( 21 | theme = bslib::bs_theme(version = 5L), 22 | actionButton( 23 | "rand", 24 | "Randomise" 25 | ), 26 | progress( 27 | progressBar(15, id = "bar") 28 | ) 29 | ) 30 | 31 | server <- \(input, output, session){ 32 | observeEvent(input$rand, { 33 | update_progress("bar", sample(10:99, 1)) 34 | }) 35 | } 36 | 37 | if(interactive()) 38 | shinyApp(ui, server) 39 | 40 | } 41 | -------------------------------------------------------------------------------- /man/progressBar.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/progress.R 3 | \name{progressBar} 4 | \alias{progressBar} 5 | \title{Progress Bar} 6 | \usage{ 7 | progressBar(value = 0L, min = 0L, max = 100L, id = NULL, class = "") 8 | } 9 | \arguments{ 10 | \item{value}{Value of progress bar.} 11 | 12 | \item{min, max}{Minimum and maximum values.} 13 | 14 | \item{id}{ID of progress bar.} 15 | 16 | \item{class}{Additional classes.} 17 | } 18 | \description{ 19 | A progress bar to pass to \code{\link[=progress]{progress()}}. 20 | } 21 | -------------------------------------------------------------------------------- /man/rangeInput.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/inputs.R 3 | \name{rangeInput} 4 | \alias{rangeInput} 5 | \title{Range Input} 6 | \usage{ 7 | rangeInput(id, label, value = 0L, ..., min = 0L, max = 100L, step = 1L) 8 | } 9 | \arguments{ 10 | \item{id}{ID of input.} 11 | 12 | \item{label}{Label of input.} 13 | 14 | \item{value}{Initial value of input.} 15 | 16 | \item{...}{Passed to input.} 17 | 18 | \item{min, max}{Minimum and maximum values of the range.} 19 | 20 | \item{step}{Step of range change.} 21 | } 22 | \description{ 23 | A range input similar to a slider. 24 | } 25 | -------------------------------------------------------------------------------- /man/switchInput.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/inputs.R 3 | \name{switchInput} 4 | \alias{switchInput} 5 | \title{Switch Input} 6 | \usage{ 7 | switchInput(inputId, label, checked = FALSE, ...) 8 | } 9 | \arguments{ 10 | \item{inputId}{ID of input.} 11 | 12 | \item{label}{Label of input.} 13 | 14 | \item{checked}{Whether the input is initialised checked.} 15 | 16 | \item{...}{Passed to input.} 17 | } 18 | \description{ 19 | Switch input, similar to checkbox. 20 | } 21 | -------------------------------------------------------------------------------- /man/textGroupInput.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/inputs.R 3 | \name{textGroupInput} 4 | \alias{textGroupInput} 5 | \title{Text Group Input} 6 | \usage{ 7 | textGroupInput( 8 | inputId, 9 | label, 10 | value = "", 11 | placeholder = NULL, 12 | .position = c("left", "right") 13 | ) 14 | } 15 | \arguments{ 16 | \item{inputId}{ID of input.} 17 | 18 | \item{label}{Label of input.} 19 | 20 | \item{value}{Initial value of input.} 21 | 22 | \item{placeholder}{Placeholder for input.} 23 | 24 | \item{.position}{Position of the label.} 25 | } 26 | \description{ 27 | Text group input. 28 | } 29 | -------------------------------------------------------------------------------- /man/toast.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/toast.R 3 | \name{toast} 4 | \alias{toast} 5 | \title{Toast} 6 | \usage{ 7 | toast( 8 | id, 9 | ..., 10 | class = "", 11 | position = c("top-right", "top-left", "bottom-right", "bottom-left") 12 | ) 13 | } 14 | \arguments{ 15 | \item{id}{ID of toast, used to show/hide from server.} 16 | 17 | \item{...}{Content, generally \code{\link[=toastHeader]{toastHeader()}}, \code{\link[=toastBody]{toastBody()}}.} 18 | 19 | \item{class}{Any additional classes.} 20 | 21 | \item{position}{Position of the toast.} 22 | } 23 | \description{ 24 | Toast notifications. 25 | } 26 | \examples{ 27 | library(shiny) 28 | 29 | ui <- fluidPage( 30 | theme = bslib::bs_theme(version = 5L), 31 | toast( 32 | "toast", 33 | toastHeader( 34 | strong( 35 | "Toast", 36 | class = "me-auto" 37 | ) 38 | ), 39 | toastBody("The body of the toast!") 40 | ), 41 | h1("Hello"), 42 | actionButton("show", "Show toast"), 43 | actionButton("hide", "Hide toast") 44 | ) 45 | 46 | server <- \(input, output, session){ 47 | observeEvent(input$show, { 48 | toast_show("toast", auto_hide = FALSE) 49 | }) 50 | 51 | observeEvent(input$hide, { 52 | toast_hide("toast") 53 | }) 54 | } 55 | 56 | if(interactive()) 57 | shinyApp(ui, server) 58 | 59 | } 60 | -------------------------------------------------------------------------------- /man/toastContent.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/toast.R 3 | \name{toastContent} 4 | \alias{toastContent} 5 | \alias{toastHeader} 6 | \alias{toastBody} 7 | \title{Toast Content} 8 | \usage{ 9 | toastHeader(..., class = "") 10 | 11 | toastBody(..., class = "") 12 | } 13 | \arguments{ 14 | \item{...}{Content.} 15 | 16 | \item{class}{Any additional class.} 17 | } 18 | \description{ 19 | Content of the toast to place within \code{\link[=toast]{toast()}}. 20 | } 21 | -------------------------------------------------------------------------------- /man/toastToggle.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/toast.R 3 | \name{toastToggle} 4 | \alias{toastToggle} 5 | \alias{toast_show} 6 | \alias{toast_hide} 7 | \title{Toast Toggle} 8 | \usage{ 9 | toast_show( 10 | id, 11 | header = NULL, 12 | body = NULL, 13 | animation = TRUE, 14 | auto_hide = TRUE, 15 | delay = 5000L, 16 | session = shiny::getDefaultReactiveDomain() 17 | ) 18 | 19 | toast_hide(id, session = shiny::getDefaultReactiveDomain()) 20 | } 21 | \arguments{ 22 | \item{id}{ID of \code{\link[=toast]{toast()}} to toggle.} 23 | 24 | \item{header, body}{Header and body of the toast 25 | to replace existing content.} 26 | 27 | \item{animation}{Whether to animate the toast.} 28 | 29 | \item{auto_hide}{Whether to automatically hide the 30 | toast after \code{delay}.} 31 | 32 | \item{delay}{Milliseconds after which to hide the 33 | toast (if \code{auto_hide = TRUE}).} 34 | 35 | \item{session}{A valid shiny session.} 36 | } 37 | \description{ 38 | Show or hide a toast. 39 | } 40 | -------------------------------------------------------------------------------- /man/update_color_picker.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/inputs.R 3 | \name{update_color_picker} 4 | \alias{update_color_picker} 5 | \title{Update Color Picker} 6 | \usage{ 7 | update_color_picker(id, value, session = shiny::getDefaultReactiveDomain()) 8 | } 9 | \arguments{ 10 | \item{id}{ID of input to update.} 11 | 12 | \item{value}{Value to set.} 13 | 14 | \item{session}{A valid shiny session.} 15 | } 16 | \description{ 17 | Update a \code{\link[=colorPickerInput]{colorPickerInput()}} from the server. 18 | } 19 | -------------------------------------------------------------------------------- /man/update_progress.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/progress.R 3 | \name{update_progress} 4 | \alias{update_progress} 5 | \title{Update Progress} 6 | \usage{ 7 | update_progress(id, value, session = shiny::getDefaultReactiveDomain()) 8 | } 9 | \arguments{ 10 | \item{id}{ID of progress bar to update.} 11 | 12 | \item{value}{Value to set the progress bar to.} 13 | 14 | \item{session}{A valid shiny session.} 15 | } 16 | \description{ 17 | Update a \code{\link[=progressBar]{progressBar()}}. 18 | } 19 | -------------------------------------------------------------------------------- /man/update_range.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/inputs.R 3 | \name{update_range} 4 | \alias{update_range} 5 | \title{Update Range} 6 | \usage{ 7 | update_range(id, ..., session = shiny::getDefaultReactiveDomain()) 8 | } 9 | \arguments{ 10 | \item{id}{ID of input to update.} 11 | 12 | \item{...}{Elements to update, one or more of, 13 | \code{value}, \code{min}, and \code{max}.} 14 | 15 | \item{session}{A valid shiny session.} 16 | } 17 | \description{ 18 | Update a \code{\link[=rangeInput]{rangeInput()}} from the server. 19 | } 20 | -------------------------------------------------------------------------------- /man/update_text_group.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/inputs.R 3 | \name{update_text_group} 4 | \alias{update_text_group} 5 | \title{Update Text Group Input} 6 | \usage{ 7 | update_text_group(id, ..., session = shiny::getDefaultReactiveDomain()) 8 | } 9 | \arguments{ 10 | \item{id}{ID of input to update.} 11 | 12 | \item{...}{Items to update; \code{value}, and/or \code{label}.} 13 | 14 | \item{session}{Valid shiny session.} 15 | } 16 | \description{ 17 | Update \code{\link[=textGroupInput]{textGroupInput()}}. 18 | } 19 | -------------------------------------------------------------------------------- /man/withPopover.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/popover.R 3 | \name{withPopover} 4 | \alias{withPopover} 5 | \title{Popover} 6 | \usage{ 7 | withPopover( 8 | el, 9 | content, 10 | title = NULL, 11 | container = "body", 12 | placement = c("top", "right", "bottom", "left") 13 | ) 14 | } 15 | \arguments{ 16 | \item{el}{Element to place popover on.} 17 | 18 | \item{content}{Content of the popover.} 19 | 20 | \item{title}{Optional popover title.} 21 | 22 | \item{container}{container of the popover.} 23 | 24 | \item{placement}{Position of the popover.} 25 | } 26 | \description{ 27 | Add a popover to an element. 28 | } 29 | -------------------------------------------------------------------------------- /man/withTooltip.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/tooltip.R 3 | \name{withTooltip} 4 | \alias{withTooltip} 5 | \title{Tooltip} 6 | \usage{ 7 | withTooltip(el, title, placement = c("top", "right", "bottom", "left")) 8 | } 9 | \arguments{ 10 | \item{el}{Element.} 11 | 12 | \item{title}{HTML tag or character vector of length 1.} 13 | 14 | \item{placement}{Placement of the tooltip.} 15 | } 16 | \description{ 17 | Add a tooltip to an element. 18 | } 19 | \examples{ 20 | library(shiny) 21 | 22 | ui <- fluidPage( 23 | theme = bslib::bs_theme(version = 5L), 24 | withTooltip( 25 | span("plain"), 26 | "content" 27 | ), 28 | br(), 29 | withTooltip( 30 | span("HTML"), 31 | tagList( 32 | strong("HTML"), 33 | "content" 34 | ) 35 | ) 36 | ) 37 | 38 | server <- \(input, output, session){ 39 | } 40 | 41 | if(interactive()) 42 | shinyApp(ui, server) 43 | 44 | } 45 | --------------------------------------------------------------------------------