33# ' Tooltips are useful for showing additional information when focusing (or
44# ' hovering over) a UI element.
55# '
6- # ' @param ... Unnamed arguments can be any valid child of an [htmltools
7- # ' tag][htmltools::tags]. Named arguments become HTML attributes on returned
8- # ' UI element. Attributes starting with `data-bs-*` may be supplied to further
9- # ' customize [tooltip
10- # ' options](https://getbootstrap.com/docs/5.3/components/tooltips/).
11- # ' @param body Content to display in the tooltip.
12- # ' @param placement The placement of the tooltip relative to the target element.
13- # ' @param html Whether to treat `body` as HTML. WARNING: setting this `TRUE`
14- # ' when the `body` is a function of user `inputs` is dangerous and not
15- # ' recommended.
16- # ' @param sanitize Whether to sanitize HTML (only relevant when `html = TRUE`).
17- # ' This can be useful if `body` is a function of user `inputs`, but should
18- # ' also be treated as HTML.
6+ # ' @param trigger A UI element (i.e., [htmltools tag][htmltools::tags]) to serve as the
7+ # ' tooltips trigger. It's good practice for this element to be a keyboard-focusable
8+ # ' and interactive element (e.g., `actionButton()`, `actionLink()`, etc) so that
9+ # ' the tooltip is accessible to keyboard and assistive technology users.
10+ # ' @param ... UI elements for the tooltip. Character strings are automatically
11+ # ' [htmlEscape()]d unless marked as [HTML()].
1912# ' @param id If provided, you can use `input$id` in your server logic to
2013# ' determine whether the tooltip is currently shown/hidden.
14+ # ' @param placement The placement of the tooltip relative to its trigger.
15+ # ' @param options A list of additional [Bootstrap options](https://getbootstrap.com/docs/5.3/components/tooltips/#options).
2116# '
22- # ' @details If multiple UI elements are provided to `...` , the last element is
17+ # ' @details If `x` yields multiple HTML elements , the last element is
2318# ' used as the tooltip's target. If the target should contain multiple elements,
2419# ' then wrap those elements in a [span()] or [div()].
2520# '
3025# '
3126# ' tooltip(
3227# ' shiny::actionButton("btn", "A button"),
33- # ' body = "A message"
28+ # ' "A message"
3429# ' )
3530# '
3631# ' card(
3732# ' card_header(
3833# ' tooltip(
3934# ' span("Card title ", bsicons::bs_icon("question-circle-fill")),
40- # ' body = "Additional info",
35+ # ' "Additional info",
4136# ' placement = "right"
4237# ' )
4338# ' ),
4439# ' "Card body content..."
4540# ' )
4641tooltip <- function (
47- ... ,
48- body = " Tooltip" ,
49- placement = c(" auto" , " top" , " right" , " bottom" , " left" ),
50- html = FALSE ,
51- sanitize = FALSE ,
52- id = NULL
53- ) {
42+ trigger , ... , id = NULL ,
43+ placement = c(" auto" , " top" , " right" , " bottom" , " left" ),
44+ options = list ()
45+ ) {
46+
47+ args <- rlang :: list2(... )
48+ argnames <- rlang :: names2(args )
49+
50+ children <- args [! nzchar(argnames )]
51+ attribs <- args [nzchar(argnames )]
52+
53+ # if (length(attribs) > 0) {
54+ # abort(c(
55+ # paste0("Unknown named argument: '", names(attribs)[1], "'."),
56+ # "i" = "Did you intend to pass it to `options`?"
57+ # ))
58+ # }
5459
5560 res <- web_component(
5661 " bslib-tooltip" ,
57- placement = rlang :: arg_match(placement ),
58- html = if (html ) NA ,
59- sanitize = if (sanitize ) NA ,
6062 id = id ,
63+ placement = rlang :: arg_match(placement ),
64+ options = jsonlite :: toJSON(options ),
65+ !!! attribs ,
6166 # Use display:none instead of <template> since shiny.js
6267 # doesn't bind to the contents of the latter
63- div(body , style = " display:none;" ),
64- ...
68+ div(!!! children , style = " display:none;" ),
69+ trigger
6570 )
6671
6772 res <- tag_require(res , version = 5 , caller = " tooltip()" )
@@ -89,13 +94,15 @@ tooltip_toggle <- function(id, show = NULL, session = get_current_session()) {
8994}
9095
9196
92- # ' @describeIn tooltip Update the `body` of a tooltip.
97+ # ' @describeIn tooltip Update the contents of a tooltip.
9398# ' @export
94- tooltip_update <- function (id , body = NULL , session = get_current_session()) {
99+ tooltip_update <- function (id , ... , session = get_current_session()) {
100+
101+ title <- tagList(... )
95102
96103 msg <- dropNulls(list (
97104 method = " update" ,
98- title = if (! is.null( body ) ) processDeps(body , session )
105+ title = if (length( title ) > 0 ) processDeps(title , session )
99106 ))
100107
101108 force(id )
@@ -105,6 +112,10 @@ tooltip_update <- function(id, body = NULL, session = get_current_session()) {
105112 session $ onFlush(callback , once = TRUE )
106113}
107114
115+ # TODO: worth it?
116+ # tooltip_disable <- function(id) {}
117+ # tooltip_enable <- function(id) {}
118+
108119
109120normalize_show_value <- function (show ) {
110121 if (is.null(show )) return (" toggle" )
0 commit comments