SkillAgentSearch skills...

Flow

Flow is a pure Lua Flexbox-style UI library for Defold, with declarative components, stack-based navigation, markdown rendering, and runtime-built GUI nodes

Install / Use

/learn @Pause-Games/Flow
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Flow logo

Flow — Flex UI Library for Defold

Flow is a Defold library that implements a CSS Flexbox-inspired UI system in pure Lua. No native extensions. No HTML. Just runtime-created GUI nodes with layout computed in Lua.

Install

Add Flow as a Defold library dependency in your game's game.project:

[project]
dependencies#0 = https://github.com/Pause-Games/flow/archive/refs/heads/main.zip

Or pin a tag:

[project]
dependencies#0 = https://github.com/Pause-Games/flow/archive/refs/tags/v1.0.0.zip

This repository exports the flow/ directory through Defold's [library] include_dirs, so after fetching libraries you can require:

local flow = require "flow/flow"

Input bindings are not applied automatically from a dependency. Add touch, scroll_up, and scroll_down in your own project's input binding file.

Quick Start

local flow = require "flow/flow"

function init(self)
  flow.init(self, {
    initial_screen = "hub",
    screens = require "sample/screens",
  })
end

function final(self)
  flow.final(self)
end

function update(self, dt)
  flow.update(self, dt)
end

function on_input(self, action_id, action)
  return flow.on_input(self, action_id, action)
end

function on_message(self, message_id, message, sender)
  return flow.on_message(self, message_id, message, sender)
end

For Defold lifecycle callbacks, prefer flow.init, flow.update, flow.on_input, and flow.on_message. For low-level renderer helpers, use flow.ui.*. For primitive UI constructors, use flow.ui.cp.*. For navigation helpers, message transport, and non-GUI runtime helpers, use flow.nav.*. For centralized logging, use flow.log.*.

Modules

Library (flow/):

  • flow/flow.lua — main facade: wires renderer, navigation, logging, and all components; exposes flow.ui, flow.ui.cp, flow.nav, and flow.log
  • flow/ui.lua — low-level renderer, input, and animation dispatcher behind flow.ui
  • flow/layout.lua — pure Flexbox layout computation (no Defold deps)
  • flow/flex.lua — Yoga-compatible imperative API, exposed as flow.ui.Flex
  • flow/navigation — stack-based navigation with animated transitions behind flow.nav
    • flow/navigation/init.lua — singleton facade used by flow.nav
    • flow/navigation/core.lua — pure router (push/pop/replace/reset)
    • flow/navigation/gui.lua — GUI adapter available as flow.nav.gui
    • flow/navigation/messages.lua — message transport helper exposed on flow.nav
    • flow/navigation/proxy.lua — optional runtime helper exposed as flow.nav.proxy
    • flow/navigation/runtime.lua — non-GUI bootstrap exposed as flow.nav.runtime
  • flow/components/ — UI components (box, text, button, icon, scroll, popup, markdown)
  • flow/bottom_sheet/ — hosted bottom-sheet runtime plus the internal sheet component
  • flow/types.lua — LuaLS type definitions

Sample (sample/):

  • sample/screens.lua — demo screens
  • sample/navigation_bootstrap.script — example .script integration

Navigation Outside GUI

For screens driven by a plain .script (e.g. a gameplay controller with a collection proxy):

local flow = require "flow/flow"

function init(self)
  flow.nav.runtime.init(self, {
    screens = {
      gameplay = {
        url = msg.url("main:/gameplay_controller#script"),
        proxy_url = msg.url("main:/gameplay_proxy#collectionproxy"),
        preload = true,
      },
    },
    initial_screen = "gameplay",
  })
end

function final(self)
  flow.nav.runtime.final(self)
end

function on_message(self, message_id, message, sender)
  if flow.nav.runtime.on_message(self, message_id, message, sender) then
    return
  end
end

Components

local flow = require "flow/flow"

local Box         = flow.ui.cp.Box
local Text        = flow.ui.cp.Text
local Button      = flow.ui.cp.Button
local ButtonImage = flow.ui.cp.ButtonImage
local Icon        = flow.ui.cp.Icon
local Scroll      = flow.ui.cp.Scroll
local Popup       = flow.ui.cp.Popup
local Markdown    = flow.ui.cp.Markdown

Hosted bottom sheets are exposed separately as flow.bottom_sheet.*.

Example:

local flow = require "flow/flow"
local Box = flow.ui.cp.Box
local Text = flow.ui.cp.Text
local Button = flow.ui.cp.Button
local ButtonImage = flow.ui.cp.ButtonImage

return Box({
  key = "root",
  style = { width = "100%", height = "100%", padding = 20 },
  children = {
    Text({ key = "title", text = "Hello", style = { height = 32 } }),
    Text({ key = "subtitle", text = "Brand", font = "heading", style = { height = 28 } }),
    Button({
      key = "cta",
      style = { width = 180, height = 56 },
      on_click = function() print("clicked") end,
      children = {
        Text({ key = "cta_label", text = "Continue", style = { width = "100%", height = "100%" } })
      }
    }),
    Button({
      key = "cta_round",
      image = "button_rounded",
      texture = "button_shapes",
      border = 18,
      color = "#3885e6",
      style = { width = 220, height = 56 },
      on_click = function() print("rounded clicked") end,
      children = {
        Text({ key = "cta_round_label", text = "Rounded Button", style = { width = "100%", height = "100%" } })
      }
    }),
    ButtonImage({
      key = "cta_image",
      image = "castle_siege",
      texture = "guide",
      style = { width = 220, height = 96, justify_content = "end", padding_bottom = 10 },
      on_click = function() print("image clicked") end,
      children = {
        Text({ key = "cta_image_label", text = "ButtonImage", style = { height = 24 } })
      }
    })
  }
})

Notes

  • Primitive constructors live under flow.ui.cp.*.
  • flow.ui.components.* is also available as a longer alias for the same constructors.
  • Text accepts font = "name" for any font registered in the owning .gui; it falls back to "default".
  • Text also supports scale and line_break = true; Icon supports scale in the same shape.
  • Color props should use strings such as "#778899", "#778899cc", "white", "rebeccapurple", or "transparent". Flow supports the standard CSS named-color set, and flow.color.rgb(...) / flow.color.rgba(...) are convenience helpers that return normalized hex strings.
  • Button can use a texture/image background and slice-9 border via image, texture, and border.
  • ButtonImage is a convenience wrapper around Button for image-backed buttons.
  • Markdown can auto-wrap generated text with auto_wrap = true and wrap_width = ...; flatten_formatting = true is optional when you want plain wrapped output. Hosted bottom sheets can run nested sheet.screens flows.
  • Component behaviors are self-registered; simply requiring the component module is enough.
  • Layout is GUI-space only. Window-space mode is intentionally internal.

Documentation

| | | |-|-| | Getting Started | Install Flow as a dependency and build your first screen | | Architecture | How the three layers fit together | | Tutorials | | | 1 — First Screen | Box, Text, mounting a GUI | | 2 — Layout & Style | Flex direction, justify, align, gap, padding | | 3 — Navigation | Screens, push/pop, params, transitions | | 4 — Interactive UI | Buttons, ButtonImage, rounded backgrounds, hover, state mutation | | 5 — Scroll & Lists | Scroll containers and virtual scrolling | | 6 — Overlays | Popup, bottom sheet, animated slide-in | | Guides | | | Best Practices | Keys, node budget, dirty tracking, patterns | | Debugging | Debug mode, log levels, context overrides | | API Reference | | | specs/ | Module-level API specs | | AI | | | AI Reference Sheet | Comprehensive single-file reference for AI agents and LLMs |

View on GitHub
GitHub Stars35
CategoryDevelopment
Updated4d ago
Forks0

Languages

Lua

Security Score

90/100

Audited on Mar 26, 2026

No findings