The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.
Call useGlassTabs() once somewhere in your UI before
using any widget.
glassPage() is the experimental exception. It is a thin
wrapper around bslib::page_fillable() and loads the
dependency itself.
The key rule: use ns() in the UI, use the
bare id in the server.
# UI function
my_ui <- function(id) {
ns <- NS(id)
tagList(
useGlassTabs(),
glassTabsUI(
ns("tabs"), # ns() wraps the id in the UI
glassTabPanel("summary", "Summary", selected = TRUE, h3("Summary")),
glassTabPanel("detail", "Detail", h3("Detail"))
)
)
}
# Server function
my_server <- function(id) {
moduleServer(id, function(input, output, session) {
active <- glassTabsServer("tabs") # bare id — no ns() here
observeEvent(active(), {
message("Active tab: ", active())
})
})
}
# App
ui <- fluidPage(my_ui("explorer"))
server <- function(input, output, session) my_server("explorer")
if (interactive()) shinyApp(ui, server)# Build panels from data
tab_defs <- list(
list(value = "revenue", label = "Revenue"),
list(value = "orders", label = "Orders"),
list(value = "returns", label = "Returns")
)
panels <- lapply(tab_defs, function(t) {
glassTabPanel(t$value, t$label, h3(t$label))
})
ui <- fluidPage(
useGlassTabs(),
do.call(glassTabsUI, c(list("metrics", selected = "orders"), panels))
)
server <- function(input, output, session) {
active <- glassTabsServer("metrics")
}Note: tab
valuestrings must be unique —glassTabsUI()will error on duplicates. Values are plain strings; they do not need to match labels.
# Switch active tab
updateGlassTabsUI(session, "main", "details")
# Hide or show a tab
hideGlassTab(session, "main", "admin")
showGlassTab(session, "main", "admin")
# Append or remove a tab at runtime
appendGlassTab(
session, "main",
glassTabPanel("compare", "Compare", h3("Compare")),
select = TRUE
)
removeGlassTab(session, "main", "compare")glassTabsUI(
"main",
glassTabPanel("a", "A", selected = TRUE, p("A")),
glassTabPanel("b", "B", p("B")),
selected = "a",
wrap = TRUE,
compact = FALSE, # set TRUE inside dashboard cards for tighter layout
content_min_height = NULL, # default: 120px (60px when compact = TRUE); "0" for no minimum
extra_ui = tags$div("Right side UI"),
theme = "light"
)Use compact = TRUE when embedding glasstabs inside a
tight layout such as a bs4Dash::bs4Card(). It reduces
margins, padding, and font size so the widget does not overflow the
card.
The active tab and its content are visually linked automatically: the
active tab carries a subtle inner light on its content-facing edge
(bottom for horizontal tabs, the rail side for vertical, RTL-aware) in
the halo color, and the content box’s top edge picks up the same color
to bridge the gap. The underline indicator keeps its own
connection cue instead. No parameters needed - to restyle the link,
theme halo_border via glass_tab_theme().
Use style = "attached" for a single unified card where
the tab bar docks onto the content box, and
transition = "slide" for directional pane movement that
follows tab order.
glassMultiSelect(
"metric",
choices,
selected = unname(choices),
label = "Metrics",
placeholder = "Choose metrics",
all_label = "All metrics",
check_style = "checkbox",
show_style_switcher = TRUE,
show_select_all = TRUE,
show_clear_all = TRUE,
searchable = "auto",
search_threshold = 12,
selection_display = "summary",
selection_max_items = 2,
dropdown_max_height = "18rem",
width = "240px",
tongue = TRUE,
label_bold = TRUE,
label_size = "14px",
search_focus_ring = FALSE,
overflow_tooltip = "auto",
fill_colors = "single",
theme = "dark",
no_matches_text = "No matches"
)glassSelect(
"region",
regions,
selected = "all",
label = "Region",
placeholder = "Pick a region",
searchable = "auto",
search_threshold = 6,
clearable = TRUE,
include_all = FALSE,
check_style = "checkbox",
width = "240px",
tongue = TRUE,
label_bold = TRUE,
label_size = "14px",
search_focus_ring = FALSE,
overflow_tooltip = "auto",
theme = "light",
no_matches_text = "No matches"
)For glassSelect(), the overflow tooltip appears for an
ellipsized trigger. Inside either open dropdown, it appears for the
truncated option currently hovered or reached with the keyboard; the
multi-select trigger does not combine selected labels into a tooltip. On
touch, wrapped option text is the full-text fallback. Use
overflow_tooltip = "never" to disable visual tips.
glassTabsUI() works inside
bs4Dash::tabItem(). Place useGlassTabs() in
the dashboardBody() (or anywhere before the first widget —
once is enough).
library(shiny)
library(bs4Dash)
ui <- bs4DashPage(
header = bs4DashNavbar(),
sidebar = bs4DashSidebar(
bs4SidebarMenu(
bs4SidebarMenuItem("Explorer", tabName = "explorer", icon = icon("table"))
)
),
body = bs4DashBody(
useGlassTabs(), # place once, anywhere in the body
bs4TabItems(
bs4TabItem(
tabName = "explorer",
bs4Card(
title = "Data explorer",
width = 12,
glassTabsUI(
"s3_tabs",
glassTabPanel("buckets", "Buckets", selected = TRUE,
p("List of S3 buckets here.")
),
glassTabPanel("objects", "Objects",
p("Object browser here.")
),
glassTabPanel("preview", "Preview",
p("File preview here.")
)
)
)
)
)
)
)
server <- function(input, output, session) {
active <- glassTabsServer("s3_tabs")
}
if (interactive()) shinyApp(ui, server)
useGlassTabs()only needs to appear once. Inside a module that renders into a bs4Dash layout, call it in your module’s UI function.
| Widget | Server value |
|---|---|
glassTabsUI("main", ...) |
input[["main-active_tab"]] or
glassTabsServer("main")() |
glassMultiSelect("metric", ...) |
input$metric or
glassMultiSelectValue(input, "metric")$selected() |
| resolved multi-select value | glassMultiSelectValue(..., empty_behavior = "all")$resolved() |
| multi-select style | input$metric_style or
glassMultiSelectValue(input, "metric")$style() |
| select open state | input$metric_open / input$region_open |
glassSelect("region", ...) |
input$region or
glassSelectValue(input, "region")() |
Use glassTabCondition() to avoid constructing the input
key manually:
# Instead of: condition = "input['main-active_tab'] === 'details'"
conditionalPanel(
condition = glassTabCondition("main", "details"),
p("Only visible on the Details tab.")
)
# Inside a module — pass the same id as glassTabsUI():
# glassTabsUI(ns("tabs"), ...)
conditionalPanel(
condition = glassTabCondition(NS("mymod")("tabs"), "details"),
p("Only visible on the Details tab.")
)useGlassTabs() must be called once in the UI.ns("tabs") in the UI but pass the bare
"tabs" to glassTabsServer() — not
ns("tabs"). Passing a namespaced id (containing
-) will produce a warning with a suggested fix.glassTabPanel() values must be unique within a
glassTabsUI() call — duplicates cause an error naming the
offending value.selected in glassTabsUI() refers to the
tab value, not the label.glassSelectValue() returns a reactive function, not a
list.glassMultiSelectValue() returns raw
selected(), resolved(),
is_empty(), and style() reactives.glassMultiSelect(), selected should
use choice values, not labels.compact = TRUE inside bs4Dash cards or any tight
layout to reduce widget spacing.load_all() before retesting.That is the whole working model: load the dependency once, compose widgets in the UI, and read their values through ordinary Shiny inputs.
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.