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

Possibility of user-defined custom toggles [enhancement] #352

Open
candidosobrinhosa opened this issue Jun 26, 2023 · 5 comments
Open

Possibility of user-defined custom toggles [enhancement] #352

candidosobrinhosa opened this issue Jun 26, 2023 · 5 comments
Labels
enhancement New feature or request question Further information is requested

Comments

@candidosobrinhosa
Copy link

Hello! Thanks for all the hard work!

I am currently hosting a web app reporting SARS in Brazil in two languages: English and Portuguese.

In order to swap between them, the user have to access radio buttons inside a dropdownmenu(notification) but a switch would look way better.

I wonder if there is a way to add a custom toggle, just like the "dark theme" and the new "help" toggles.

Best regards

@sactyr
Copy link

sactyr commented Jul 11, 2023

@candidosobrinhosa I am looking for the same and I managed to add a custom toggle using this code, but it looks fugly:

dashboardHeader(
    disable = FALSE
    ,rightUi = tags$li(
      class = "dropdown"
      ,prettySwitch(
          inputId = "test_toggle"
          ,label = NULL
          ,status = "primary"
          ,fill = TRUE
        )
        
    )
    
  )

image

It would be nice to include a native toggle switch just like the "dark" and "help" toggles. In the help for dashboardHeader it says rightUi and leftUi takes an element like dropdownMenu, but it would be good to know what other elements are possible here.

@sactyr
Copy link

sactyr commented Jul 13, 2023

ok so with my limited css knowledge I managed to align and make it a bit nicer, but prettySwitch is still a bit bigger than the other two toggles. If anyone knows how to scale it to the same size as other toggles that would be nice.

dashboardHeader(
    disable = FALSE
    ,rightUi = tags$li(
      class = "dropdown"
      ,prettySwitch(
          inputId = "test_toggle"
          ,label = NULL
          ,status = "primary"
          ,fill = TRUE
        ) %>% 
        tagAppendAttributes(
          class = "test_toggle_custom"
          ,style = "
          margin-bottom: 0; 
          margin-top: 0.5rem!important;
          margin-left: 0.5rem!important;
          margin-right: 0.5rem!important;
          width:32px" 
        )
    )
    
  )

image

@DivadNojnarg
Copy link
Member

Hi,

I think you could leverage Bootstrap 4 power and use the custom switch component (the same I used in the header for the theme switch and help switch): https://getbootstrap.com/docs/4.2/components/forms/#switches

library(shiny)
library(bs4Dash)

switch_input <- function(inputId, label, checked = FALSE, disabled = FALSE) {
  div(
    class = "custom-control custom-switch",
    tags$input(
      id = inputId,
      type = "checkbox",
      disabled = if (disabled) NA,
      class = "custom-control-input"
    ),
    tags$label(
      label,
      `for` = inputId,
      class = "custom-control-label"
    )
  )
}

ui <- dashboardPage(
  header = dashboardHeader(
    title = dashboardBrand(
      title = "My dashboard",
      color = "primary",
      href = "https://adminlte.io/themes/v3",
      image = "https://adminlte.io/themes/v3/dist/img/AdminLTELogo.png"
    ),
    switch_input("plop", "Activate me!")
  ),
  sidebar = dashboardSidebar(),
  body = dashboardBody(),
  controlbar = dashboardControlbar(),
  title = "DashboardPage"
)

server <- function(input, output, session) {
  observe({
    print(input$plop)
  })
}

shinyApp(ui, server)

@DivadNojnarg DivadNojnarg added enhancement New feature or request question Further information is requested labels Jul 13, 2023
@sactyr
Copy link

sactyr commented Jul 14, 2023

@DivadNojnarg That is awesome thanks! I think the checked argument is not being called within the switch_input function, and I couldn't see from the Bootstrap 4 switches doco how it is being used.

Update: Just figured how to include the checked argument:

switch_input <- function(inputId, label, checked = FALSE, disabled = FALSE) {
  div(
    class = "custom-control custom-switch",
    tags$input(
      id = inputId,
      type = "checkbox",
      disabled = if (disabled) NA,
      checked = if (checked) NA,
      class = "custom-control-input"
    ),
    tags$label(
      label,
      `for` = inputId,
      class = "custom-control-label"
    )
  )
}

@sactyr
Copy link

sactyr commented Jul 14, 2023

I have generalised @DivadNojnarg's switch_input function to accept other types of custom control inputs from Bootstrap 4, such as checkbox and radio. These seems to only work for one input per type:

custom_control_input <- function(inputId, type = c("switch", "checkbox", "radio"), label, checked = FALSE, disabled = FALSE) {
  
  div(
    class = paste0("custom-control custom-", type),
    tags$input(
      id = inputId,
      type = ifelse(type == "switch", "checkbox", type),
      disabled = if (disabled) NA,
      checked = if (checked) NA,
      class = "custom-control-input"
    ),
    tags$label(
      label,
      `for` = inputId,
      class = "custom-control-label"
    )
  )
}

I did some digging and implemented a similar function for form check inputs that seems to accept multiple choice inputs per type. Useful if you want to use the same style of inputs throughout your bs4Dash app:

library(shiny)
library(bs4Dash)


form_check_input <- function(inputId, type = c("checkbox", "radio"), label, radio_name, checked, disabled, inline = FALSE) {
  
  if (length(unique(c(length(checked), length(disabled), length(label)))) == 1) {
    
    lapply(seq_along(label), function(x) {
      
      div(
        class = paste("form-check", if (inline) "form-check-inline")
        ,tags$input(
          class = "form-check-input"
          ,type = type
          ,name = ifelse(type == "radio", radio_name, NA) 
          ,id = paste0(inputId, x)
          ,disabled = if (disabled[x]) NA
          ,checked = if (checked[x]) NA
        )
        ,tags$label(
          class = "form-check-label"
          ,`for` = paste0(inputId, x)
          ,label[x]
        )
      )
      
    })
    
  } else {
    
    stop("Check lengths of label, checked and disabled are all same")
    
  }
  
}

ui <- dashboardPage(
  header = dashboardHeader(
    title = dashboardBrand(
      title = "My dashboard",
      color = "primary",
      href = "https://adminlte.io/themes/v3",
      image = "https://adminlte.io/themes/v3/dist/img/AdminLTELogo.png"
    )
  ),
  sidebar = dashboardSidebar(),
  body = dashboardBody(
    
    form_check_input(
      inputId = "plop"
      , type = "checkbox"
      , label = c("a","b")
      , radio_name = "testradio"
      , checked = c(TRUE, FALSE)
      , disabled = c(FALSE, FALSE)
      ,inline = TRUE
    )
    
  ),
  controlbar = dashboardControlbar(),
  title = "DashboardPage"
)

server <- function(input, output, session) {
  observe({
    print(
      c(input$plop1, input$plop2)
    )
  })

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants