Skip to contents

Create a bslib::bs_theme() styled with a Liquid Glass look: translucent surfaces, backdrop blur, soft depth, and system typography. Pass the result to theme = on fluidPage(), navbarPage(), bslib::page_sidebar(), or any other page function that accepts a bslib theme.

Usage

glass_theme(
  preset = c("light", "dark", "auto"),
  primary = "#007AFF",
  blur = 36,
  saturation = 200,
  radius = "1.5rem",
  material = c("regular", "clear"),
  intensity = 0.45,
  tint = TRUE,
  specular = TRUE,
  nav_morph = TRUE,
  ...
)

Arguments

preset

"light", "dark", or "auto". "auto" follows prefers-color-scheme and updates when the OS theme changes.

primary

Accent color for buttons, links, and focus rings. Defaults to system blue (#007AFF).

blur

Backdrop blur radius in pixels. Default 36 matches the iOS 27 diffusion-first material.

saturation

Backdrop saturation percentage.

radius

Default border radius for glass surfaces (CSS length). Prefer larger concentric radii (default 1.5rem).

material

"regular" (adaptive, most UI) or "clear" (more transparent; best over media-rich content with bold labels).

intensity

Liquid Glass intensity from 0 (Ultra Clear) to 1 (Tinted), matching iOS 27 Appearance -> Liquid Glass. Default 0.45. Use glass_intensity_slider() for a live control.

tint

Content-aware ambient tint from plots/images (JS).

specular

Pointer-driven specular highlight on glass surfaces (JS).

nav_morph

Compact navbar on scroll down; expand on scroll up (JS).

...

Additional arguments forwarded to bslib::bs_theme().

Value

A bslib::bs_theme() object suitable for 'shiny' page functions.

Details

Light and dark surface tokens are compiled into dual CSS custom-property packs. Switching preset at runtime (via update_glass_theme() or preset = "auto") updates document.documentElement.dataset.glassPreset without recompiling Sass or reloading the page. Accent color can also be updated live with update_glass_theme() primary= (CSS variables).

Examples

theme <- glass_theme()
dark <- glass_theme(preset = "dark", primary = "#BF5AF2")
auto <- glass_theme(preset = "auto", tint = FALSE)
clear <- glass_theme(material = "clear")

if (interactive()) {
  library(shiny)

  ui <- fluidPage(
    theme = glass_theme(preset = "auto"),
    titlePanel("Liquid Glass"),
    glass_theme_toggle(),
    selectInput("color", "Color", c("Blue", "Purple", "Orange")),
    plotOutput("plot")
  )

  server <- function(input, output, session) {
    # Client onclick already switches; keep session in sync:
    observe_glass_theme_toggle(input, session)
  }

  shinyApp(ui, server)
}