Skip to content

Examples

This page explains a few complete Lua widget patterns. For every shipped example, its dependency, and inbox behavior, use the Bundled Widgets catalog.

If you are just starting out, read First Widget before using these as templates.

Toggle widget

local enabled = false
local toggle

local function render()
    toggle:set({
        icon = {
            string = enabled and "󰄬" or "󰄱",
            color = enabled and "#30d158" or "#ff453a",
        },
        label = {
            string = enabled and "ON" or "OFF",
            color = enabled and "#30d158" or "#ff453a",
        },
    })
end

toggle = easybar.add(easybar.kind.item, "toggle_test", {
    position = "right",
    order = 1,
})

toggle:subscribe(easybar.events.forced, function()
    render()
end)

toggle:subscribe(easybar.events.mouse.clicked, function()
    enabled = not enabled
    render()
end)

render()

Bundled Homebrew widget

widgets/brew.lua is a complete example of a stateful popup widget. It:

  • checks formulae and casks with brew outdated
  • exposes Update and Upgrade actions as clickable popup children
  • runs Homebrew commands asynchronously so other widgets remain responsive
  • changes Update to Cancel while an operation is active
  • returns directly to the idle actions after cancellation while preserving the last known package list
  • writes command diagnostics to brew-widget.log under the configured EasyBar logging directory

The widget is intentionally more extensive than the snippets on this page. Use it as a reference for command chaining, cancellation, structured state rendering, popup rows, error presentation, and bounded file logging.

Use the inbox-only widgets/brew-inbox.lua variant to publish outdated formulae, casks, Homebrew warnings, and command errors into the native inbox. It supports refresh, brew update, individual or complete upgrades, and cancellation while an update or upgrade is running. Load either brew.lua or brew-inbox.lua, not both.

Bundled GitLab work-items widget

widgets/gitlab.lua shows the open issues and merge requests assigned to the authenticated user. It works with GitLab.com and private GitLab Self-Managed or Dedicated instances through the official glab CLI. Use the inbox-only widgets/gitlab-inbox.lua variant to publish the same work items into EasyBar's shared native inbox.

The equivalent inbox-only GitHub publisher is widgets/github-inbox.lua. Use widgets/inbox-demo.lua to preview inbox grouping, severities, Markdown, unread state, and actions without external services.

Install glab, authenticate the instance, and make the CLI and host available to GUI-launched EasyBar sessions:

brew install glab
glab auth login --hostname gitlab.example.com
[app.env]
PATH = "/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin"
GITLAB_HOST = "https://gitlab.example.com"

Then add gitlab.lua to the configured widgets_dir together with the bundled lib directory. The widget refreshes every five minutes, orders assigned work by its most recent update, opens an item when its popup row is clicked, and provides Refresh and Open GitLab actions in its native right-click menu. GITLAB_HOST is optional for GitLab.com.

Clock widget

local clock

clock = easybar.add(easybar.kind.item, "clock", {
    position = "right",
    order = 10,
    interval = 60,
    icon = "􀐫",
    label = os.date("%H:%M"),
    on_interval = function()
        clock:set({
            label = os.date("%H:%M"),
        })
    end,
})

Native context menu widget

widgets/context-menu.lua shows a native macOS right-click menu with actions, a separator, checked state, a submenu, and dynamic menu replacement. See Native Context Menus for the full API and right-click precedence rules.

widgets/popup-context-menu.lua attaches both interaction surfaces to one anchor. Hovering shows status in a popup, while right-clicking opens a native menu with an action and checked mode submenu. The example also shows how one render function keeps popup content, anchor content, and menu checkmarks synchronized. The popup uses EasyBar's native hover tracking, so it remains open while moving from the anchor into the popup without custom mouse.entered or mouse.exited handlers.

Widget-relative image asset

local github = easybar.add(easybar.kind.item, "github", {
    icon = {
        color = easybar.theme.ref.text,
        image = {
            path = easybar.asset("github-mark.svg"),
            size = 16,
        },
    },
})

easybar.asset() resolves relative to the Lua file that calls it, so the example expects github-mark.svg beside the widget file. Nested paths such as easybar.asset("assets/github-mark.svg") work too. This approach is best for larger images or assets reused by more than one part of a widget. Existing absolute paths remain valid when passed directly as image.path.

Inline SVG image

local github_svg = [[
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
    <path d="..." />
</svg>
]]

local github = easybar.add(easybar.kind.item, "github", {
    icon = {
        color = easybar.theme.ref.text,
        image = {
            svg = github_svg,
            size = 16,
        },
    },
})

Inline SVG is useful for small, self-contained widgets. Set either path or svg, never both. Without an icon color, SVG images keep their original colors; setting icon.color applies the same template tint used for file-backed images. Inline SVG does not sandbox a widget: widget files remain trusted local code.