Components

Nixi provides a HyperScript-like DSL (Domain Specific Language) for generating HTML elements in Lua. This approach keeps your UI code declarative and type-safe.

Creating Elements

create_element

The base function for creating any HTML element:

Nixi.create_element(tag, attrs, children...)
-- Self-closing element
local br = Nixi.create_element("br", nil)

-- Element with attributes
local input = Nixi.create_element("input", {
    type = "text",
    name = "username",
    placeholder = "Enter name"
})

-- Element with children
local div = Nixi.create_element("div", { class = "card" },
    Nixi.h2(nil, "Title"),
    Nixi.p(nil, "Content here")
)

Built-in Element Functions

Container Elements

Nixi.div({ class = "container" }, "Content")
Nixi.span({ id = "counter" }, "0")
Nixi.p({ style = "color: red;" }, "Text")
Nixi.h1(nil, "Main Title")
Nixi.h2(nil, "Section Title")

Interactive Elements

-- Button with HTMX
Nixi.button({
    class = "btn primary",
    ["hx-post"] = "/api/submit",
    ["hx-target"] = "#result",
    ["hx-swap"] = "innerHTML"
}, "Submit")

-- Anchor link
Nixi.a({ href = "/about" }, "About Us")

-- Input fields
Nixi.input({
    type = "text",
    name = "email",
    placeholder = "email@example.com",
    required = true
})

List Elements

-- Unordered list with items
Nixi.ul({ class = "menu" }, {
    "Item 1",
    "Item 2",
    "Item 3"
})

HTMX Attributes

HTMX is core to Nixi's reactivity. Use HTMX attributes for AJAX interactions:

Attribute Description
hx-get Make GET request
hx-post Make POST request
hx-target CSS selector of target element
hx-swap How to swap content (innerHTML, outerHTML, etc.)
hx-trigger Event that triggers request
hx-vals Additional values to send

Attributes

Basic Attributes

Nixi.div({
    id = "main",
    class = "container active",
    style = "padding: 20px;"
}, "Content")

Boolean Attributes

Nixi.input({
    type = "text",
    disabled = false,        -- Not included in output
    readonly = true,         -- Included as "readonly"
    required = true         -- Included as "required"
})

Data Attributes

Nixi.div({
    ["data-user-id"] = "123",
    ["data-action"] = "edit"
}, "Content")

Nesting Elements

Build complex layouts by nesting components:

local card = Nixi.div(
    { class = "card" },
    Nixi.div(
        { class = "card-header" },
        Nixi.h1({ class = "title" }, "My First Post")
    ),
    Nixi.div(
        { class = "card-body" },
        Nixi.p(nil, "First paragraph..."),
        Nixi.p(nil, "Second paragraph...")
    ),
    Nixi.footer(
        { class = "card-footer" },
        Nixi.a({ href = "/" }, "Back to Home")
    )
)

UI Component Library

Nixi includes a pre-built UI component library with styled components and a theme system.

Setup

package.path = "src/?.lua;src/?/init.lua;" .. package.path

local Nixi = require("nixi.init")
_G.Nixi = Nixi

local style = require("nixi.style")
Nixi.style = style

local UI = require("nixi.ui")
local theme = require("nixi.ui.theme")

-- Apply theme
local tokyoNight = theme.getTheme("tokyoNight")
theme.applyTheme(tokyoNight.colors)
theme.injectAllStyles(tokyoNight.colors)

Available Components

Component Description
Button Styled buttons with variants (primary, secondary, danger, ghost, outline)
Input Text inputs with label, error, and hint support
Select Dropdown select with options
Checkbox Checkbox and radio inputs
Card Content cards with header, image, and footer
Modal Dialog modals with backdrop
Toast Notification toasts
Loader Loading spinners and progress bars
Tabs Tabbed interface
Badge Small status badges and tags

Using UI Components

-- Render a button
UI.Button.render({ variant = "primary", children = "Click Me" })

-- Render an input with label
UI.Input.render({
    type = "email",
    name = "email",
    label = "Email Address",
    placeholder = "you@example.com"
})

-- Render a card
UI.Card.render({
    title = "My Card",
    children = "Card content here"
})

Theme System

-- Available themes
local themes = theme.themes
-- tokyoNight, dracula, githubDark, catppuccinMocha

-- Apply a theme
local selectedTheme = theme.getTheme("tokyoNight")
theme.applyTheme(selectedTheme.colors)
theme.injectAllStyles(selectedTheme.colors)

-- Or inject styles for a specific theme
theme.injectAllStyles(themes.dracula.colors)

Security: XSS Protection

All UI components include automatic XSS protection. User-provided values are escaped before rendering to prevent cross-site scripting attacks.

Escaped Values

The following values are automatically escaped in all components:

Example

-- This input is safe even with malicious user input
UI.Input.render({
    label = "<script>alert('xss')</script>",  -- Escaped
    placeholder = 'onload="alert(1)"',  -- Escaped
    value = '<img src=x onerror=alert(1)>'  -- Escaped
})
-- Output: All special characters are converted to HTML entities

Escape Function

The escape() function converts dangerous characters:

Character Escaped To
& &amp;
< &lt;
> &gt;
" &quot;
' &#39;