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"),
  plot_surface = c("clear", "opaque"),
  intensity = 0.45,
  tint = TRUE,
  specular = TRUE,
  nav_morph = TRUE,
  ambient_motion = TRUE,
  persist = FALSE,
  scene = c("default", "tahoe", "dusk", "mesh", "aurora", "harbor", "grove"),
  wallpaper = NULL,
  flatten = FALSE,
  tokens = NULL,
  ...
)

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).

plot_surface

"clear" (default) keeps plot/table hosts translucent so wallpaper shows through. "opaque" densifies .shiny-plot-output, plotly, gt, and DT hosts (~94% panel fill, readable ink) while leaving nav and controls on Liquid Glass. Also available as the CSS class .glass-plot-surface-opaque on a host or ancestor.

intensity

Liquid Glass intensity from 0 (Ultra Clear) to 1 (Tinted), matching iOS 27 Settings -> Appearance -> Liquid Glass. Default 0.45. The web cannot read the OS slider; use glass_intensity_slider() for the in-app 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).

ambient_motion

Animate the decorative ambient sheen. Set FALSE to keep static glass surfaces. OS reduced-motion settings take priority.

persist

Remember preset, intensity, accent, material, plot surface, and scene in localStorage for this app path. Default FALSE (opt in). glass_page() turns this on.

scene

Wallpaper scene id from glass_scenes() ("default", "tahoe", "dusk", "mesh", "aurora", "harbor", "grove").

wallpaper

Optional image URL painted as a frosted photo behind the glass (https, data URI, or site-relative path). Photos are blurred and washed so body ink stays above the contrast floor (see glass_css_tokens()).

flatten

TRUE starts in print/export flatten mode (no backdrop blur). See glass_flatten().

tokens

Named list of public CSS token overrides (see glass_css_tokens() / glass_add_tokens()).

...

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()
opaque <- glass_theme(
  plot_surface = "opaque",
  scene = "aurora",
  tokens = list(blur = "28px")
)

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)
}