Multi-task progress bar component for tracking parallel operations.
Built on top of Alaja.Components.Table, rendering each task as a row
with columns: label | progress bar | status icon | description.
Uses ANSI cursor positioning for in-place updates without flickering.
Task status flow
running ──→ success
│ ╰──→ error
╰─────→ wait ──→ running
╰─→ errorUsage
{:ok, pid} = MultiBar.start_link(
tasks: [
%{id: :scan, label: "File Scanner"},
%{id: :embed, label: "Embeddings"},
%{id: :graph, label: "Graph Builder"}
],
title: "Indexing Project",
table_border: :rounded
)
MultiBar.progress(pid, :scan, 45, "lib/auth.ex")
MultiBar.success(pid, :scan, "127 files indexed")
MultiBar.error(pid, :embed, "server unreachable")
MultiBar.wait(pid, :graph, "DB connection pending")
MultiBar.info(pid, :scan, "Skipping _build/")
MultiBar.done(pid)Options (global)
:title— title displayed above the bars:table_border— border style (:normal,:rounded,:double,:none):table_align— table alignment (:left,:center,:right):box— wrap in box (default:false); seeAlaja.Printer:box_title— box title:box_border— box border style:box_color— box border color:padding— cell padding (default: 1):bar_width— progress bar width in chars (default: 40):bar_filled_char— char for filled portion (default: "▓"):bar_empty_char— char for empty portion (default: "░"):headers_color— color for header row:headers_effects— effects for header row:status_color— status-specific color overrides:%{running: :cyan, success: :green, error: :red, wait: :yellow, info: :blue}
Per-task options
:label— task display name (required):description— initial description text:bar_color— specific color for this task's bar
Summary
Functions
Returns a specification to start this module under a supervisor.
Stops the MultiBar, printing the final state.
Marks a task as failed with an error message.
Attaches an informational message to a task without changing its status.
Reports progress (0-100) for a task with optional description.
Starts the MultiBar GenServer.
Marks a task as successfully completed.
Marks a task as waiting/paused.
Types
@type t() :: %{ tasks: %{required(atom()) => task_state()}, titles: [String.t()], opts: keyword(), sorted_ids: [atom()], first_line: integer() | nil, line_count: non_neg_integer(), done: boolean() }
MultiBar internal state
@type task_state() :: %{ id: atom(), label: String.t(), progress: non_neg_integer(), status: :running | :success | :error | :wait | :info, status_text: String.t(), description: String.t(), bar_color: {integer(), integer(), integer()} | nil }
Internal state of one task
Functions
Returns a specification to start this module under a supervisor.
See Supervisor.
@spec done(GenServer.server()) :: :ok
Stops the MultiBar, printing the final state.
If status is :all_success and all tasks succeeded, prints a
success summary. Otherwise prints each task's final status.
@spec error(GenServer.server(), atom(), String.t() | nil) :: :ok
Marks a task as failed with an error message.
@spec info(GenServer.server(), atom(), String.t()) :: :ok
Attaches an informational message to a task without changing its status.
@spec progress(GenServer.server(), atom(), non_neg_integer(), String.t() | nil) :: :ok
Reports progress (0-100) for a task with optional description.
@spec start_link(keyword()) :: GenServer.on_start()
Starts the MultiBar GenServer.
Options (see @moduledoc for full list)
:tasks— list of%{id: atom, label: String.t, ...}(required):name— register under this name via{:via, Registry, {registry, name}}
@spec success(GenServer.server(), atom(), String.t() | nil) :: :ok
Marks a task as successfully completed.
@spec wait(GenServer.server(), atom(), String.t() | nil) :: :ok
Marks a task as waiting/paused.