rshinybslib

How to change the text on bslib sidebar toggle button in opened and closed states?


I have the following working app that modifies the default sidebar toggle button. I want the button to say "Close Options" when the sidebar is opened and "Options" when the sidebar is closed. But I am not sure how to make this change. Could you please guide me what CSS property I can use to make that change?

library(bslib)
library(shiny)
library(ggplot2)

custom_sidebar <- function(ui_content, ...) {
  div(
    class = "custom-sidebar",
    page_sidebar(
      ...,
      tags$head(tags$style(HTML(
        "
     /* Style the toggle button */
     .custom-sidebar .bslib-sidebar-layout > .collapse-toggle {
       padding: 15px 10px;
       background-color: #007398;
       position: absolute;
       border-radius: 0 5px 5px 0;
       writing-mode: vertical-rl;
       text-orientation: mixed;
       height: auto;
       z-index: 1000;
       display: flex;
       align-items: center;
       justify-content: center;
       transition: all 0.3s;
       top: 100px;  /* Position from top */
       right: -40px;  /* Position on the right of sidebar */
     }
     /* When sidebar is closed */
     .custom-sidebar .bslib-sidebar-layout:not(.sidebar-open) > .collapse-toggle {
       left: 0;
       right: auto;  /* Reset right position when closed */
     }
     /* Style the toggle icon */
     .custom-sidebar .bslib-sidebar-layout > .collapse-toggle > .collapse-icon {
       fill: white !important;
       margin-bottom: 10px;
     }
     /* Add Options text */
     .custom-sidebar .bslib-sidebar-layout > .collapse-toggle::after {
       content: 'Options';
       color: white;
       font-size: 1.1em;
       text-transform: uppercase;
       letter-spacing: 1px;
       margin-top: 10px;
     }
     /* Adjust main content margins */
     .custom-sidebar .bslib-sidebar-layout > .main {
       margin-left: 300px;
       transition: margin-left 0.3s;
       width: calc(100% - 300px);
     }
     .custom-sidebar .bslib-sidebar-layout:not(.sidebar-open) > .main {
       margin-left: 0;
       width: 100%;
     }
     .custom-sidebar .bslib-sidebar-layout>.sidebar {
         margin-left: 20px;
     }
     "
      ))),
      ui_content
    )
  )
}

ui <- custom_sidebar(
  title = "Example dashboard",
  sidebar = sidebar(
    open = FALSE, # Start with sidebar open
    varSelectInput("var", "Select variable", mtcars)
  ),
  card(
    full_screen = TRUE,
    card_header("My plot"),
    plotOutput("p")
  )
)
server <- function(input, output) {
  output$p <- renderPlot({
    ggplot(mtcars) +
      geom_histogram(aes(!!input$var))
  })
}
shinyApp(ui, server)

Solution

  • Remove the content: 'Options'; from .custom-sidebar .bslib-sidebar-layout > .collapse-toggle::after and distinguish between the value of aria-expanded:

    .custom-sidebar .bslib-sidebar-layout > .collapse-toggle[aria-expanded='true']::after {
      content: 'Close Options';
    }
    .custom-sidebar .bslib-sidebar-layout > .collapse-toggle[aria-expanded='false']::after {
      content: 'Options';
    }
    

    enter image description here

    library(bslib)
    library(shiny)
    library(ggplot2)
    
    custom_sidebar <- function(ui_content, ...) {
      div(
        class = "custom-sidebar",
        page_sidebar(
          ...,
          tags$head(tags$style(HTML(
            "
         /* Style the toggle button */
         .custom-sidebar .bslib-sidebar-layout > .collapse-toggle {
           padding: 15px 10px;
           background-color: #007398;
           position: absolute;
           border-radius: 0 5px 5px 0;
           writing-mode: vertical-rl;
           text-orientation: mixed;
           height: auto;
           z-index: 1000;
           display: flex;
           align-items: center;
           justify-content: center;
           transition: all 0.3s;
           top: 100px;  /* Position from top */
           right: -40px;  /* Position on the right of sidebar */
         }
         /* When sidebar is closed */
         .custom-sidebar .bslib-sidebar-layout:not(.sidebar-open) > .collapse-toggle {
           left: 0;
           right: auto;  /* Reset right position when closed */
         }
         /* Style the toggle icon */
         .custom-sidebar .bslib-sidebar-layout > .collapse-toggle > .collapse-icon {
           fill: white !important;
           margin-bottom: 10px;
         }
         /* Add Options text */
         .custom-sidebar .bslib-sidebar-layout > .collapse-toggle::after {
           color: white;
           font-size: 1.1em;
           text-transform: uppercase;
           letter-spacing: 1px;
           margin-top: 10px;
         }
         .custom-sidebar .bslib-sidebar-layout > .collapse-toggle[aria-expanded='true']::after {
           content: 'Close Options';
         }
         .custom-sidebar .bslib-sidebar-layout > .collapse-toggle[aria-expanded='false']::after {
           content: 'Options';
         }
         /* Adjust main content margins */
         .custom-sidebar .bslib-sidebar-layout > .main {
           margin-left: 300px;
           transition: margin-left 0.3s;
           width: calc(100% - 300px);
         }
         .custom-sidebar .bslib-sidebar-layout:not(.sidebar-open) > .main {
           margin-left: 0;
           width: 100%;
         }
         .custom-sidebar .bslib-sidebar-layout>.sidebar {
             margin-left: 20px;
         }
         "
          ))),
          ui_content
        )
      )
    }
    
    ui <- custom_sidebar(
      title = "Example dashboard",
      sidebar = sidebar(
        open = FALSE, # Start with sidebar open
        varSelectInput("var", "Select variable", mtcars)
      ),
      card(
        full_screen = TRUE,
        card_header("My plot"),
        plotOutput("p")
      )
    )
    server <- function(input, output) {
      output$p <- renderPlot({
        ggplot(mtcars) +
          geom_histogram(aes(!!input$var))
      })
    }
    shinyApp(ui, server)