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:
id,name,classattributesvalue,placeholder,labelerror,hint,titlemessageschildrencontent- All HTMX attributes (
hx-get,hx-post,hx-target, etc.) - Option values and labels in Select components
- Tab IDs, labels, and content in Tabs 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 |
|---|---|
& |
& |
< |
< |
> |
> |
" |
" |
' |
' |