Reusable liquid glass UI kit for Windows Tauri apps. Two halves in one repo:
src/+styles.css+fonts/— the npm package: React components that render native GPU liquid glass surfaces behind the DOM (via theliquid-glasscrate), the Tauri invoke bridge they speak, and the shared glass design system (SF Pro Display, menu, modal and glass-shape styles).native/— the Rust crateglass-ui:MenuGlassManager, the menu-glass machinery (per-key glass surfaces, warm recycle pool, grouped reveals, scale spring, hit rects, reconciliation sweep) plus optional Tauri command wrappers behind thetaurifeature.
Then in the app root:
import "glass-ui/styles.css";
import { GlassCard, LiquidDropdown } from "glass-ui";styles.css owns the SF Pro Display @font-face rules (font URLs resolve
inside the package) plus the base transparent-document styles, the menu,
modal and glass-shape classes. Apps bring their own layout CSS.
# src-tauri/Cargo.toml — while iterating locally (sibling checkout):
glass-ui = { path = "../glass-ui/native", features = ["tauri"] }
# standalone (git dep, tracks main):
glass-ui = { git = "https://github.com/alphamerics/glass-ui", features = ["tauri"] }And wire it up:
use glass_ui::{commands, MenuGlassManager};
tauri::Builder::default()
.manage(MenuGlassManager::new())
.invoke_handler(tauri::generate_handler![
commands::set_ui_hit_rects,
commands::prewarm_menu_glass,
commands::position_menu_glass,
commands::sync_menu_glasses,
commands::log_message,
])
// optional: grouped surfaces emit when the whole group is warm, so the
// web UI can fade its content in with the glass.
.setup(|app| {
app.state::<MenuGlassManager>()
.set_group_emitter(|| { /* e.g. app.emit("glass-group-ready", ()) */ });
Ok(())
})Every app that renders liquid glass needs all of the following, or the glass will be wrong (refracting its own DOM, mis-scaled, or absent):
-
Transparent, decorationless overlay window — in
tauri.conf.json:transparent: true,decorations: false,backgroundColor: "#00000000",shadow: false. -
--force-device-scale-factor=1in the window'sadditionalBrowserArgs(the kit pushes rects in physical px; a DPI-scaled DOM would misplace every surface). Recommended alongside:--disable-features=msWebOOUI,msPdfOOUI,msSmartScreenProtection,CalculateNativeWinOcclusion. -
Exclude the web UI from the glass's own capture — at startup:
SetWindowDisplayAffinity(hwnd, WDA_EXCLUDEFROMCAPTURE), and setWS_EX_LAYEREDon the window (what lets cross-thread click-through work for shell overlays). -
Ship
glass-broker.exebeside the app executable — the broker bin must exist next to the app at runtime. Apps that embed their own broker trampoline as a[[bin]]target get it for free: Tauri automatically bundles every bin target beside the executable (build it first inbeforeDevCommand/beforeBuildCommand, like Glassbar does). Apps consuming the library differently bundle it explicitly:"bundle": { "resources": { "target/release/glass-broker.exe": "glass-broker.exe" } }
The glass pipeline auto-spawns the broker (session-wide singleton; many glass apps share one).
-
Full-screen click-through shells only: push interactive-element rects via
set_ui_hit_rectsand run a hit-test loop that makes the overlay click-through everywhere else. Normal (non-shell) apps skip this.
The crates are git-based now. native/Cargo.toml depends on
liquid-glass = { git = "https://github.com/alphamerics/liquid-glass" } —
there is deliberately NO [patch] committed here: a git-fetched package
cannot resolve path dependencies outside its own checkout, so a patch in
this manifest would break every crate consuming glass-ui from GitHub.
Live local iteration lives in the consuming app instead (glassbar is an app, never a dependency, so committing patches there is safe):
# glassbar/src-tauri/Cargo.toml
[dependencies]
liquid-glass = { git = "https://github.com/alphamerics/liquid-glass" }
glass-ui = { git = "https://github.com/alphamerics/glass-ui", features = ["tauri"] }
# redirect both to the sibling checkouts so edits apply instantly:
[patch."https://github.com/alphamerics/liquid-glass"]
liquid-glass = { path = "../../liquid-glass" }
[patch."https://github.com/alphamerics/glass-ui"]
glass-ui = { path = "../../glass-ui/native" }Working with a Rust liquid-glass copy that is NOT tracked main (e.g. local
edits ahead of a push): glassbar's committed patches already route around
this — the patched path is used instead of the fetched repo.
If the GitHub repos are private, cargo's built-in fetch cannot use your credential helper by itself; enable the CLI fallback once per machine:
# ~/.cargo/config.toml
[net]
git-fetch-with-cli = trueThe npm package stays on the sibling file: dep (glassbar's choice): instant
edits, no link step. A standalone consumer switches package.json to
github:alphamerics/glass-ui#v0.1.0 as shown above.
The npm package needs no build step in git-dep mode: package.json has a
prepare script pattern (tsc emit is unnecessary — apps consume the TS
source through their own bundler; main/types point at src/index.ts).