[data-glass-preset].
Switching preset no longer requires recompiling Sass or reloading the
page. Apps that overrode Sass-only $glass-* tokens should
target --glass-* CSS variables (or
[data-glass-preset="dark"]) instead.glass_theme() always builds on the Bootstrap 5 base
theme (not Bootswatch darkly for dark). Dark appearance
comes from the CSS variable pack so light↔︎dark can toggle live. Visuals
should match 0.1.x closely; if you relied on darkly-specific chrome
outside glass surfaces, re-check dark mode.window.__shinyglassDisableTint
still works, but the supported API is
glass_theme(tint = FALSE) /
update_glass_theme(tint = …).Light / Dark / Auto is an iOS-style segmented control: theme-aware glass thumb (changes in light vs dark), body ink on every chip, and a delegated click so Auto applies even when host pages rewrite inline handlers.
Theme toggle applies the preset once (no inline handler + server echo storm), so plots no longer flicker when switching Light / Dark.
Default actionButton() / .btn-link ink
follows theme tokens (--glass-body-color /
--glass-accent) instead of compiled
$primary.
[glass_resolved_preset()] reports the resolved light/dark appearance so plots do not stay light-inked when the user picks Auto.
Dark pack no longer re-locks default / outline / download labels
to compiled $primary. Download links and ghost focus rings
follow --glass-accent. Accent
<select id="accent"> applies setPrimary
immediately.
[glass_intensity_slider()] / [observe_glass_intensity()] — iOS
27-style Ultra Clear → Tinted control.
glass_theme(intensity = ) sets the starting value
(0–1, default 0.45);
[update_glass_theme()] and window.shinyglass.setIntensity()
update it live.
[glass_preset_input()] / [observe_glass_preset_input()] —
client-first Light/Dark/Auto select (applies setPreset
immediately; server sync is optional). Prefer this over a bare
selectInput() + update_glass_theme() alone on
hosts that rewrite custom messages.
Theme delivery is dual-channel (shinyglass + legacy
glassPreset) with a self-healing
oncustommessage proxy so preset/intensity/showModal survive
host message rewrites (e.g. shinyapps.io).
Demo app intensity-slider-demo.R; live shinyglass-demo
and shinyglass-dashboard
ship glass_intensity_slider() in the UI.
iOS 27 material polish: stronger darkened edges, brighter specular highlights, intensity-scaled fill/blur for clearer layer separation and readability.
Dark-mode nav tab ink keeps WCAG UI 3:1 on glass (inactive tabs).
Closer iOS 27 Liquid Glass: defined borders (not shadow-only),
chromatic edge refraction cues, lighter dark-mode glass, thicker
elevated chrome, ambient specular drift + pointer override, stronger
diffusion blur defaults (blur = 36,
saturation = 200).
Runtime light/dark switching via
document.documentElement.dataset.glassPreset without a full
reload.
glass_theme(preset = "auto") follows
prefers-color-scheme and updates when the OS theme
changes.
[update_glass_theme()] to change preset,
tint, and primary (live
accent via --glass-accent / --bs-primary) from
the server. Recolors primary buttons, Shiny checkboxInput()
/ radios / switches, ion.rangeSlider bars, value chips, and active
nav/list items without a Sass recompile.
[glass_theme_toggle()] / [observe_glass_theme_toggle()] drop-in Light / Dark / Auto buttons.
Behavior knobs on [glass_theme()]: tint,
specular, and nav_morph (all default
TRUE, matching 0.1.x JS behavior).
Client helpers: window.shinyglass.setPreset() /
.getPreset() / .setTint() /
.setPrimary() / .getPrimary().
Liquid Glass material fidelity (Tahoe / iOS 26 inspired): multi-layer surfaces (illumination fill, dual-edge rim/lip, ambient + pointer specular), chrome vs content hierarchy (less glass-on-glass), softer wallpaper orbs, larger concentric radii, capsule-leaning controls.
New glass_theme(material = "regular"|"clear"). Clear
is more transparent for media-rich layouts. Defaults:
blur = 36, radius = "1.5rem",
saturation = 200.
Value boxes are tinted glass (theme-color wash + body ink), not
solid .bg-* slabs. Plots and DT/gt hosts inside cards drop
the extra glass frame so page orbs show through
(renderPlot(bg = "transparent") in bundled demos).
DataTables / Bootstrap pagination chips: style the visible
.page-link surface (DT uses
<li.paginate_button><a.page-link>). Fixes solid
black page numbers and light-grey ellipsis chips in dark mode on the
dashboard demo / README screenshots.
Overlay chrome (datepicker popup, Shiny notification types,
generic accordion, Bootstrap tooltip/popover/toast,
.btn-close, file Browse chip) now uses the glass menu pack
so dark mode is not leftover Bootstrap light hex. Datepicker is hoisted
to document.body (Shiny 1.14 bsDatepicker) so
card/navbar backdrop-filter no longer clips the calendar.
Navbar overflow is visible so nav_menu dropdowns escape the
glass bar. Kitchen-sink example: chrome-kitchen-sink.R
(page_navbar, nav_menu,
showModal(), all four showNotification()
types).
Visual QA harness:
inst/scripts/audit-glass-contrast.R (+ .js)
runs a dual-theme computed-style audit (low contrast, solid-black chips,
Bootstrap light greys in dark, dark ink on accent, DT pagination
structure) across demo / dashboard / inputs-gallery / chrome
kitchen-sink. Opens datepicker, navbar menu, notifications, accordion,
tooltip/popover, and server modal before sampling. Checklist and
definition of done in inst/scripts/VISUAL-QA.md.
Selectize fields: force body/menu ink on inputs and multi-select
tags (selectize default near-black item text failed dark mode); opaque
--glass-menu-bg fills in dark; dropdown options use menu
colors.
Ecosystem chrome: plotly modebar + frame,
gt tables, waiter / shinybusy
overlays, shinyalert/SweetAlert2 popups, denser
shinydashboardPlus controlbar/dropdowns/user menu,
light rhandsontable / echarts/highcharter hosts.
Examples: plotly-gt-demo.R,
shinydashboardPlus-glass-demo.R.
Live demo shinyglass-plotly-gt; README light/dark screenshots for plotly+gt.
CI workflow visual-qa (testthat + dual-theme
contrast audit) and committed
inst/scripts/audit-baseline.json.
Navbar brand / page title ink uses
--glass-body-color (no more white brand on light glass).
Plotly hosts no longer clip x-axis titles.
Active-on-accent contrast: lower Bootstrap
$min-contrast-ratio to 3 so
color-contrast() picks white on brand blues/purples (white
on #007AFF is ~4.02:1 and failed the old 4.5 gate). Solid
.bg-* / .text-bg-* fills (including
bslib::value_box(theme=)) get luminance-based ink via
glass-on() / --glass-on-* — not body color on
solid primary. Safety nets remain for checks, radios, switches,
pagination, and list-group active.
Accent rules target Shiny markup
(.shiny-input-checkbox) as well as Bootstrap
.form-check-input.
Plot / image outputs get a softer glass frame (lighter nesting inside cards).
prefers-reduced-motion: reduce disables nav morph,
specular, tint sampling, and decorative transitions (JS + CSS).
Demo and bslib dashboard examples: theme toggle helper; dashboard
accent select calls
update_glass_theme(primary = …).
Vignettes cover migration, primary updates, toggle helper, and reduced motion.
Unit tests cover dual CSS packs, head script knobs, active-color
vars, and update_glass_theme() messaging.
shiny-glass.js no longer crashes when the script loads
in <head> before document.body
exists.bslib::sidebar() / page_sidebar()
layout no longer collapses to a full-width stack. Glass floating-sidebar
rules now win over bslib’s later
position/width cascade, and open sidebars
reserve space in main so value boxes and cards stay fully visible beside
the chrome (not under it).layout_sidebar() no longer double-floats.
Inner sidebars keep glass styling but use bslib’s in-flow grid so
content is not pushed into a large empty gutter beside a second absolute
panel.shinydashboard and
bs4Dash) gets stronger glass overlay — translucent
header/sidebar, soft-tinted value/info boxes, and clearer menu active
states — without breaking AdminLTE layout.glass_theme() returns a bslib theme with Liquid
Glass styling for shiny apps:
translucent surfaces, backdrop blur, soft depth, and system
typography.fluidPage(), navbarPage(),
bslib::page_sidebar(), and other page functions that accept
a bslib theme. Pass the theme via theme = glass_theme(), or
for teal apps
via options(teal.bs_theme = glass_theme()).