Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CRAN release 2.3.0 #350

Merged
merged 9 commits into from
Jun 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: bs4Dash
Type: Package
Title: A 'Bootstrap 4' Version of 'shinydashboard'
Version: 2.2.1
Version: 2.3.0
Authors@R: c(
person("David", "Granjon", email = "[email protected]", role = c("aut", "cre")),
person(family = "RinteRface", role = "cph"),
Expand Down
4 changes: 4 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export(dashboardUser)
export(dashboardUserItem)
export(descriptionBlock)
export(dropdownDivider)
export(dropdownHeader)
export(dropdownMenu)
export(dropdownMenuOutput)
export(getAdminLTEColors)
Expand All @@ -114,6 +115,8 @@ export(menuItemOutput)
export(menuSubItem)
export(messageItem)
export(multiProgressBar)
export(navbarMenu)
export(navbarTab)
export(notificationItem)
export(pagination)
export(paginationItem)
Expand Down Expand Up @@ -158,6 +161,7 @@ export(updateCard)
export(updateCardSidebar)
export(updateControlbar)
export(updateControlbarMenu)
export(updateNavbarTabs)
export(updatePagination)
export(updateSidebar)
export(updateTabItems)
Expand Down
22 changes: 22 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
# bs4Dash 2.3.0

## New feature
New navbar navigation menu.
- `navbarTab()`, `navbarMenu()` and `updateNavbarTabs()` to create navbar navigation.
This will close #108.

## Minor change
- New `dropdownHeader()` function to display Bootstrap 4 dropdown headers.
- Adjust `dropdownDivider()` as it was invisible.
- `tabItems()` has __.list__ parameter to pass `tabItem()` elements as list.
- Fix #342: better title alignment in `tabBox()`. Increase padding for card with pills. Thanks @HugoGit39
for reporting.

## Bug fixes
- Fix #349: allow to pass list of `accordionItem()` with `.list` parameter in `accordion()`. Thanks @vladimirstroganov for reporting.
- Fix #330: allow to use input elements (or any not `menuItem` element) in the sidebar.
- Fix #343: Refine `help` parameter behavior in `dashboardPage()`. If NULL, no icon is shown. If FALSE, icon and toggle are shown but not checked. If TRUE the toggle is checked.

## Internal
- Change dark/light switch CSS class for consistency.

# bs4Dash 2.2.1

## New features
Expand Down
37 changes: 25 additions & 12 deletions R/cards.R
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,7 @@ cardDropdownItem <- function(..., id = NULL, href = NULL, icon = NULL) {
#'
#' @export
dropdownDivider <- function() {
shiny::tags$a(class = "divider")
shiny::div(class = "dropdown-divider")
}


Expand Down Expand Up @@ -1180,7 +1180,7 @@ bs4TabCard <- function(..., id = NULL, selected = NULL, title = NULL, width = 6,
# add card-tabs class
boxTag$children[[1]]$attribs$class <- paste0(
boxTag$children[[1]]$attribs$class,
if (solidHeader) {
if (solidHeader || type == "pills") {
" card-tabs"
} else {
" card-outline-tabs"
Expand All @@ -1190,19 +1190,27 @@ bs4TabCard <- function(..., id = NULL, selected = NULL, title = NULL, width = 6,
# change header class
boxTag$children[[1]]$children[[1]]$attribs$class <- paste0(
boxTag$children[[1]]$children[[1]]$attribs$class,
if (solidHeader) {
" p-0 pt-1"
} else {
" p-0 border-bottom-0"
if (type != "pills") {
if (solidHeader) {
" p-0 pt-1"
} else {
" p-0 border-bottom-0"
}
}
)


# Remove title and add it to tab list
titleTag <- boxTag$children[[1]]$children[[1]]$children[[1]]
if (type == "tabs") {
titleTag$attribs$class <- paste(
titleTag$attribs$class,
"pt-1"
)
}
boxTag$children[[1]]$children[[1]]$children[[1]] <- NULL
titleNavTag <- shiny::tags$li(
class = "pt-2 px-3",
class = if (side == "left") "pt-2 px-3 ml-auto" else "pt-2 px-3",
titleTag
)

Expand All @@ -1224,11 +1232,16 @@ bs4TabCard <- function(..., id = NULL, selected = NULL, title = NULL, width = 6,
}

# Insert box tools at the end of the list
content$children[[1]] <- tagInsertChild(
content$children[[1]],
shiny::tags$li(class = "ml-auto", boxToolTag),
length(content$children[[1]])
)
if (
length(boxToolTag$children[[1]]) > 0 ||
length(boxToolTag$children[[2]]) > 0
) {
content$children[[1]] <- tagInsertChild(
content$children[[1]],
shiny::tags$li(class = if (side == "left") "ml-0" else "ml-auto", boxToolTag),
length(content$children[[1]])
)
}

# Insert tabs at different position in the header tag
if (side == "right") {
Expand Down
8 changes: 5 additions & 3 deletions R/dashboardBody.R
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,16 @@ bs4DashBody <- function(...) {
#'
#' @param ... Items to put in the container. Each item should be a
#' \code{\link{tabItem}}.
#' @param .list Pass items as list with \link{lapply} family functions.
#'
#' @rdname dashboardBody
#'
#' @export
bs4TabItems <- function(...) {
lapply(list(...), tagAssert, class = "tab-pane")
bs4TabItems <- function(..., .list = NULL) {
items <- c(list(...), .list)
lapply(items, tagAssert, class = "tab-pane")

shiny::tags$div(class = "tab-content", ...)
shiny::tags$div(class = "tab-content", items)
}

#' Boostrap 4 body item
Expand Down
178 changes: 177 additions & 1 deletion R/dashboardHeader.R
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
#'
#' @rdname dashboardHeader
#'
#' @param ... Any UI element between left and right Ui.
#' @param ... Any UI element between left and right Ui. Can include \link{navbarMenu} to host
#' the navigation in the navbar.
#' @param title Dashboard title (displayed top-left side). Alternatively, use \link{dashboardBrand}
#' for more evolved title.
#' @param titleWidth This argument is deprecated; bs4Dash (AdminLTE3) title width
Expand Down Expand Up @@ -129,9 +130,184 @@ bs4DashNavbar <- function(..., title = NULL, titleWidth = NULL, disable = FALSE,
list(headerTag, title)
}

#' Navbar tab item
#'
#' Similar to \link{menuItem} but for the
#' \link{dashboardHeader}.
#'
#' @param text Tab text.
#' @param ... Slot for nested \link{navbarTab}. You can nest as many elements
#' as you want.
#' @param tabName Should correspond exactly to the tabName given in \link{tabItem}.
#' @param icon An icon tag, created by shiny::icon. If NULL, don't display an icon.
#' @param .list Use this slot if you had to programmatically pass \link{navbarTab}
#' like with \link{lapply}.
#'
#' @note You can nest \link{navbarTab} so it does like
#' \link{menuSubItem}. This is to avoid to create too many functions.
#' @export
#' @rdname navbar-menu
navbarTab <- function(text, ..., tabName = NULL, icon = NULL, .list = NULL) {
items <- c(list(...), .list)
if (length(items) > 0) {
do.call(navbarDropdown, list(text, items))
} else {
shiny::tags$li(
class = "nav-item",
shiny::tags$a(
class = "nav-link",
id = paste0("tab-", tabName),
href = paste0("#shiny-tab-", tabName),
`data-toggle` = "tab",
`data-value` = tabName,
icon,
shiny::tags$p(text)
)
)
}
}

#' Build navbar dropdown for navigation
#'
#' This is different from \link{dropdownMenu}.
#'
#' @param text Dropdown menu title.
#' @param ... Slot for nested items such as \link{navbarTab}.
#'
#' @keywords internal
navbarDropdown <- function(text, ...) {
shiny::tags$li(
class = "nav-item dropdown",
shiny::tags$a(
href = "#",
`data-toggle` = "dropdown",
`aria-haspopup` = "true",
`aria-expanded` = "false",
class = "nav-link dropdown-toggle",
text
),
shiny::tags$ul(
class = "dropdown-menu border-0 shadow",
style = "left: 0px; right: inherit;",
...
)
)
}

#' Dropdown header helper
#'
#' Display header text within dropdown menu
#'
#' @param text Text to display.
#'
#' @return A shiny tag.
#' @export
dropdownHeader <- function(text) {
shiny::tags$h6(class = "dropdown-header", text)
}

#' Navbar menu
#'
#' Like \link{sidebarMenu} but inside \link{dashboardHeader}.
#'
#' @param ... Slot for \link{navbarTab}.
#' @param id Menu id. Useful to leverage \link{updateNavbarTabs} on the
#' server.
#' @rdname navbar-menu
#' @export
#' @examples
#' if (interactive()) {
#' library(shiny)
#' library(bs4Dash)
#'
#' tabs <- tabItems(.list = lapply(1:7, function(i) {
#' tabItem(tabName = sprintf("Tab%s", i), sprintf("Tab %s", i))
#' }))
#'
#' shinyApp(
#' ui = dashboardPage(
#' header = dashboardHeader(
#' navbarMenu(
#' id = "navmenu",
#' navbarTab(tabName = "Tab1", text = "Tab 1"),
#' navbarTab(tabName = "Tab2", text = "Tab 2"),
#' navbarTab(
#' text = "Menu",
#' dropdownHeader("Dropdown header"),
#' navbarTab(tabName = "Tab3", text = "Tab 3"),
#' dropdownDivider(),
#' navbarTab(
#' text = "Sub menu",
#' dropdownHeader("Another header"),
#' navbarTab(tabName = "Tab4", text = "Tab 4"),
#' dropdownHeader("Yet another header"),
#' navbarTab(tabName = "Tab5", text = "Tab 5"),
#' navbarTab(
#' text = "Sub sub menu",
#' navbarTab(tabName = "Tab6", text = "Tab 6"),
#' navbarTab(tabName = "Tab7", text = "Tab 7")
#' )
#' )
#' )
#' )
#' ),
#' body = dashboardBody(tabs),
#' controlbar = dashboardControlbar(
#' sliderInput(
#' inputId = "controller",
#' label = "Update the first tabset",
#' min = 1,
#' max = 4,
#' value = 1
#' )
#' ),
#' sidebar = dashboardSidebar(disable = TRUE)
#' ),
#' server = function(input, output, session) {
#' observeEvent(input$controller, {
#' updateNavbarTabs(
#' session,
#' inputId = "navmenu",
#' selected = paste0("Tab", input$controller)
#' )
#' },
#' ignoreInit = TRUE
#' )
#' }
#' )
#' }
navbarMenu <- function(..., id = NULL) {
if (is.null(id)) id <- paste0("tabs_", round(stats::runif(1, min = 0, max = 1e9)))

items <- list(...)
items <- htmltools::tagQuery(items)$
find(".nav-item.dropdown")$
removeClass("nav-item dropdown")$
addClass("dropdown-submenu dropdown-hover")$
find("ul")$
removeAttrs("style")$
reset()$
selectedTags()

shiny::tags$ul(
class = "navbar-nav sidebar-menu",
role = "menu",
items,
shiny::div(
id = id,
class = "sidebarMenuSelectedTabItem",
`data-value` = "null",

)
)
}

#' Update navbar menu from the server.
#'
#' @inheritParams updatebs4TabItems
#' @rdname navbar-menu
#' @export
updateNavbarTabs <- updatebs4TabItems

#' Alternative to simple text title
#'
Expand Down
11 changes: 8 additions & 3 deletions R/dashboardPage.R
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@
#' Expect a list.
#' @param fullscreen Whether to allow fullscreen feature in the navbar. Default to FALSE.
#' @param help Whether to enable/disable popovers and tooltips. This allows to seamlessly use
#' \link{tooltip} and \link{popover} without having to individually toggle them. Default to FALSE.
#' if TRUE, a help icon is display in the navigation bar.
#' \link{tooltip} and \link{popover} without having to individually toggle them. Default to FALSE,
#' the toggle is shown but not enabled. If TRUE, all tooltips and popovers are enabled.
#' Set to NULL if you want to hide the help icon.
#' @param dark Whether to display toggle to switch between dark and light mode in the \link{dashboardHeader}.
#' Default to FALSE, app starts in light mode, with possibility to switch to dark.
#' If TRUE, the app starts in dark with possibility to switch back to light. If NULL,
Expand Down Expand Up @@ -179,7 +180,11 @@ bs4DashPage <- function(header, sidebar, body, controlbar = NULL, footer = NULL,
# Body
add_bs4Dash_deps(
shiny::tags$body(
`data-help` = if (help) 1 else 0,
`data-help` = if (!is.null(help)) {
if (help) 2 else 1
} else {
0
},
`data-fullscreen` = if (fullscreen) 1 else 0,
`data-dark` = if (!is.null(dark)) {
if (dark) {
Expand Down
Loading