Skip to content

Commit d65ad5e

Browse files
Modify icon() function to call fontawesome::fa_i() for equivalent functionality (#3302)
* Use `fontawesome::fa_i()` for FA <i> tags * Remove fontawesome vendor files * Add fontawesome pkg to Imports & Remotes * Remove FontAwesome `person()` entry * Remove Font Awesome license info * Delete font-awesome.R * Update 'Collate' field (removes 'font-awesome.R') * Delete updateFontAwesome.R * Prefer use of `fontawesome::fa()` * Improve function documentation * Update help file using roxygen * Modify icon name * Update icon name in example * Modify icon name in example * Update help files * Update bootstrap.R * Update icon.Rd * Update bootstrap.R * Revert `showcaseCodeTabs()` to use FA v4 name * Revert icon name in example (back to FA v4) * Remove `call. = FALSE` in `stop()` * Remove `fontawesome` from Remotes * Add min version req for the fontawesome pkg * Increase minimum version requirement for fontawesome * Update roxygen docs for `icon()` * Document (GitHub Actions) * Update icon.Rd * Generate early return <i> tag for tabsetPanel logic * Close #3384 and #3383: simplify and correct icon() logic * Install htmltools PR for now * Document (GitHub Actions) * Avoid using tag attribs to hold non-attribute values * Better legacy support * No need to call prepTabIcon() twice * code review * Fix glyphicon class creation * update news Co-authored-by: Carson Sievert <[email protected]> Co-authored-by: rich-iannone <[email protected]> Co-authored-by: cpsievert <[email protected]>
1 parent 383fa6c commit d65ad5e

27 files changed

+102
-17539
lines changed

DESCRIPTION

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@ Authors@R: c(
4444
comment = "Bootstrap-datepicker library"),
4545
person("Andrew", "Rowls", role = c("ctb", "cph"),
4646
comment = "Bootstrap-datepicker library"),
47-
person("Dave", "Gandy", role = c("ctb", "cph"),
48-
comment = "Font-Awesome font"),
4947
person("Brian", "Reavis", role = c("ctb", "cph"),
5048
comment = "selectize.js library"),
5149
person("Salmen", "Bejaoui", role = c("ctb", "cph"),
@@ -80,6 +78,7 @@ Imports:
8078
mime (>= 0.3),
8179
jsonlite (>= 0.9.16),
8280
xtable,
81+
fontawesome (>= 0.2.1),
8382
htmltools (>= 0.5.1.9003),
8483
R6 (>= 2.0),
8584
sourcetools,
@@ -138,7 +137,6 @@ Collate:
138137
'devmode.R'
139138
'diagnose.R'
140139
'fileupload.R'
141-
'font-awesome.R'
142140
'graph.R'
143141
'reactives.R'
144142
'reactive-domains.R'

LICENSE

Lines changed: 0 additions & 444 deletions
Large diffs are not rendered by default.

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ shiny 1.6.0.9000
1717
* Closed #3321: New informative warning when `shiny.tag` object(s) are supplied to `...`. In this case we will continue to create an "empty" nav item and include the content on every tab, but the warning will mention the (new) `header`/`footer` args, which is likely what the user wants.
1818
* Closed #3320: The HTML markup that `tabPanel()` et. al generate (for Bootstrap nav) is now Bootstrap 4+ compliant when used with `theme = bslib::bs_theme()`.
1919
* Closed #1928: `NULL` values are now dropped instead of producing an empty nav item.
20+
21+
* `icon(lib="fontawesome")` is now powered by the `{fontawesome}` package, which will make it easier to use the latest FA icons in the future (by updating the `{fontawesome}` package). (#3302)
2022

2123
### Other improvements
2224

R/bootstrap.R

Lines changed: 66 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -498,10 +498,14 @@ navbarPage <- function(title,
498498
#' @rdname navbarPage
499499
#' @export
500500
navbarMenu <- function(title, ..., menuName = title, icon = NULL) {
501+
icon <- prepTabIcon(icon)
501502
structure(list(title = title,
502503
menuName = menuName,
503504
tabs = list2(...),
504-
iconClass = iconClass(icon)),
505+
# Here for legacy reasons
506+
# https://github.com/cran/miniUI/blob/74c87d3/R/layout.R#L369
507+
iconClass = tagGetAttribute(icon, "class"),
508+
icon = icon),
505509
class = "shiny.navbarmenu")
506510
}
507511

@@ -641,13 +645,18 @@ helpText <- function(...) {
641645
#' @export
642646
#' @describeIn tabPanel Create a tab panel that can be included within a [tabsetPanel()] or a [navbarPage()].
643647
tabPanel <- function(title, ..., value = title, icon = NULL) {
644-
div(
648+
icon <- prepTabIcon(icon)
649+
pane <- div(
645650
class = "tab-pane",
646651
title = title,
647652
`data-value` = value,
648-
`data-icon-class` = iconClass(icon),
653+
# Here for legacy reasons
654+
# https://github.com/cran/miniUI/blob/74c87d/R/layout.R#L395
655+
`data-icon-class` = tagGetAttribute(icon, "class"),
649656
...
650657
)
658+
attr(pane, "_shiny_icon") <- icon
659+
pane
651660
}
652661

653662
isTabPanel <- function(x) {
@@ -879,17 +888,23 @@ findAndMarkSelectedTab <- function(tabs, selected, foundSelected) {
879888
return(list(tabs = tabs, foundSelected = foundSelected))
880889
}
881890

882-
# Returns the icon object (or NULL if none), provided either a
883-
# tabPanel, OR the icon class
884-
getIcon <- function(tab = NULL, iconClass = NULL) {
885-
if (!is.null(tab)) iconClass <- tab$attribs$`data-icon-class`
886-
if (!is.null(iconClass)) {
887-
if (grepl("fa-", iconClass, fixed = TRUE)) {
888-
# for font-awesome we specify fixed-width
889-
iconClass <- paste(iconClass, "fa-fw")
890-
}
891-
icon(name = NULL, class = iconClass)
892-
} else NULL
891+
prepTabIcon <- function(x = NULL) {
892+
if (is.null(x)) return(NULL)
893+
if (!inherits(x, "shiny.tag")) {
894+
stop(
895+
"`icon` must be a `shiny.tag` object. ",
896+
"Try passing `icon()` (or `tags$i()`) to the `icon` parameter.",
897+
call. = FALSE
898+
)
899+
}
900+
901+
is_fa <- grepl("fa-", tagGetAttribute(x, "class") %||% "", fixed = TRUE)
902+
if (!is_fa) {
903+
return(x)
904+
}
905+
906+
# for font-awesome we specify fixed-width
907+
tagAppendAttributes(x, class = "fa-fw")
893908
}
894909

895910
# Text filter for navbarMenu's (plain text) separators
@@ -990,15 +1005,14 @@ buildNavItem <- function(divTag, tabsetId, index) {
9901005
# https://github.com/rstudio/shiny/issues/3352
9911006
title <- divTag$attribs[["title"]]
9921007
value <- divTag$attribs[["data-value"]]
993-
icon <- getIcon(iconClass = divTag$attribs[["data-icon-class"]])
9941008
active <- isTabSelected(divTag)
9951009
divTag <- tagAppendAttributes(divTag, class = if (active) "active")
9961010
divTag$attribs$id <- id
9971011
divTag$attribs$title <- NULL
9981012
list(
9991013
divTag = divTag,
10001014
liTag = tagAddRenderHook(
1001-
liTag(id, title, value, icon),
1015+
liTag(id, title, value, attr(divTag, "_shiny_icon")),
10021016
function(x) {
10031017
if (isTRUE(getCurrentThemeVersion() >= 4)) {
10041018
tagQuery(x)$
@@ -1053,7 +1067,7 @@ buildDropdown <- function(divTag, tabset) {
10531067
class = "dropdown-toggle",
10541068
`data-toggle` = "dropdown",
10551069
`data-value` = divTag$menuName,
1056-
getIcon(iconClass = divTag$iconClass),
1070+
divTag$icon,
10571071
divTag$title,
10581072
tags$b(class = "caret")
10591073
),
@@ -1565,32 +1579,31 @@ downloadLink <- function(outputId, label="Download", class=NULL, ...) {
15651579
#' Create an icon
15661580
#'
15671581
#' Create an icon for use within a page. Icons can appear on their own, inside
1568-
#' of a button, or as an icon for a [tabPanel()] within a
1569-
#' [navbarPage()].
1570-
#'
1571-
#' @param name Name of icon. Icons are drawn from the
1572-
#' [Font Awesome Free](https://fontawesome.com/) (currently icons from
1573-
#' the v5.13.0 set are supported with the v4 naming convention) and
1574-
#' [Glyphicons](https://getbootstrap.com/components/#glyphicons)
1575-
#' libraries. Note that the "fa-" and "glyphicon-" prefixes should not be used
1576-
#' in icon names (i.e. the "fa-calendar" icon should be referred to as
1577-
#' "calendar")
1578-
#' @param class Additional classes to customize the style of the icon (see the
1582+
#' of a button, and/or used with [tabPanel()] and [navbarMenu()].
1583+
#'
1584+
#' @param name The name of the icon. A name from either [Font
1585+
#' Awesome](https://fontawesome.com/) (when `lib="font-awesome"`) or
1586+
#' [Bootstrap
1587+
#' Glyphicons](https://getbootstrap.com/docs/3.3/components/#glyphicons) (when
1588+
#' `lib="glyphicon"`) may be provided. Note that the `"fa-"` and
1589+
#' `"glyphicon-"` prefixes should not appear in name (i.e., the
1590+
#' `"fa-calendar"` icon should be referred to as `"calendar"`). A `name` of
1591+
#' `NULL` may also be provided to get a raw `<i>` tag with no library attached
1592+
#' to it.
1593+
#' @param class Additional classes to customize the style of an icon (see the
15791594
#' [usage examples](https://fontawesome.com/how-to-use) for details on
15801595
#' supported styles).
1581-
#' @param lib Icon library to use ("font-awesome" or "glyphicon")
1582-
#' @param ... Arguments passed to the `<i>` tag of [htmltools::tags]
1596+
#' @param lib The icon library to use. Either `"font-awesome"` or `"glyphicon"`.
1597+
#' @param ... Arguments passed to the `<i>` tag of [htmltools::tags].
15831598
#'
1584-
#' @return An icon element
1585-
#'
1586-
#' @seealso For lists of available icons, see
1587-
#' [https://fontawesome.com/icons](https://fontawesome.com/icons) and
1588-
#' [https://getbootstrap.com/components/#glyphicons](https://getbootstrap.com/components/#glyphicons).
1599+
#' @return An `<i>` (icon) HTML tag.
15891600
#'
1601+
#' @seealso For lists of available icons, see <https://fontawesome.com/icons>
1602+
#' and <https://getbootstrap.com/docs/3.3/components/#glyphicons>
15901603
#'
15911604
#' @examples
15921605
#' # add an icon to a submit button
1593-
#' submitButton("Update View", icon = icon("refresh"))
1606+
#' submitButton("Update View", icon = icon("redo"))
15941607
#'
15951608
#' navbarPage("App Title",
15961609
#' tabPanel("Plot", icon = icon("bar-chart-o")),
@@ -1599,48 +1612,26 @@ downloadLink <- function(outputId, label="Download", class=NULL, ...) {
15991612
#' )
16001613
#' @export
16011614
icon <- function(name, class = NULL, lib = "font-awesome", ...) {
1602-
prefixes <- list(
1603-
"font-awesome" = "fa",
1604-
"glyphicon" = "glyphicon"
1605-
)
1606-
prefix <- prefixes[[lib]]
16071615

1608-
# determine stylesheet
1609-
if (is.null(prefix)) {
1610-
stop("Unknown font library '", lib, "' specified. Must be one of ",
1611-
paste0('"', names(prefixes), '"', collapse = ", "))
1616+
# A NULL name allows for a generic <i> not tied to any library
1617+
if (is.null(name)) {
1618+
lib <- "none"
16121619
}
16131620

1614-
# build the icon class (allow name to be null so that other functions
1615-
# e.g. buildTabset can pass an explicit class value)
1616-
iconClass <- ""
1617-
if (!is.null(name)) {
1618-
prefix_class <- prefix
1619-
if (prefix_class == "fa" && name %in% font_awesome_brands) {
1620-
prefix_class <- "fab"
1621-
}
1622-
iconClass <- paste0(prefix_class, " ", prefix, "-", name)
1623-
}
1624-
if (!is.null(class))
1625-
iconClass <- paste(iconClass, class)
1626-
1627-
iconTag <- tags$i(class = iconClass, role = "presentation", `aria-label` = paste(name, "icon"), ...)
1628-
1629-
# font-awesome needs an additional dependency (glyphicon is in bootstrap)
1630-
if (lib == "font-awesome") {
1631-
htmlDependencies(iconTag) <- htmlDependency(
1632-
"font-awesome", "5.13.0", "www/shared/fontawesome", package = "shiny",
1633-
stylesheet = c(
1634-
"css/all.min.css",
1635-
"css/v4-shims.min.css"
1636-
)
1637-
)
1638-
}
1639-
1640-
htmltools::browsable(iconTag)
1621+
switch(
1622+
lib %||% "",
1623+
"none" = iconTag(name, class = class, ...),
1624+
"font-awesome" = fontawesome::fa_i(name = name, class = class, ...),
1625+
"glyphicon" = iconTag(
1626+
name, class = "glyphicon", class = paste0("glyphicon-", name),
1627+
class = class, ...
1628+
),
1629+
stop("Unknown icon library: ", lib, ". See `?icon` for supported libraries.")
1630+
)
16411631
}
16421632

1643-
# Helper funtion to extract the class from an icon
1644-
iconClass <- function(icon) {
1645-
if (!is.null(icon)) icon$attribs$class
1633+
iconTag <- function(name, ...) {
1634+
htmltools::browsable(
1635+
tags$i(..., role = "presentation", `aria-label` = paste(name, "icon"))
1636+
)
16461637
}

0 commit comments

Comments
 (0)