| 
 | 1 | +library(shiny)  | 
 | 2 | +library(bslib)  | 
 | 3 | + | 
 | 4 | +ui <- page_fill(  | 
 | 5 | +  theme = bs_theme(  | 
 | 6 | +    # Don't transition when collapsing (so screenshot timing is less of an issue)  | 
 | 7 | +    "transition-collapse" = "none",  | 
 | 8 | +    "accordion-bg" = "#1E1E1E",  | 
 | 9 | +    "accordion-color" = "white",  | 
 | 10 | +    "accordion-icon-color" = "white",  | 
 | 11 | +    "accordion-icon-active-color" = "white"  | 
 | 12 | +  ),  | 
 | 13 | +  layout_sidebar(  | 
 | 14 | +    border_radius = FALSE,  | 
 | 15 | +    border = FALSE,  | 
 | 16 | +    bg = "lightgray",  | 
 | 17 | +    sidebar(  | 
 | 18 | +      bg = "#1E1E1E",  | 
 | 19 | +      accordion(  | 
 | 20 | +        open = TRUE,  | 
 | 21 | +        accordion_panel(  | 
 | 22 | +          "Selected section(s)",  | 
 | 23 | +          selectInput("selected", NULL, LETTERS, multiple = TRUE, selected = "A"),  | 
 | 24 | +        ),  | 
 | 25 | +        accordion_panel(  | 
 | 26 | +          "Displayed section(s)",  | 
 | 27 | +          selectInput("displayed", NULL, LETTERS, multiple = TRUE, selected = LETTERS)  | 
 | 28 | +        ),  | 
 | 29 | +        accordion_panel(  | 
 | 30 | +          "Parameters",  | 
 | 31 | +          checkboxInput("multiple", "Allow multiple panels to be open", TRUE),  | 
 | 32 | +          checkboxInput("open_on_insert", "Open on insert", FALSE)  | 
 | 33 | +        )  | 
 | 34 | +      )  | 
 | 35 | +    ),  | 
 | 36 | +    uiOutput("accordion")  | 
 | 37 | +  )  | 
 | 38 | +)  | 
 | 39 | + | 
 | 40 | +server <- function(input, output, session) {  | 
 | 41 | + | 
 | 42 | +  make_panel <- function(x) {  | 
 | 43 | +    accordion_panel(  | 
 | 44 | +      paste("Section", x),  | 
 | 45 | +      paste("Some narrative for section", x),  | 
 | 46 | +      value = x  | 
 | 47 | +    )  | 
 | 48 | +  }  | 
 | 49 | + | 
 | 50 | +  # Allows us to track which panels are entering/exiting  | 
 | 51 | +  # (when input$displayed changes)  | 
 | 52 | +  displayed <- reactiveVal(LETTERS)  | 
 | 53 | + | 
 | 54 | +  output$accordion <- renderUI({  | 
 | 55 | +    displayed(LETTERS)  | 
 | 56 | + | 
 | 57 | +    accordion(  | 
 | 58 | +      id = "acc", multiple = input$multiple,  | 
 | 59 | +      !!!lapply(LETTERS, make_panel)  | 
 | 60 | +    )  | 
 | 61 | +  })  | 
 | 62 | + | 
 | 63 | +  observeEvent(input$selected, ignoreInit = TRUE, {  | 
 | 64 | +    accordion_panel_set("acc", input$selected)  | 
 | 65 | +  })  | 
 | 66 | + | 
 | 67 | +  observeEvent(input$acc, ignoreInit = TRUE, {  | 
 | 68 | +    updateSelectInput(inputId = "selected", selected = input$acc)  | 
 | 69 | +  })  | 
 | 70 | + | 
 | 71 | +  observeEvent(input$displayed, ignoreInit = TRUE, {  | 
 | 72 | +    exit <- setdiff(displayed(), input$displayed)  | 
 | 73 | +    enter <- setdiff(input$displayed, displayed())  | 
 | 74 | + | 
 | 75 | +    if (length(exit)) {  | 
 | 76 | +      accordion_panel_remove("acc", target = exit)  | 
 | 77 | +    }  | 
 | 78 | + | 
 | 79 | +    if (length(enter)) {  | 
 | 80 | +      lapply(enter, function(x) {  | 
 | 81 | +        panel <- make_panel(x)  | 
 | 82 | +        if (identical("A", x)) {  | 
 | 83 | + | 
 | 84 | +          # Can always be inserted at the top (no target required)  | 
 | 85 | +          accordion_panel_insert("acc", panel = panel, position = "before")  | 
 | 86 | + | 
 | 87 | +        } else {  | 
 | 88 | + | 
 | 89 | +          # Other letters require us to find the closest _currently displayed_  | 
 | 90 | +          # letter (to insert after)  | 
 | 91 | +          idx_displayed <- which(LETTERS %in% displayed())  | 
 | 92 | +          idx_insert <- match(x, LETTERS)  | 
 | 93 | +          idx_diff <- idx_insert - idx_displayed  | 
 | 94 | +          idx_diff[idx_diff < 0] <- NA  | 
 | 95 | +          target <- LETTERS[idx_displayed[which.min(idx_diff)]]  | 
 | 96 | +          accordion_panel_insert("acc", panel = panel, target = target, position = "after")  | 
 | 97 | + | 
 | 98 | +        }  | 
 | 99 | + | 
 | 100 | +        displayed(c(x, displayed()))  | 
 | 101 | +      })  | 
 | 102 | + | 
 | 103 | +      if (input$open_on_insert) {  | 
 | 104 | +        accordion_panel_open("acc", enter)  | 
 | 105 | +      }  | 
 | 106 | +    }  | 
 | 107 | + | 
 | 108 | +    displayed(input$displayed)  | 
 | 109 | +  })  | 
 | 110 | + | 
 | 111 | +  observeEvent(displayed(), ignoreInit = TRUE, {  | 
 | 112 | +    updateSelectInput(inputId = "displayed", selected = displayed())  | 
 | 113 | +    updateSelectInput(  | 
 | 114 | +      inputId = "selected", choices = displayed(),  | 
 | 115 | +      selected = input$selected  | 
 | 116 | +    )  | 
 | 117 | +  })  | 
 | 118 | + | 
 | 119 | +}  | 
 | 120 | + | 
 | 121 | +shinyApp(ui, server)  | 
0 commit comments