hs.ui
Module
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.
Key Features
- Custom Windows: Build custom UI windows with shapes, text, and layouts
- Alerts: Display temporary on-screen notifications
- Dialogs: Show modal dialogs with custom buttons and callbacks
- Text Input: Prompt users for text input
- File Pickers: Let users select files or directories
- Reactive Colors: Pass an
HSColorobject to.fill(),.stroke(), or.foregroundColor(), then call.set()on it from any callback to re-render the canvas automatically - Reactive Text: Create a string with
hs.ui.string(), pass it to.text(), then call.set()on it to update the displayed content live - Reactive Images: Pass an
HSImageobject to.image(), then call.set()on it to swap the image without rebuilding the window
Basic Examples
Simple Alert
hs.ui.alert("Task completed!")
.duration(3)
.show();
Dialog with Buttons
hs.ui.dialog("Save changes?")
.informativeText("Your document has unsaved changes.")
.buttons(["Save", "Don't Save", "Cancel"])
.onButton((index) => {
if (index === 0) print("Saving...");
})
.show();
Text Input Prompt
hs.ui.textPrompt("Enter your name")
.defaultText("John Doe")
.onButton((buttonIndex, text) => {
print("User entered: " + text);
})
.show();
File Picker
hs.ui.filePicker()
.message("Choose a file")
.allowedFileTypes(["txt", "md"])
.onSelection((path) => {
if (path) print("Selected: " + path);
})
.show();
Custom Window
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();
Reactive Color on Hover
// 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.set(isHovered ? "#E24A4A" : "#4A90E2");
})
.show();
Reactive Text on Hover
// 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();
Reactive Image on Click
// 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.set(next);
})
.show();
Complete Example: Status Dashboard
Here's a more complex example showing how to build an interactive status dashboard that combines multiple UI elements:
// 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();
Complete Example: Reactive Hover Card
Demonstrates reactive colors and reactive text together — a single .onHover()
callback updates both the fill color of a shape and the content of a text label:
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.set(isHovered ? "#E74C3C" : "#3498DB");
cardLabel.set(isHovered ? "You found it!" : "Hover the card");
})
.text(cardLabel)
.font(HSFont.headline())
.foregroundColor("#FFFFFF")
.end()
.backgroundColor("#1A252F")
.show();
Types
This module provides the following types:
Properties
This module has no properties.
Methods
hs.ui.window
Create a custom UI window Creates a borderless window that can contain custom UI elements built using a declarative, SwiftUI-like syntax with shapes, text, and layout containers.
Hammerspoon 2/Modules/hs.ui/HSUIModule.swift:308
Declaration
hs.ui.window(dict) -> HSUIWindow
Parameters
-
dict{[key: string]: any}Dictionary with keys: `x`, `y`, `w`, `h` (all numbers)
Return Value
An `HSUIWindow` object for chaining
hs.ui.alert
Create a temporary on-screen alert Displays a temporary notification that automatically dismisses after the specified duration. Similar to the old `hs.alert` module but with more features.
Hammerspoon 2/Modules/hs.ui/HSUIModule.swift:344
Declaration
hs.ui.alert(message) -> HSUIAlert
Parameters
-
messagestringThe message text to display
Return Value
An `HSUIAlert` object for chaining
hs.ui.dialog
Create a modal dialog with buttons Shows a blocking dialog with customizable message, informative text, and buttons. Use the callback to handle button presses.
Hammerspoon 2/Modules/hs.ui/HSUIModule.swift:384
Declaration
hs.ui.dialog(message) -> HSUIDialog
Parameters
-
messagestringThe main message text
Return Value
An `HSUIDialog` object for chaining
hs.ui.textPrompt
Create a text input prompt Shows a modal dialog with a text input field. The callback receives the button index and the entered text.
Hammerspoon 2/Modules/hs.ui/HSUIModule.swift:424
Declaration
hs.ui.textPrompt(message) -> HSUITextPrompt
Parameters
-
messagestringThe prompt message
Return Value
An `HSUITextPrompt` object for chaining
hs.ui.string
Create a reactive string for binding text element content to a dynamic value An `HSString` is a reactive value container. When passed to `.text()`, the canvas automatically re-renders whenever `.set()` is called from JavaScript.
Hammerspoon 2/Modules/hs.ui/HSUIModule.swift:445
Declaration
hs.ui.string(initialValue) -> HSString
Parameters
-
initialValuestringThe starting string value
Return Value
An `HSString` object whose value can be updated with `.set()`
hs.ui.filePicker
Create a file or directory picker Shows a standard macOS file picker dialog. Can be configured to select files, directories, or both, with support for file type filtering and multiple selection.
Hammerspoon 2/Modules/hs.ui/HSUIModule.swift:501
Declaration
hs.ui.filePicker() -> HSUIFilePicker
Parameters
None
Return Value
An `HSUIFilePicker` object for chaining