hammerspoon2-docs
    Preparing search index...

    Namespace ui

    hs.ui

    Create custom user interfaces, alerts, dialogs, and file pickers* The hs.ui module provides a set of tools for creating custom user interfaces in Hammerspoon with SwiftUI-like declarative syntax.

    then call .replaceWithColor() or .replaceWithHex() on it from any callback to re-render the canvas automatically then call .set() on it to update the displayed content live to swap the image without rebuilding the window

    hs.ui.alert("Task completed!")
    .duration(3)
    .show();
    hs.ui.dialog("Save changes?")
    .informativeText("Your document has unsaved changes.")
    .buttons(["Save", "Don't Save", "Cancel"])
    .onButton((index) => {
    if (index === 0) console.log("Saving...");
    })
    .show();
    hs.ui.textPrompt("Enter your name")
    .defaultText("John Doe")
    .onButton((buttonIndex, text) => {
    console.log("User entered: " + text);
    })
    .show();
    hs.ui.filePicker()
    .message("Choose a file")
    .allowedFileTypes(["txt", "md"])
    .onSelection((path) => {
    if (path) console.log("Selected: " + path);
    })
    .show();
    hs.ui.window({x: 100, y: 100, w: 300, h: 200})
    .vstack()
    .spacing(10)
    .padding(20)
    .text("Hello, World!")
    .font(HSFont.title())
    .foregroundColor("#FFFFFF")
    .rectangle()
    .fill("#4A90E2")
    .cornerRadius(10)
    .frame({w: "100%", h: 60})
    .end()
    .backgroundColor("#2C3E50")
    .show();
    // Create a mutable color, then mutate it inside the hover callback
    const btnColor = HSColor.hex("#4A90E2");

    hs.ui.window({x: 100, y: 100, w: 160, h: 60})
    .rectangle()
    .fill(btnColor)
    .cornerRadius(8)
    .frame({w: "100%", h: "100%"})
    .onHover((isHovered) => {
    btnColor.replaceWithHex(isHovered ? "#E24A4A" : "#4A90E2");
    })
    .show();
    // Create a mutable string, then mutate it inside the hover callback
    const label = hs.ui.string("Move your mouse here");

    hs.ui.window({x: 100, y: 200, w: 220, h: 50})
    .text(label)
    .font(HSFont.body())
    .foregroundColor("#FFFFFF")
    .onHover((isHovered) => {
    label.set(isHovered ? "You're hovering!" : "Move your mouse here");
    })
    .show();
    // Toggle between two system icons on each click
    const icon = HSImage.fromName("NSStatusAvailable");

    hs.ui.window({x: 100, y: 300, w: 80, h: 80})
    .image(icon)
    .resizable()
    .aspectRatio("fit")
    .frame({w: 64, h: 64})
    .onClick(() => {
    const next = (icon.name === "NSStatusAvailable")
    ? HSImage.fromName("NSStatusUnavailable")
    : HSImage.fromName("NSStatusAvailable");
    icon.replaceWithImage(next);
    })
    .show();

    Here's a more complex example showing how to build an interactive status dashboard

    // Create a status dashboard window
    const statusWindow = hs.ui.window({x: 100, y: 100, w: 400, h: 500})
    .vstack()
    .spacing(15)
    .padding(20)

    // Header
    .text("System Status Dashboard")
    .font(HSFont.largeTitle())
    .foregroundColor("#FFFFFF")

    // Status cards
    .hstack()
    .spacing(10)
    .vstack()
    .spacing(5)
    .rectangle()
    .fill("#4CAF50")
    .cornerRadius(8)
    .frame({w: 180, h: 100})
    .text("CPU: 45%")
    .font(HSFont.headline())
    .foregroundColor("#FFFFFF")
    .end()
    .vstack()
    .spacing(5)
    .rectangle()
    .fill("#2196F3")
    .cornerRadius(8)
    .frame({w: 180, h: 100})
    .text("Memory: 8.2GB")
    .font(HSFont.headline())
    .foregroundColor("#FFFFFF")
    .end()
    .end()

    // Activity indicator with image
    .hstack()
    .spacing(10)
    .image(HSImage.fromName("NSComputer"))
    .resizable()
    .aspectRatio("fit")
    .frame({w: 64, h: 64})
    .vstack()
    .text("System Running")
    .font(HSFont.title())
    .text("All services operational")
    .font(HSFont.caption())
    .foregroundColor("#A0A0A0")
    .end()
    .end()

    // Circle status indicators
    .hstack()
    .spacing(20)
    .circle()
    .fill("#4CAF50")
    .frame({w: 30, h: 30})
    .circle()
    .fill("#FFC107")
    .frame({w: 30, h: 30})
    .circle()
    .fill("#F44336")
    .frame({w: 30, h: 30})
    .end()
    .end()
    .backgroundColor("#2C3E50");

    // Show the dashboard
    statusWindow.show();

    // Later, interact with dialogs
    hs.ui.dialog("Shutdown system?")
    .informativeText("This will close all applications.")
    .buttons(["Shutdown", "Cancel"])
    .onButton((index) => {
    if (index === 0) {
    hs.ui.alert("Shutting down...")
    .duration(3)
    .show();
    }
    })
    .show();

    Demonstrates reactive colors and reactive text together — a single .onHover()

    const cardColor = HSColor.hex("#3498DB");
    const cardLabel = hs.ui.string("Hover the card");

    hs.ui.window({x: 100, y: 100, w: 220, h: 120})
    .vstack()
    .spacing(12)
    .padding(16)
    .rectangle()
    .fill(cardColor)
    .cornerRadius(10)
    .frame({w: "100%", h: 60})
    .onHover((isHovered) => {
    cardColor.replaceWithHex(isHovered ? "#E74C3C" : "#3498DB");
    cardLabel.set(isHovered ? "You found it!" : "Hover the card");
    })
    .text(cardLabel)
    .font(HSFont.headline())
    .foregroundColor("#FFFFFF")
    .end()
    .backgroundColor("#1A252F")
    .show();

    Functions

    alert
    dialog
    filePicker
    string
    textPrompt
    webview
    window