knitr::opts_chunk$set(eval = FALSE)
glassSelect() is an animated single-select dropdown for Shiny.
It behaves like a standard Shiny input:
input$<inputId> stores the selected value as a single character string,
or NULL when nothing is selected.
It supports:
glass_select_theme()check_styleupdateGlassSelect()closeGlassSelect() and input$<inputId>_openlibrary(shiny) library(glasstabs) fruits <- c( Apple = "apple", Banana = "banana", Cherry = "cherry", Mango = "mango" ) ui <- fluidPage( useGlassTabs(), glassSelect("pick", fruits), verbatimTextOutput("out") ) server <- function(input, output, session) { output$out <- renderPrint(input$pick) } if (interactive()) shinyApp(ui, server)
# No selection (default) glassSelect("f", fruits) # Pre-select one value glassSelect("f", fruits, selected = "banana")
glassSelect("f", fruits, label = "Choose a fruit")
glassSelect() supports three selection marker styles:
"checkbox" (default)"check-only""filled"glassSelect("f1", fruits, check_style = "checkbox") glassSelect("f2", fruits, check_style = "check-only") glassSelect("f3", fruits, check_style = "filled")
By default the trigger and dropdown use the signature rounded glass corners.
Pass shape = "square" for crisp, selectize-style corners so the widget sits
flush next to native selectizeInput() controls without looking out of place:
# Rounded (default) glassSelect("region_rounded", fruits, shape = "rounded") # Square - matches selectizeInput() glassSelect("region_square", fruits, shape = "square")
The shape can also be switched at runtime with
updateGlassSelect(session, "region_square", shape = "square"). Here is the
complete side-by-side layout with a native Shiny control:
fluidRow( column( 6, selectizeInput("native_region", "Native", choices = fruits) ), column( 6, glassSelect( "glass_region", fruits, label = "glasstabs", shape = "square", width = "100%" ) ) )
For parity with native selectizeInput(), glassSelect() accepts a width,
grouped choices as a named list, and disabled state:
# Fixed / fluid width glassSelect("region_w", fruits, width = "240px") # Grouped choices (selectInput()-style named list) glassSelect("food", list( Fruit = c(Apple = "apple", Banana = "banana"), Veg = c(Carrot = "carrot", Pea = "pea") )) # Disable the whole widget, or specific options glassSelect("region_d", fruits, disabled = TRUE) glassSelect("region_dc", fruits, disabled_choices = "banana")
disabled and disabled_choices can also be toggled at runtime with
updateGlassSelect().
For dynamic layouts, modals, sidebars, or tab changes, you can explicitly close an open dropdown from the server:
observeEvent(input$change_layout, { closeGlassSelect(session, "pick") })
The widget also reports whether its dropdown is open:
observe({ message("Dropdown open: ", isTRUE(input$pick_open)) })
closeAllGlassSelects(session) closes every open glasstabs select dropdown in
the current session.
Search is enabled by default. You can also enable a clear control.
glassSelect( "f", fruits, searchable = TRUE, clearable = TRUE )
To hide the search box:
glassSelect( "f", fruits, searchable = FALSE )
For hundreds or thousands of choices, set server = TRUE in the UI and
register glassSelectServer() in the server function. The browser renders
only an initial slice of choices and asks Shiny for matching choices as
the user types.
many_choices <- stats::setNames( sprintf("value-%04d", 1:2000), sprintf("Choice %04d", 1:2000) ) ui <- fluidPage( useGlassTabs(), glassSelect( "pick", many_choices, selected = "value-1500", clearable = TRUE, server = TRUE, server_limit = 30 ), verbatimTextOutput("out") ) server <- function(input, output, session) { glassSelectServer("pick", many_choices, session = session, limit = 30) output$out <- renderPrint(input$pick) } if (interactive()) shinyApp(ui, server)
This pattern also works when the control is created dynamically with
renderUI(). Keep the glassSelectServer() call in the server function
for the same inputId.
You can prepend an explicit "All" option:
glassSelect( "f", fruits, include_all = TRUE, all_choice_label = "All fruits", all_choice_value = "__all__" )
This is useful when you want the UI to distinguish between: - no selection - a deliberate "All" selection
Read the current value directly from input$<inputId>:
server <- function(input, output, session) { observe({ message("Selected: ", if (is.null(input$pick)) "NULL" else input$pick) }) }
If you want a small convenience wrapper, use glassSelectValue():
server <- function(input, output, session) { pick <- glassSelectValue(input, "pick") observe({ print(pick()) }) }
updateGlassSelect() can update:
- available choices
- current selection
- selection marker style
observeEvent(input$filled, { updateGlassSelect( session, "pick", check_style = "filled" ) })
It follows Shiny-style update semantics:
choices = NULL leaves choices unchangedselected = NULL leaves selection unchangedselected = character(0) clears the selectionui <- fluidPage( useGlassTabs(), actionButton("subset", "Keep first 2 fruits"), actionButton("banana", "Select banana"), actionButton("clear", "Clear"), actionButton("filled", "Use filled style"), glassSelect("pick", fruits, clearable = TRUE), verbatimTextOutput("out") ) server <- function(input, output, session) { output$out <- renderPrint(input$pick) observeEvent(input$subset, { updateGlassSelect( session, "pick", choices = fruits[1:2] ) }) observeEvent(input$banana, { updateGlassSelect( session, "pick", selected = "banana" ) }) observeEvent(input$clear, { updateGlassSelect( session, "pick", selected = character(0) ) }) } if (interactive()) shinyApp(ui, server)
When choices is updated without selected, the widget keeps the
current value if it still exists in the new set of choices.
glassSelect("f", fruits, theme = "dark") glassSelect("f", fruits, theme = "light") glassSelect("f", fruits, theme = "auto")
Use theme = "auto" inside Bootstrap 5 / bslib apps to follow
data-bs-theme light and dark modes without server code.
glass_select_theme()glassSelect( "f", fruits, theme = glass_select_theme( mode = "dark", accent_color = "#f59e0b" ) ) glassSelect( "f", fruits, theme = glass_select_theme( bg_color = "#1a0a2e", border_color = "#a855f7", text_color = "#ede9fe", accent_color = "#a855f7" ) ) #other themes glassSelect( "f", fruits, theme = glass_select_theme( mode = "light", accent_color = "#2563eb" ) ) #more themes glassSelect( "f", fruits, theme = glass_select_theme( mode = "light", bg_color = "#ffffff", border_color = "rgba(0,0,0,0.15)", text_color = "#111111", accent_color = "#111111", label_color = "#111111" ) )
glassSelect() can be used without the tab widget. You only need
useGlassTabs() to load the package CSS and JavaScript assets:
ui <- fluidPage( useGlassTabs(), glassSelect("region", c(North = "North", South = "South", East = "East")), verbatimTextOutput("out") ) server <- function(input, output, session) { output$out <- renderPrint(input$region) } if (interactive()) shinyApp(ui, server)
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.