Packages

Multi-surface application runtime for Elixir. One TEA module renders to terminal, browser (LiveView), SSH, and MCP (agents). 30+ widgets, flexbox + CSS grid, AI agent runtime, distributed swarm with CRDTs, time-travel debugging, session recording, sandboxed REPL, and agentic commerce.

Current section

Files

Jump to
raxol lib raxol.ex
Raw

lib/raxol.ex

defmodule Raxol do
@moduledoc """
Raxol is a feature-rich terminal UI framework for Elixir.
It provides a comprehensive set of components and tools for building
beautiful, accessible, and responsive terminal applications.
## Features
* **Modern Component Library**: A rich set of pre-built UI components like buttons,
text inputs, tables, modals, and more.
* **Accessibility Support**: Built-in features for screen readers, high contrast
mode, and keyboard navigation.
* **Theming System**: Customize the look and feel of your application with
consistent theming.
* **Responsive Layouts**: Create layouts that adapt to different terminal sizes.
* **The Elm Architecture**: Follows TEA (The Elm Architecture) for predictable
state management.
* **Event Handling**: Comprehensive event system for keyboard, mouse, and terminal events.
## Getting Started
To create a new Raxol application, you need to define three core functions:
* `init/1`: Initializes your application state
* `update/2`: Updates the state based on events
* `render/1`: Renders the UI based on the current state
Here's a simple counter example:
```text
defmodule Counter do
@behaviour Raxol.Core.Runtime.Application
require Raxol.Core.Renderer.View
alias Raxol.Core.Runtime.Events.Event
def init(_opts) do
{%{count: 0}, []}
end
def update(%{count: count} = model, %Event{type: :command, data: :increment}) do
{%{model | count: count + 1}, []}
end
def update(%{count: count} = model, %Event{type: :command, data: :decrement}) do
{%{model | count: count - 1}, []}
end
def update(model, _event_or_msg), do: {model, []}
def view(model) do
Raxol.Core.Renderer.View.column [padding: 1] do
[
Raxol.Core.Renderer.View.text("Count: \#{model.count}"),
Raxol.Core.Renderer.View.row [gap: 1] do
[
Raxol.Core.Renderer.View.button "-", on_click: {:command, :decrement},
Raxol.Core.Renderer.View.button "+", on_click: {:command, :increment}
]
end
]
end
end
end
# Start the application
Raxol.run(Counter)
```
## Architecture
Raxol is built on the Elm Architecture:
1. **Model**: Your application state
2. **Update**: Logic to update the state based on messages
3. **View**: Pure functions to render UI based on the current state
Messages can be generated by user interactions (like button clicks) or
system events (like terminal resize).
## Components
Raxol provides a rich set of built-in components in the Raxol.Components
module. Common components include:
* Buttons
* Text inputs
* Tables
* Progress indicators
* Modals
* Dropdown menus
* Tab bars
Each component follows consistent patterns for styling and behavior.
"""
alias Raxol.Core.Runtime.Application
require Logger
@doc """
Runs a Raxol application.
This function starts the Raxol runtime with the provided application module
and options. The application module must implement the `Raxol.Core.Runtime.Application` behaviour.
## Parameters
* `app` - Module implementing the `Raxol.Core.Runtime.Application` behaviour
* `opts` - Additional options for the runtime
## Options
* `:quit_keys` - List of keys that will quit the application (default: `[{:ctrl, ?c}]`)
* `:fps` - Target frames per second (default: `60`)
* `:title` - Terminal window title (default: `"Raxol Application"`)
* `:font` - Terminal font (if supported)
* `:font_size` - Terminal font size (if supported)
* `:accessibility` - Accessibility options
* `:screen_reader` - Enable screen reader support (default: `true`)
* `:high_contrast` - Enable high contrast mode (default: `false`)
* `:large_text` - Enable large text mode (default: `false`)
## Returns
The return value of the application when it exits.
## Example
```elixir
Raxol.run(MyApp, %{initial: "state"}, title: "My Application", fps: 30)
```
"""
def run(app, opts \\ []) do
Raxol.Core.Runtime.Lifecycle.start_application(app, opts)
end
@doc """
Gracefully stops a running Raxol application.
This function can be called from within your application to exit gracefully.
## Parameters
* `return_value` - Value to return from the `Raxol.run/3` function
## Example
```elixir
def update(model, :exit) do
Raxol.stop(:normal)
model
end
```
"""
def stop(return_value \\ :ok) do
Raxol.Core.Runtime.Lifecycle.stop_application(return_value)
end
@doc """
Returns the current version of Raxol.
## Returns
A string representing the current version.
## Example
```elixir
Raxol.version()
# => "1.0.0"
```
"""
def version do
# Update this with each release
"1.0.0"
end
@doc """
Returns information about the terminal environment.
This includes terminal size, color support, and other capabilities.
## Returns
A map with terminal information.
## Example
```elixir
Raxol.terminal_info()
# => %{
# name: "iTerm2",
# version: "3.5.0",
# features: [:true_color, :unicode, :mouse, :clipboard],
# ...
# }
```
"""
def terminal_info do
# Assuming capabilities are now handled differently, maybe via Driver or Config?
# Platform.get_terminal_capabilities()
# Placeholder
%{width: 80, height: 24, colors: 256}
end
@doc """
Sets the default theme for Raxol applications.
This function sets the default theme that will be used by Raxol components.
## Parameters
* `theme` - A theme created with `Raxol.UI.Theming.Theme.new/1` or one of the built-in themes
## Example
```elixir
# Use a built-in theme
Raxol.set_theme(Raxol.UI.Theming.Theme.dark())
# Create and use a custom theme
custom_theme = Raxol.UI.Theming.Theme.new(name: "Custom", colors: %{primary: :green})
Raxol.set_theme(custom_theme)
```
"""
def set_theme(theme) do
require Logger
Logger.info("Setting theme: #{theme.name}")
# Persist the theme choice (e.g., Application config)
Application.put_env(:raxol, :theme, theme)
:ok
end
@doc """
Gets the current default theme.
## Returns
The current theme map.
## Example
```elixir
theme = Raxol.current_theme()
```
"""
def current_theme do
# Update to use new Theme module path and function
Application.get_env(:raxol, :theme, Raxol.UI.Theming.Theme.default_theme())
end
@doc """
Enables or disables accessibility features.
## Parameters
* `opts` - Map of accessibility features to enable/disable
## Options
* `:screen_reader` - Enable screen reader support
* `:high_contrast` - Enable high contrast mode
* `:large_text` - Enable large text mode
* `:reduced_motion` - Reduce or eliminate animations
## Example
```elixir
Raxol.set_accessibility(screen_reader: true, high_contrast: true)
```
"""
def set_accessibility(opts \\ []) do
# Update theme setting based on opts (e.g., high_contrast: true)
if opts[:high_contrast] do
# Find the high contrast theme or use a default if not directly available
# Needs review based on how high_contrast themes are managed
# For now, assume a dark theme provides contrast
set_theme(Raxol.UI.Theming.Theme.dark_theme())
# Old call: set_theme(Theme.high_contrast())
else
set_theme(Raxol.UI.Theming.Theme.default_theme())
end
# Persist accessibility settings
# Application.put_env(:raxol, :accessibility, opts) # Comment out undefined function
:ok
end
@doc """
Gets the current accessibility settings.
## Returns
A map of current accessibility settings.
## Example
```elixir
settings = Raxol.accessibility_settings()
if settings.high_contrast do
# Do something for high contrast mode
end
```
"""
def accessibility_settings do
Application.get_env(:raxol, :accessibility, %{
screen_reader: true,
high_contrast: false,
large_text: false,
reduced_motion: false
})
end
end