1#' Navigation items
2#'
3#' Create nav item(s) for use inside nav containers (e.g., [navs_tab()],
4#' [navs_bar()], etc).
5#'
6#' @param title A title to display. Can be a character string or UI elements
7#'   (i.e., [tags]).
8#' @param ... Depends on the function:
9#'   * For `nav()` and `nav_content()`: UI elements (i.e., [tags]) to display
10#'     when the item is active.
11#'   * For `nav_menu()`: a collection of nav items (e.g., `nav()`, `nav_item()`).
12#'   * For `nav_item()`: UI elements (i.e., [tags]) to place directly in
13#'     the navigation panel (e.g., search forms, links to external content, etc).
14#' @param value A character string to assign to the nav item. This value may be
15#'   supplied to the relevant container's `selected` argument in order to show
16#'   particular nav item's content immediately on page load. This value is also
17#'   useful for programmatically updating the selected content via
18#'   [nav_select()], [nav_hide()], etc (updating selected tabs this way is often
19#'   useful for showing/hiding panels of content via other UI controls like
20#'   [shiny::radioButtons()] -- in this scenario, consider using [nav_content()]
21#'   with [navs_hidden()]).
22#' @param icon Optional icon to appear next to the nav item's `title`.
23#' @return A nav item that may be passed to a nav container (e.g. [navs_tab()]).
24#' @export
25#' @seealso [navs_tab()], [nav_select()].
26#' @describeIn nav Content to display when the given item is selected.
27nav <- function(title, ..., value = title, icon = NULL) {
28  tabPanel_(title, ..., value = value, icon = icon)
29}
30
31#' @describeIn nav Create a menu of nav items.
32#' @param align horizontal alignment of the dropdown menu relative to dropdown toggle.
33#' @export
34nav_menu <- function(title, ..., value = title, icon = NULL, align = c("left", "right")) {
35  align <- match.arg(align)
36  navbarMenu_(title, ..., menuName = value, icon = icon, align = align)
37}
38
39#' @describeIn nav Create nav content for use inside `navs_hidden()` (for
40#'   creating custom navigation controls via `navs_select()`),
41#' @export
42nav_content <- function(value, ..., icon = NULL) {
43  tabPanelBody_(value, ..., icon = icon)
44}
45
46#' @describeIn nav Place arbitrary content in the navigation panel (e.g., search
47#'   forms, links to external content, etc.)
48#' @export
49nav_item <- function(...) {
50  # TODO: drop form-inline since BS5 dropped it?
51  # If we do that do we need navs_bar() to generate valid BS5 markup?
52  tags$li(class = "bslib-nav-item nav-item form-inline", ...)
53}
54
55is_nav_item <- function(x) {
56  tag_has_class(x, "bslib-nav-item")
57}
58
59#' @describeIn nav Adding spacing between nav items.
60#' @export
61nav_spacer <- function() {
62  div(class = "bslib-nav-spacer")
63}
64
65is_nav_spacer <- function(x) {
66  tag_has_class(x, "bslib-nav-spacer")
67}
68
69tag_has_class <- function(x, class) {
70  if (!inherits(x, "shiny.tag")) {
71    return(FALSE)
72  }
73  tagQuery(x)$hasClass(class)
74}
75