Appearance
Layout Components
Vulpis uses a Flexbox-inspired system to arrange elements. The core building blocks for layout are Box components. These containers group other elements and control their positioning, spacing, and alignment.
Components
el.VBox (Vertical Box)
A container that arranges its children in a vertical column (top to bottom).
- Engine Type:
"vbox"
lua
el.VBox({
style = { gap = 10 },
children = { el.Text("Top"), el.Text("Bottom") }
})el.HBox (Horizontal Box)
A container that arranges its children in a horizontal row (left to right).
- Engine Type:
"hbox"
lua
el.HBox({
style = { gap = 10 },
children = { el.Text("Left"), el.Text("Right") }
})el.Box (Generic Box)
A generic container. By default, it acts as an hbox, but you can override the type manually if needed.
- Default Engine Type:
"hbox"
lua
-- Equivalent to HBox
el.Box({
children = { ... }
})Native Engine Shorthands
To keep your code concise, the Vulpis C++ engine natively supports shorthand properties for dimensions and spacing inside your style table.
The Cascading Box Model
Spacing shorthands (padding and margin) use a smart Cascading Fallback system native to the C++ engine. The engine will prioritize specific sides, then axes, and finally the general value.
For example, if you write style = { p = 20, pb = 0 }, the engine understands that Top, Left, and Right are 20, but Bottom is overridden to 0.
- Specific Side:
pt,pb,pl,pr(Overrides everything else) - Axis:
px(Left/Right),py(Top/Bottom) - All Sides:
p
Supported Shorthands
| Shorthand Prop | Equivalent Style Property | Description |
|---|---|---|
w, h | w, h | Width and height (e.g., 200 or "100%"). |
p, px, py | padding, paddingLeft/paddingRight, paddingTop/paddingBottom | Padding across all, horizontal, or vertical axes. |
pt, pb, pl, pr | paddingTop, paddingBottom, paddingLeft, paddingRight | Specific padding overrides. |
m, mx, my | margin, marginLeft/marginRight, marginTop/marginBottom | Margin across all, horizontal, or vertical axes. |
mt, mb, ml, mr | marginTop, marginBottom, marginLeft, marginRight | Specific margin overrides. |
gap | spacing | Space between child elements. |
(Note: Colors, borders, and flexbox alignments must use their full names like BGColor, borderRadius, alignItems, etc.)
Shorthand Example:
lua
el.VBox({
style = {
w = "100%", h = 200,
BGColor = "#222222",
borderRadius = 10,
justifyContent = "center",
alignItems = "center",
gap = 15,
p = 20, pb = 0 -- 20px padding everywhere except the bottom
},
children = { el.Text("Item 1"), el.Text("Item 2") }
})Complete Styling Reference
All layout components accept the following properties inside their style table.
Dimensions
| Property | Type | Description |
|---|---|---|
w, h | number | string | Width and height in pixels or percentages (e.g., "100%"). |
minWidth, maxWidth | number | Minimum and maximum width in pixels. |
minHeight, maxHeight | number | Minimum and maximum height in pixels. |
Alignment (Flexbox)
Control how children are distributed inside the box.
| Property | Options | Description |
|---|---|---|
justifyContent | "start", "center", "end", "space-between", "space-around", "space-evenly" | Alignment along the main axis (Vertical for VBox, Horizontal for HBox). |
alignItems | "start", "center", "end", "stretch" | Alignment along the cross axis. |
flexGrow | number | If > 0, the box will grow to fill available space relative to siblings. |
flexShrink | number | If > 0, the box will shrink if space is limited. |
flexWrap | "nowrap", "wrap", "wrap-reverse" | Controls whether children are forced onto one line or can wrap onto multiple lines. |
Spacing (Box Model)
All spacing values are in pixels.
| Property | Description |
|---|---|
gap (or spacing) | Space between child elements. |
padding | Padding on all four sides. |
paddingTop, paddingBottom | Vertical padding overrides. |
paddingLeft, paddingRight | Horizontal padding overrides. |
margin | Margin on all four sides. |
marginTop, marginBottom | Vertical margin overrides. |
marginLeft, marginRight | Horizontal margin overrides. |
Positioning, Visuals & Scrolling
| Property | Type/Options | Description |
|---|---|---|
BGColor | string | table | Background color of the box. |
position | "relative", "absolute" | Layout position strategy. Absolute elements are removed from the flow. |
left, top, right, bottom | number | Offset coordinates used when position is set to "absolute". |
zIndex | number | Rendering order. Higher numbers draw on top of lower numbers. |
opacity | number | Controls transparency from 0.0 (invisible) to 1.0 (opaque). |
borderRadius | number | Rounds the corners of the box's background and borders. |
borderWidth | number | Thickness of the border in pixels. |
borderColor | string | table | Color of the border. |
overflow | "visible", "hidden", "scroll", "auto" | Controls clipping and scrollbars. "scroll"/"auto" enables vertical and horizontal scrolling if content exceeds the container. |
autoScroll | "none", "bottom", "top" | Automatically scrolls the container when new content is added (useful for chat boxes or logs). |
Examples
1. Centered Card
A fixed-size card centered within a full-screen container.
lua
el.VBox({
style = {
w = "100%",
h = "100%",
BGColor = "#000000",
justifyContent = "center",
alignItems = "center"
},
children = {
el.VBox({
style = {
w = 300,
h = 200,
BGColor = "#666666",
p = 20,
gap = 10,
borderRadius = 12
},
children = {
el.Text("Card Title"),
el.Text("This is some content inside the card.")
}
})
}
})2. Scrollable Navigation Bar
A simple Scrollable container with many elements
lua
function Window()
return {
title = "Vulpis Scrolling Demo",
w = 800,
h = 600,
resizable = true,
}
end
function App()
local listItems = {}
for i = 1, 50 do
table.insert(listItems, {
type = "vbox",
style = {
w = "100%",
p = 20, -- Padding inside the item box
marginBottom = 10, -- Space between items
BGColor = "#2A2A35", -- Dark slate background for the item
borderRadius = 8, -- Rounded corners
},
children = {
{
type = "text",
text = "Scrollable Item #" .. tostring(i),
style = {
color = "#FFFFFF",
fontSize = 24,
fontWeight = "bold",
},
},
{
type = "text",
text = "This is some description text for the item.",
style = {
color = "#A0A0A0",
fontSize = 16,
marginTop = 5,
},
},
},
})
end
-- Return the root Virtual DOM node
return {
type = "vbox",
style = {
w = "100%",
h = "100%", -- Force container to bounds of the window
BGColor = "#18181E", -- Main app background
p = 20,
overflow = "auto", --Enables scrolling
},
children = listItems,
}
end