Skip to content

Meridius-Labs/electron-liquid-glass

Repository files navigation

electron-liquid-glass

image

npm npm downloads GitHub Platform Node

Modern macOS glass effects for Electron applications

πŸͺ„ NATIVE NSGlassEffectView integration with ZERO CSS hacks

Installation β€’ Quick Start β€’ API β€’ Examples β€’ Contributing


✨ Features

  • πŸͺŸ Native Glass Effects - Real NSGlassEffectView integration, not CSS approximations
  • ⚑ Zero Configuration - Works out of the box with any Electron app
  • 🎨 Fully Customizable - Corner radius, tint colors, and glass variants
  • πŸ“¦ Modern Package - Dual ESM/CommonJS support with TypeScript declarations
  • πŸ”§ Pre-built Binaries - No compilation required for standard setups
  • πŸŒ™ Auto Dark Mode - Automatically adapts to system appearance changes

πŸš€ Installation

# npm
npm install electron-liquid-glass

# yarn
yarn add electron-liquid-glass

# pnpm
pnpm add electron-liquid-glass

# bun
bun add electron-liquid-glass

Requirements

  • macOS 26+ (Tahoe or later)
  • Electron 30+
  • Node.js 22+

Note: This package only works on macOS. On other platforms, it provides safe no-op fallbacks.

🎯 Quick Start

Basic Usage

import { app, BrowserWindow } from "electron";
import liquidGlass from "electron-liquid-glass";

app.whenReady().then(() => {
  const win = new BrowserWindow({
    width: 800,
    height: 600,

    vibrancy: false, // <-- ❌❌❌ do NOT set vibrancy alongside with liquid glass, it will override and look blurry

    transparent: true, // <-- This MUST be true
  });

  win.setWindowButtonVisibility(true); // <-- βœ… This is required to show the window buttons

  win.loadFile("index.html");

  /**
   * πŸͺ„ Apply glass effect after content loads πŸͺ„
   */
  win.webContents.once("did-finish-load", () => {
    // πŸͺ„ Apply effect, get handle
    const glassId = liquidGlass.addView(win.getNativeWindowHandle(), {
      /* options */
    });

    // Experimental, undocumented private APIs
    liquidGlass.unstable_setVariant(glassId, 2);
  });
});

TypeScript Usage

import { BrowserWindow } from "electron";
import liquidGlass, { GlassOptions } from "electron-liquid-glass";

const options: GlassOptions = {
  cornerRadius: 16, // (optional)
  tintColor: "#44000010", // black tint (optional)
  opaque: true, // add opaque background behind glass (optional)
};

liquidGlass.addView(window.getNativeWindowHandle(), options);

πŸ“š API Reference

liquidGlass.addView(handle, options?)

Applies a glass effect to an Electron window.

Parameters:

  • handle: Buffer - The native window handle from BrowserWindow.getNativeWindowHandle()
  • options?: GlassOptions - Configuration options

Returns: number - A unique view ID for future operations

GlassOptions

interface GlassOptions {
  cornerRadius?: number; // Corner radius in pixels (default: 0)
  tintColor?: string; // Hex color with optional alpha (#RRGGBB or #RRGGBBAA)
  opaque?: boolean; // Add opaque background behind glass (default: false)
}

UNDOCUMENTED EXPERIMENTAL METHODS

⚠️ Warning: DO NOT USE IN PROD. These methods use private macOS APIs and may change in future versions.

// Glass variants (number) (0-15, 19 are functional)
liquidGlass.unstable_setVariant(glassId, 2);

// Scrim overlay (0 = off, 1 = on)
liquidGlass.unstable_setScrim(glassId, 1);

// Subdued state (0 = normal, 1 = subdued)
liquidGlass.unstable_setSubdued(glassId, 1);

πŸ”§ Development

Building from Source

# Clone the repository
git clone https://github.com/meridius-labs/electron-liquid-glass.git
cd electron-liquid-glass

# Install dependencies
bun install

# Build native module
bun run build:native

# Build TypeScript library
bun run build

# Build everything
bun run build:all

Rebuilding for Custom Electron

If you're using a custom Electron version:

npx electron-rebuild -f -w electron-liquid-glass

Project Structure

electron-liquid-glass/
β”œβ”€β”€ src/                 # Native C++ source code
β”‚   β”œβ”€β”€ glass_effect.mm  # Objective-C++ implementation
β”‚   └── liquidglass.cc   # Node.js addon bindings
β”œβ”€β”€ js/                  # TypeScript source
β”‚   β”œβ”€β”€ index.ts         # Main library code
β”‚   └── native-loader.ts # Native module loader
β”œβ”€β”€ dist/                # Built library (generated)
β”œβ”€β”€ examples/            # Example applications
└── prebuilds/          # Pre-built binaries

πŸ—οΈ How It Works

  1. Native Integration: Uses Objective-C++ to create NSGlassEffectView instances
  2. View Hierarchy: Inserts glass views behind your web content, not over it
  3. Automatic Updates: Listens for system appearance changes to keep effects in sync
  4. Memory Management: Properly manages native view lifecycle

Technical Details

  • Primary: Uses NSGlassEffectView API when available
  • Fallback: Falls back to public NSVisualEffectView on older systems
  • Performance: Minimal overhead, native rendering performance
  • Compatibility: Works with all Electron window configurations

🀝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

Development Setup

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/amazing-feature
  3. Make your changes and test thoroughly
  4. Commit with conventional commits: git commit -m "feat: add amazing feature"
  5. Push and create a Pull Request

Reporting Issues

  • Use the issue tracker
  • Include your macOS version, Electron version, and Node.js version
  • Provide a minimal reproduction case when possible

πŸ“‹ Roadmap

  • View Management - Remove and update existing glass views

πŸ™ Acknowledgments

  • Apple's private NSGlassEffectView API documentation (reverse-engineered)
  • The Electron team for excellent native integration capabilities
  • Contributors and users who help improve this library

πŸ“„ License

MIT Β© Meridius Labs 2025


Made with ❀️ for the Electron community

⭐ Star on GitHub β€’ πŸ› Report Bug β€’ πŸ’‘ Request Feature