editor_options: markdown: wrap: 72 —
Animated tabs and select inputs that feel at home in a Shiny app.
glasstabs gives Shiny apps polished navigation and filtering without asking you to write custom JavaScript or CSS. The package includes:
glassTabsUI() for animated horizontal or vertical tab
navigationglassSelect() for a searchable single-select inputglassMultiSelect() for multi-select filters with
optional tag pillsThe widgets work in a regular fluidPage(), a
bslib app, or a bs4Dash dashboard. Each one
can use a dark, light, automatic, or custom colour theme.
Install the CRAN release:
install.packages("glasstabs")Or install the development version from GitHub:
pak::pak("prigasG/glasstabs")Call useGlassTabs() once in the UI, then compose the
widgets like ordinary Shiny controls. This app places a filter beside
two tabs and displays the current tab and selection.
library(shiny)
library(glasstabs)
choices <- c(Apple = "apple", Banana = "banana", Cherry = "cherry")
ui <- fluidPage(
useGlassTabs(),
glassTabsUI(
"main",
glassTabPanel(
"overview", "Overview", selected = TRUE,
h3("Fruit summary"),
glassFilterTags("fruit")
),
glassTabPanel(
"details", "Details",
h3("Selection details"),
verbatimTextOutput("selection")
),
extra_ui = glassMultiSelect(
"fruit",
choices,
show_style_switcher = FALSE
)
),
verbatimTextOutput("active_tab")
)
server <- function(input, output, session) {
active_tab <- glassTabsServer("main")
output$active_tab <- renderPrint(active_tab())
output$selection <- renderPrint(input$fruit)
}
if (interactive()) {
shinyApp(ui, server)
}glassMultiSelect() selects every choice by default. Use
selected = character(0) when the filter should start
empty.
Tabs are made from glassTabPanel() objects. The first
selected panel is shown when the app opens.
glassTabsUI(
"reports",
glassTabPanel("summary", "Summary", selected = TRUE, summary_ui),
glassTabPanel("table", "Table", tableOutput("results")),
glassTabPanel("notes", "Notes", textAreaInput("notes", NULL))
)A single-select behaves like a standard Shiny input. Its value is
available at input$region.
glassSelect(
"region",
c(North = "north", South = "south", East = "east", West = "west"),
label = "Region",
clearable = TRUE
)A multi-select returns a character vector and can display the selected values as tag pills anywhere in the UI.
glassMultiSelect(
"status",
c(Open = "open", Review = "review", Closed = "closed"),
selected = c("open", "review"),
label = "Status"
)
glassFilterTags("status")Use theme = "auto" in Bootstrap 5 or bslib
apps so the widgets follow the page’s light and dark modes. Use
shape = "square" when the controls sit next to native Shiny
inputs.
glassTabsUI(
"nav",
glassTabPanel("one", "One", selected = TRUE, p("First panel")),
glassTabPanel("two", "Two", p("Second panel")),
indicator = "underline",
theme = "auto"
)
glassSelect("region", choices, shape = "square", theme = "auto")
glassMultiSelect("filters", choices, shape = "square", theme = "auto")Tabs also support a vertical rail and three indicator styles:
glassTabsUI(
"workflow",
glassTabPanel("intake", "Intake", selected = TRUE, intake_ui),
glassTabPanel("review", "Review", review_ui),
glassTabPanel("approve", "Approve", approve_ui),
orientation = "vertical",
indicator = "solid",
tab_align = "left"
)For a custom accent, change only the fields your app needs:
glassTabsUI(
"nav",
glassTabPanel("a", "A", selected = TRUE, p("Content")),
glassTabPanel("b", "B", p("More content")),
theme = glass_tab_theme(
halo_bg = "rgba(37, 99, 235, 0.16)",
halo_border = "#2563eb"
)
)
glassSelect(
"region",
choices,
theme = glass_select_theme(mode = "light", accent_color = "#2563eb")
)Inside a bs4Dash card, compact = TRUE
reduces spacing and wrap = FALSE lets the card provide the
outer container.
bs4Dash::box(
width = 12,
glasstabs::glassTabsUI(
"dashboard",
glassTabPanel("summary", "Summary", selected = TRUE, summary_ui),
glassTabPanel("detail", "Detail", detail_ui),
compact = TRUE,
wrap = FALSE,
theme = "light"
)
)The widgets expose familiar Shiny inputs:
| Widget | Current value |
|---|---|
glassTabsUI("main", ...) |
input[["main-active_tab"]] |
glassSelect("region", ...) |
input$region |
glassMultiSelect("status", ...) |
input$status |
| An open select dropdown | input$region_open or
input$status_open |
Server helpers cover common programmatic changes:
server <- function(input, output, session) {
observeEvent(input$next_step, {
updateGlassTabsUI(session, "workflow", selected = "review")
updateGlassTabBadge(session, "workflow", "review", count = 3)
})
observeEvent(input$reset_filters, {
updateGlassSelect(session, "region", selected = character(0))
updateGlassMultiSelect(session, "status", selected = character(0))
})
}Use glassTabCondition() when a regular
conditionalPanel() should follow the active glass tab:
conditionalPanel(
condition = glassTabCondition("main", "details"),
p("This appears while the Details tab is active.")
)For hundreds or thousands of choices, keep the full vector on the server and send a small page of matches to the browser.
many_choices <- stats::setNames(
sprintf("value-%04d", 1:2000),
sprintf("Choice %04d", 1:2000)
)
ui <- fluidPage(
useGlassTabs(),
glassSelect("item", many_choices, server = TRUE, server_limit = 30),
glassMultiSelect("filters", many_choices, server = TRUE, server_limit = 30)
)
server <- function(input, output, session) {
glassSelectServer("item", many_choices, session = session, limit = 30)
glassMultiSelectServer("filters", many_choices, session = session, limit = 30)
}| Function | Description |
|---|---|
useGlassTabs() |
Inject package CSS and JavaScript—call once in the UI |
runGlassExample(example) |
Launch a built-in example app (runGlassExample() lists
all available apps) |
glasstabs_news() |
Print the package changelog to the R console |
Built-in examples include basic, bs4dash,
bslib, connect-workflow,
dashboard, indicators,
server-select, smoke-test, and
square-corners.
| Function | Description |
|---|---|
glassTabsUI(id, ..., selected, wrap, compact, shape, indicator, orientation, tab_align, extra_ui, theme) |
Animated tab bar with content area; use compact = TRUE
for dashboard cards |
glassTabPanel(value, label, ..., icon, selected) |
Define one tab and its content; icon accepts
shiny::icon() |
glassTabsServer(id, bookmark) |
Reactive returning the active tab; can bookmark the active tab in the URL |
glassTabsOutput(outputId) |
UI placeholder for a server-rendered tab widget |
renderGlassTabs({expr}) |
Render a glassTabsUI() reactively; JavaScript
reinitialises automatically |
glassTabCondition(id, value) |
JavaScript condition string for conditionalPanel() |
updateGlassTabsUI(session, id, selected) |
Switch the active tab from the server |
updateGlassTabBadge(session, id, value, count) |
Set a numeric badge on a tab button (0 hides it) |
showGlassTab(session, id, value) |
Show a hidden tab |
hideGlassTab(session, id, value) |
Hide a tab from the navigation bar |
disableGlassTab(session, id, value) |
Disable a tab while keeping it visible |
enableGlassTab(session, id, value) |
Re-enable a disabled tab |
appendGlassTab(session, id, tab, select) |
Add a new tab at runtime |
removeGlassTab(session, id, value) |
Remove a tab at runtime |
glass_tab_theme(...) |
Create a custom colour theme for glassTabsUI() |
| Function | Description |
|---|---|
glassMultiSelect(inputId, choices, ...) |
Multi-select dropdown widget |
glassMultiSelectServer(inputId, choices, ...) |
Server-side search for large multi-select choice sets |
updateGlassMultiSelect(session, inputId, ...) |
Update multi-select choices, selection, or style |
glassMultiSelectValue(input, inputId) |
Reactive helpers for multi-select value and style |
glassSelect(inputId, choices, ...) |
Single-select dropdown widget |
glassSelectServer(inputId, choices, ...) |
Server-side search for large single-select choice sets |
updateGlassSelect(session, inputId, ...) |
Update single-select choices, selection, or style |
glassSelectValue(input, inputId) |
Reactive helper for the selected value |
closeGlassSelect(session, inputId) |
Close one open single-select dropdown |
closeGlassMultiSelect(session, inputId) |
Close one open multi-select dropdown |
closeAllGlassSelects(session) |
Close every open glasstabs select dropdown |
glassFilterTags(inputId) |
Tag-pill display area synced to a multi-select |
glass_select_theme(...) |
Create a custom theme for glassSelect() and
glassMultiSelect() |
| Input | Type | Description |
|---|---|---|
input[["<id>-active_tab"]] |
character |
Active tab value from glassTabsUI() |
input$<inputId> |
character vector |
Selected values from glassMultiSelect() |
input$<inputId>_style |
character |
Active selection style from glassMultiSelect() |
input$<inputId>_open |
logical |
Whether a select dropdown is open |
input$<inputId> |
character or NULL |
Selected value from glassSelect() |
The glasstabs
website includes focused articles and a searchable function
reference. Release notes are available in NEWS.md or from R with
glasstabs_news().
If a widget does not fit naturally into your app, please open a GitHub issue with a small Shiny example. Questions, bug reports, and ideas for making the package easier to use are all welcome.