App

The App type is the main entry point for creating Bonito applications. It wraps your content and handles the connection between Julia and the browser.

Basic Usage

using Bonito

# Simple app with static content
app = App(DOM.div("Hello World"))

# App with session access
app = App() do session::Session
    button = Button("Click me")
    on(button.value) do _
        println("Button clicked!")
    end
    return button
end

# App with request access (useful for routing)
app = App() do session::Session, request::HTTP.Request
    path = request.target
    return DOM.div("You requested: $path")
end

App Options

The App constructor accepts the following keyword arguments:

App(handler;
    title="Bonito App",  # Browser tab title
    indicator=nothing    # Connection status indicator (nothing by default)
)

Connection Indicator

Bonito provides an optional LED-like indicator that can be displayed in the top-right corner to show the connection status to the Julia server:

  • Green: Connected to the server
  • Yellow: Connecting or reconnecting
  • Red: Disconnected from the server
  • Gray: No connection mode (static export)

Enabling the Indicator

To show the connection indicator, pass a ConnectionIndicator() to your App:

App(; indicator=ConnectionIndicator()) do
    DOM.h1("App with connection indicator")
end

Customizing Colors and Size

App(; indicator=ConnectionIndicator(
    connected_color="lime",
    connecting_color="orange",
    disconnected_color="red",
    no_connection_color="gray",
    size=15  # pixels
)) do
    DOM.h1("Custom indicator colors")
end
Browser Display

When using browser display (e.g., displaying apps in VS Code or via Server), the indicator is rendered on the root session which persists across app updates. Changes to the indicator argument will not take effect until you refresh the browser page to create a new root session.

Customizing Position

By default, the indicator is positioned in the top-right corner. You can change this:

# Bottom-left corner
App(; indicator=ConnectionIndicator(
    top="auto",
    right="auto",
    style=Styles(
        "bottom" => "10px",
        "left" => "10px"
    )
)) do
    DOM.h1("Indicator in bottom-left")
end

# Center-top with custom styling
App(; indicator=ConnectionIndicator(
    right="auto",
    style=Styles(
        "left" => "50%",
        "transform" => "translateX(-50%)",
        "border" => "2px solid white"
    )
)) do
    DOM.h1("Centered indicator")
end

ConnectionIndicator Arguments

ArgumentDefaultDescription
connected_color"#22c55e"Color when connected (green)
connecting_color"#eab308"Color when connecting (yellow)
disconnected_color"#ef4444"Color when disconnected (red)
no_connection_color"#6b7280"Color for NoConnection mode (gray)
size10Diameter in pixels
position"fixed"CSS position property
top"10px"Distance from top
right"10px"Distance from right
styleStyles()Additional CSS styles

Creating a Custom Indicator

For complete control over the indicator's appearance and behavior, you can create your own by subtyping AbstractConnectionIndicator:

using Bonito

struct TextIndicator <: AbstractConnectionIndicator
    font_size::Int
end

TextIndicator(; font_size=12) = TextIndicator(font_size)

function Bonito.jsrender(session::Session, indicator::TextIndicator)
    # Create the DOM element
    status_text = DOM.span("Connecting...";
        style=Styles(
            "position" => "fixed",
            "top" => "10px",
            "right" => "10px",
            "font-size" => "$(indicator.font_size)px",
            "font-family" => "monospace",
            "padding" => "4px 8px",
            "background" => "rgba(0,0,0,0.7)",
            "color" => "white",
            "border-radius" => "4px",
            "z-index" => "9999"
        )
    )

    # JavaScript to handle status changes
    init_script = js"""
    function initTextIndicator(element) {
        const messages = {
            connected: "✓ Connected",
            connecting: "◐ Connecting...",
            disconnected: "✗ Disconnected",
            no_connection: "○ Static Mode"
        };

        const colors = {
            connected: "#22c55e",
            connecting: "#eab308",
            disconnected: "#ef4444",
            no_connection: "#6b7280"
        };

        const indicator = {
            onStatusChange: function(status) {
                element.textContent = messages[status] || messages.disconnected;
                element.style.color = colors[status] || colors.disconnected;
            }
        };

        Bonito.register_connection_indicator(indicator);
    }
    """

    Bonito.onload(session, status_text, init_script)
    return Bonito.jsrender(session, status_text)
end

# Use it
App(; indicator=TextIndicator(font_size=14)) do
    DOM.h1("App with text-based indicator")
end

JavaScript API for Custom Indicators

When creating a custom indicator, register it with Bonito using these JavaScript functions:

// Register your indicator object
Bonito.register_connection_indicator({
    // Called when connection status changes
    onStatusChange: function(status) {
        // status: "connected" | "connecting" | "disconnected" | "no_connection"
    }
});

// Unregister the current indicator
Bonito.unregister_connection_indicator();

// Status constants (for comparison)
Bonito.ConnectionStatus.CONNECTED      // "connected"
Bonito.ConnectionStatus.CONNECTING     // "connecting"
Bonito.ConnectionStatus.DISCONNECTED   // "disconnected"
Bonito.ConnectionStatus.NO_CONNECTION  // "no_connection"

The indicator automatically shows the appropriate status based on the connection state, including "no_connection" for static exports.