electron-liquid-glass

repository·main·Indexed 20 days ago

https://github.com/meridius-labs/electron-liquid-glass

A macOS glass and vibrancy wrapper for Electron BrowserWindow that provides native NSGlassEffectView effects. It allows developers to apply native glass looks with configurable corner radius, tint color, and opacity, avoiding CSS approximations. Requires macOS 26+, Electron 30+, and Node.js 22+. The library includes a liquidGlass singleton for managing views and provides safe no-op fallbacks for non-macOS platforms.

Tokens
2.4K
Snippets
11
Records
12
Agent score
19%

What's inside electron-liquid-glass

  1. How electron-liquid-glass works

    main

    The library provides native macOS glass effects by integrating directly with the system's view hierarchy.

    Core Mechanisms

    • Native Integration: Uses Objective-C++ to create NSGlassEffectView instances.
    • View Hierarchy: Instead of overlaying content, it inserts glass views behind your web content.
    • Automatic Updates: The library listens for system appearance changes (e.g., switching between Light and Dark mode) to keep the glass effect in sync with the OS.
    • Fallback Behavior: It uses the private NSGlassEffectView API when available, falling back to the public NSVisualEffectView on older systems.
    • Memory Management: It handles the native view lifecycle to prevent memory leaks.
  2. Install electron-liquid-glass

    main

    Install the package using your preferred package manager. Note that this package only works on macOS; on other platforms, it provides safe no-op fallbacks.

    Requirements

    • macOS 26+ (Tahoe or later)
    • Electron 30+
    • Node.js 22+
    # npm
    npm install electron-liquid-glass
    
    # yarn
    yarn add electron-liquid-glass
    
    # pnpm
    pnpm add electron-liquid-glass
    
    # bun
    bun add electron-liquid-glass
  3. Quick Start: Basic Usage

    main

    To apply a glass effect to an Electron window, follow these critical configuration steps:

    1. Set transparent: true in your BrowserWindow constructor.
    2. Do NOT set the vibrancy property, as it will override the liquid glass effect and cause blurriness.
    3. Call win.setWindowButtonVisibility(true) to ensure window controls remain visible.
    4. Apply the effect using liquidGlass.addView() after the window content has finished loading.
    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
        transparent: true, // MUST be true
      });
    
      win.setWindowButtonVisibility(true); // Required for window buttons
      win.loadFile("index.html");
    
      win.webContents.once("did-finish-load", () => {
        const glassId = liquidGlass.addView(win.getNativeWindowHandle(), {
          /* options */
        });
      });
    });
    import { app, BrowserWindow } from "electron";
    import liquidGlass from "electron-liquid-glass";
    
    app.whenReady().then(() => {
      const win = new BrowserWindow({
        width: 800,
        height: 600,
        vibrancy: false, 
        transparent: true, 
      });
    
      win.setWindowButtonVisibility(true); 
    
      win.loadFile("index.html");
    
      win.webContents.once("did-finish-load", () => {
        const glassId = liquidGlass.addView(win.getNativeWindowHandle(), {
          /* options */
        });
      });
    });
  4. Use liquidGlass with TypeScript

    main

    When using TypeScript, you can import the GlassOptions type to ensure type safety when configuring your glass effect.

    import { BrowserWindow } from "electron";
    import liquidGlass, { GlassOptions } from "electron-liquid-glass";
    
    const options: GlassOptions = {
      cornerRadius: 16,
      tintColor: "#44000010",
      opaque: true,
    };
    
    liquidGlass.addView(window.getNativeWindowHandle(), options);
    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);
  5. API Reference: liquidGlass.addView()

    main

    Applies a native glass effect to an Electron window.

    Signature: liquidGlass.addView(handle, options?)

    Parameters:

    • handle: Buffer - The native window handle obtained via BrowserWindow.getNativeWindowHandle().
    • options?: GlassOptions - Configuration object for the effect.

    Returns: number - A unique view ID used for subsequent operations on this specific glass view.

    liquidGlass.addView(handle: Buffer, options?: GlassOptions): number
  6. Experimental: Undocumented macOS Private APIs

    main

    ⚠️ WARNING: DO NOT USE IN PRODUCTION. These methods use private macOS APIs and are subject to change without notice.

    Use these methods with the glassId returned by addView().

    • unstable_setVariant(glassId, variant: number): Sets the glass variant (0-15, 19 are functional).
    • unstable_setScrim(glassId, state: number): Toggles the scrim overlay (0 = off, 1 = on).
    • unstable_setSubdued(glassId, state: number): Toggles the subdued state (0 = normal, 1 = subdued).
    // 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);
  7. Reference: GlassOptions

    main

    Configuration object for defining the appearance of the glass effect.

    KeyTypeDescription
    cornerRadiusnumberCorner radius in pixels (default: 0)
    tintColorstringHex color with optional alpha (#RRGGBB or #RRGGBBAA)
    opaquebooleanWhether to add an opaque background behind the glass (default: false)
    interface GlassOptions {
      cornerRadius?: number;
      tintColor?: string;
      opaque?: boolean;
    }
  8. Use the LiquidGlass singleton

    main

    The liquidGlass singleton is the primary entry point for applying glass/vibrancy effects to Electron windows. It handles platform checks (macOS only) and native addon loading internally. If the environment is not macOS or the native addon fails to load, the functionality is gracefully disabled.

    To apply an effect, use addView by passing the native window handle obtained from BrowserWindow.getNativeWindowHandle().

    import liquidGlass from 'electron-liquid-glass';
    
    // Assuming you have an Electron BrowserWindow instance named 'mainWindow'
    const handle = mainWindow.getNativeWindowHandle();
    const viewId = liquidGlass.addView(handle, {
      cornerRadius: 10,
      tintColor: '#ffffff',
      opaque: false
    });
    
    if (viewId === -1) {
      console.log('Liquid glass is not supported on this platform/version.');
    }
  9. LiquidGlass.addView()

    main

    Wraps an Electron window with a glass/vibrancy view. It will gracefully fall back to legacy macOS blur if liquid glass is not supported by the OS.

    Parameters:

    • handle: A Buffer representing the native window handle (use BrowserWindow.getNativeWindowHandle()).
    • options: An optional GlassOptions object.

    Returns:

    • A number representing the view ID (used for future updates/removal).
    • -1 if the effect is not supported on the current platform.
    const viewId = liquidGlass.addView(handle, { cornerRadius: 8 });
  10. Check if liquid glass is supported

    main

    Use isGlassSupported() to determine if the current environment can use the liquid glass effect. The library requires macOS with a product version of 26 or higher. If not supported, addView will return -1.

    if (liquidGlass.isGlassSupported()) {
      // Proceed with adding glass views
    }
  11. Unstable API: Modify glass state

    main

    The following methods are marked as unstable and are used to modify the state of an existing glass view using its viewId (returned by addView).

    • unstable_setVariant(id: number, variant: GlassMaterialVariant): Sets the material variant for the view.
    • unstable_setScrim(id: number, scrim: number): Sets the scrim state.
    • unstable_setSubdued(id: number, subdued: number): Sets the subdued state.
    // Example of using an unstable method
    liquidGlass.unstable_setVariant(viewId, liquidGlass.GlassMaterialVariant.SOME_VARIANT);
  12. Configure GlassOptions

    main

    The GlassOptions interface defines the visual properties of the glass effect applied to a window handle.

    KeyTypeDescription
    cornerRadiusnumberThe corner radius for the glass view.
    tintColorstringA color string (e.g., hex or CSS color) to tint the glass.
    opaquebooleanWhether the glass effect should be opaque.

    Note: All options are optional.

    export interface GlassOptions {
      cornerRadius?: number;
      tintColor?: string;
      opaque?: boolean;
    }