To build a foundational UI toolkit that handles 99% of everyday desktop
application needsincluding your window manager and the AST Debuggeryou only
need a surprisingly small set of logical primitives. By borrowing the core
philosophy of CSS Flexbox and Flutter, we can construct almost any interface
using just boxes, text, and interactive inputs.
Here is a proposed minimal widget set, designed to be perfectly expressible
via your JSON-Lisp record and array opcodes.
1. Structural Layouts (The Skeletons)
Instead of absolute positioning, applications wrap their content in flexible
boxes.
* vbox (Vertical Box): Stacks children top-to-bottom.
* hbox (Horizontal Box): Stacks children left-to-right.
* Universal Layout Properties:
* pad (Number): Internal padding in pixels.
* gap (Number): Spacing between child elements.
* flex (Number): Proportional sizing (e.g., 1 makes it stretch to fill
available space).
* scroll (Boolean): If true, overflows create a scrollbar rather than
clipping.
* bg (String): Background color (hex).
2. Display Primitives (The Content)
* text: Standard display text.
* value (String): The text to display.
* color (String): Font color.
* bold (Boolean): Font weight.
* align (String): "left", "center", or "right".
3. Interactive Elements (The I/O)
These elements map directly to your microkernel's intent routing loop.
* button: A clickable action trigger.
* text (String): Button label.
* bg & fg (Strings): Background and foreground colors.
* onClick (Array): The raw intent array to dispatch to the OS (e.g.,
["intent", "sys-ast-api", "dump-process"]).
* input: Single-line text entry.
* value (String): Current text.
* placeholder (String): Hint text.
* onChange (Array): An intent template to fire when the user types (the
client will append the new string to this array before sending).
* textarea: Multi-line text/code editor (critical for your debugger).
* value (String): The code payload.
* monospace (Boolean): Forces a code-friendly font.
* flex (Number): Usually set to 1 so the editor fills the remaining window
space.
Proving the Set: The Debugger Example
To prove this minimal set is "good enough," here is how your complex AST
Debugger UI translates from messy HTML into clean, declarative logic.
The HTML Way (Old):
<div style='padding:10px; height:calc(100% - 20px); display:flex;
flex-direction:column;'>
<div style='display:flex; gap:10px; margin-bottom:10px;'>
<button onclick="...">Load File</button>
<button onclick="...">Dump App Memory</button>
</div>
<textarea style='flex:1; ...'> [Code Here] </textarea>
</div>
The Logical Widget Way (New):
["record",
["str", "type"], ["str", "vbox"],
["str", "pad"], 10,
["str", "gap"], 10,
["str", "children"], ["array",
["record",
["str", "type"], ["str", "hbox"],
["str", "gap"], 10,
["str", "children"], ["array",
["record",
["str", "type"], ["str", "button"],
["str", "text"], ["str", "Load File"],
["str", "flex"], 1,
["str", "bg"], ["str", "#0f0"],
["str", "onClick"], ["array", ["str", "intent"], ["str",
"sys-ast-api"], ["str", "read-file"]]
],
["record",
["str", "type"], ["str", "button"],
["str", "text"], ["str", "Dump App Memory"],
["str", "flex"], 1,
["str", "bg"], ["str", "#f0f"],
["str", "onClick"], ["array", ["str", "intent"], ["str",
"sys-ast-api"], ["str", "dump-process"]]
]
]
],
["record",
["str", "type"], ["str", "textarea"],
["str", "value"], ["get", "state", ["str", "code"]],
["str", "monospace"], true,
["str", "flex"], 1
]
]
]
This completely removes browser DOM awareness from your JSON-Lisp compiler.
The AST just manages data and layout logic; the thin-client translates that
logic into pixels.
If this widget schema looks solid to you, we can implement the recursive
buildWidget JavaScript parser for your thin client's 01_render.js file. Are
you ready to upgrade the display client?