Skip to content

Commit 53106de

Browse files
committed
Documentation update
Simplify Readme and move details to Documentation/Architecture.md Add ReactNative and tkinter comparisons - not my words - I asked AI to write objective comparisons.
1 parent 8a39cac commit 53106de

4 files changed

Lines changed: 380 additions & 297 deletions

File tree

Documentation/Architecture.md

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
# ActionUI Architecture
2+
3+
## Overview
4+
5+
ActionUI renders SwiftUI views from JSON descriptions. There is no intermediate runtime, virtual DOM, or reconciliation step — JSON is parsed into validated properties and constructed directly as SwiftUI views.
6+
7+
## Pipeline
8+
9+
```
10+
┌─────────────────────────────────────────────┐
11+
│ JSON/Plist Description │
12+
│ { "type": "Button", "id": 1, ... } │
13+
└─────────────────┬───────────────────────────┘
14+
15+
16+
┌─────────────────────────────────────────────┐
17+
│ ActionUIRegistry │
18+
│ - View type registration │
19+
│ - Type lookup and dispatch │
20+
└─────────────────┬───────────────────────────┘
21+
22+
23+
┌─────────────────────────────────────────────┐
24+
│ ActionUIViewConstruction │
25+
│ - validateProperties() │
26+
│ - buildView() │
27+
│ - applyModifiers() │
28+
└─────────────────┬───────────────────────────┘
29+
30+
31+
┌─────────────────────────────────────────────┐
32+
│ ActionUIModel │
33+
│ - State management (@MainActor) │
34+
│ - Action routing │
35+
│ - View value get/set │
36+
└─────────────────────────────────────────────┘
37+
```
38+
39+
### ActionUIRegistry
40+
Maps type strings ("Button", "TextField", etc.) to view construction implementations. Extensible — new view types are registered here.
41+
42+
### ActionUIViewConstruction Protocol
43+
Every view type conforms to this protocol, implementing three methods:
44+
- **validateProperties()** — Validates JSON properties, applies defaults, reports errors/warnings
45+
- **buildView()** — Constructs the SwiftUI view from validated properties
46+
- **applyModifiers()** — Applies styling and behavior modifiers (padding, frame, font, actionID, etc.)
47+
48+
### ActionUIModel
49+
The central state manager. Holds view values, routes action callbacks, and provides the get/set API for client code to read and update view state.
50+
51+
## Supported Components (50+)
52+
53+
**Layout & Containers:**
54+
HStack, VStack, ZStack, LazyHStack, LazyVStack, LazyHGrid, LazyVGrid, Grid, NavigationStack, NavigationSplitView, NavigationLink, TabView, Group, Section, Form, ControlGroup, DisclosureGroup, GroupBox, ScrollView, ScrollViewReader
55+
56+
**Input Controls:**
57+
TextField, SecureField, TextEditor, Picker, ComboBox, DatePicker, ColorPicker, Toggle, Slider, Button, Link, ShareLink, Menu
58+
59+
**Display Elements:**
60+
Text, Label, Image, AsyncImage, ProgressView, Gauge, Table, List, VideoPlayer, Map, Canvas, WebView, Spacer, Divider, EmptyView
61+
62+
**Dynamic Loading:**
63+
LoadableView — Load JSON UI definitions at runtime from files or URLs
64+
65+
## Universal Modifiers
66+
67+
All views inherit modifiers from the base View implementation:
68+
- **Layout:** padding, frame, background, cornerRadius, position, offset
69+
- **Styling:** foregroundColor, font, opacity, shadow, border
70+
- **Sizing:** controlSize (mini, small, regular, large, extraLarge)
71+
- **Behavior:** hidden, disabled, actionID, keyboardShortcut
72+
- **Accessibility:** accessibilityLabel, accessibilityHint
73+
74+
## State Management
75+
76+
Views with integer IDs have their state tracked by ActionUIModel. Client code can:
77+
- **Get values:** Read the current value of any identified view
78+
- **Set values:** Update view values programmatically
79+
- **Get/set properties:** Read or modify view properties at runtime
80+
- **Get/set state:** Access view-specific state (e.g., scroll position)
81+
82+
## Action System
83+
84+
User interactions fire action callbacks identified by string IDs. The action handler receives:
85+
- **actionID** — The string identifier from the view's JSON
86+
- **windowUUID** — Which window the action originated from
87+
- **viewID** — The integer ID of the view
88+
- **viewPartID** — Sub-component identifier (e.g., column index in a table)
89+
- **context** — Optional contextual data (e.g., button title, row index)
90+
91+
## Language Adapters
92+
93+
ActionUI's core is a Swift framework. Language adapters provide bindings for different programming environments:
94+
95+
- **ActionUISwiftAdapter** — Native Swift integration
96+
- **ActionUIObjCAdapter** — Objective-C bridging
97+
- **ActionUICAdapter** — C function API (foundation for other language bindings)
98+
- **ActionUICppAdapter** — C++ bindings
99+
- **ActionUIJavaScriptCoreAdapter** — JavaScriptCore integration
100+
- **ActionUIWebKitJSAdapter** — WebKit JavaScript bridge
101+
- **ActionUI Python Module** — Full Python package with pip install (see [Python Bridge](#python-bridge))
102+
103+
## Python Bridge
104+
105+
The `actionui` Python module provides a complete API for building macOS applications:
106+
107+
```python
108+
import actionui
109+
110+
app = actionui.Application(name="MyApp")
111+
112+
window = actionui.Window.from_file("ui.json", title="My Window")
113+
app.load_and_present_window(window)
114+
115+
@app.action("buttonClicked")
116+
def on_button(ctx):
117+
value = window.get_string(view_id=10)
118+
window.set_string(view_id=20, value=f"You entered: {value}")
119+
120+
app.run()
121+
```
122+
123+
### Application Features
124+
- Multi-window management with per-window state
125+
- Application lifecycle callbacks (will_terminate, should_terminate, etc.)
126+
- Window lifecycle callbacks (window_will_present, window_will_close)
127+
- Native menu bar with CommandGroup and CommandMenu
128+
- File open/save panels with type filtering
129+
- Alert dialogs with custom buttons
130+
131+
### Building
132+
The Python module is built from `ActionUIPython/` using `build_and_install.sh`, which:
133+
1. Builds ActionUI static frameworks via xcodebuild (universal arm64 + x86_64)
134+
2. Compiles the C bridge (`actionui_native.m`) against the frameworks
135+
3. Installs the `actionui` Python package via pip
136+
137+
## Platform Support
138+
139+
- macOS 14.6+
140+
- iOS 17.6+
141+
- iPadOS 17.6+
142+
- watchOS 10.6+
143+
- tvOS 17.6+
144+
- visionOS 2.6+
145+
146+
Platform-specific views (e.g., Table on macOS) are conditionally available. Unsupported features degrade gracefully with validation warnings.
147+
148+
## Tools
149+
150+
- **ActionUIViewer** — Preview JSON files, take screenshots for sharing or AI feedback
151+
- **ActionUIVerifier** — Validate JSON files before deployment
152+
- **ActionUISwiftTestApp** — Test app with examples of all supported view types
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# ActionUI vs React Native
2+
3+
A comparison of ActionUI with React Native, focusing on architecture, philosophy, and trade-offs — setting aside the obvious difference that ActionUI targets only Apple platforms while React Native is cross-platform (iOS, Android, Web).
4+
5+
## Architectural Differences
6+
7+
| Aspect | ActionUI | React Native |
8+
|--------|----------|--------------|
9+
| Runtime | None — JSON parsed directly into SwiftUI | JavaScript engine (Hermes/JSC) with native bridge |
10+
| UI definition | Pure data (JSON) | Code (JSX) that produces virtual DOM |
11+
| Rendering | SwiftUI views directly | Bridge to UIKit/AppKit (New Architecture: Fabric) |
12+
| State | Flat set/get by view ID | useState, useReducer, Redux, Context API, etc. |
13+
| Diffing | None — SwiftUI handles updates | Virtual DOM reconciliation |
14+
| Build toolchain | Xcode, static frameworks | Node.js, Metro bundler, Babel/TypeScript, CocoaPods/Gradle |
15+
| Client language | Any (Python, C, Swift, ObjC, JS, C++) | JavaScript/TypeScript |
16+
17+
## Where ActionUI Excels
18+
19+
### Simplicity
20+
ActionUI has no runtime, no virtual DOM, no reconciliation, no bridge. JSON goes in, SwiftUI views come out. State changes call `set_value()` and SwiftUI handles the rest. There is no state management framework to choose, no component lifecycle to manage, no hooks to understand.
21+
22+
React Native requires understanding JSX, component lifecycle, hooks (useState, useEffect, useMemo, useCallback), the bridge architecture, and typically a state management library. The mental model is significantly more complex.
23+
24+
### True Native SwiftUI
25+
ActionUI produces actual SwiftUI views with full modifier support. It doesn't abstract away the platform — it embraces it. NavigationSplitView, Table, Gauge, Map, DisclosureGroup, and 50+ other components are real SwiftUI views with native behavior.
26+
27+
React Native bridges to UIKit (and AppKit via third-party support). The views are native but the abstraction layer means some platform behaviors are lost or approximated. macOS support is a community effort (react-native-macos), not first-class.
28+
29+
### macOS-First
30+
ActionUI has deep AppKit integration: native menu bars with CommandGroup/CommandMenu, file open/save panels, alert dialogs, multi-window with per-window state, window lifecycle callbacks. This is first-class macOS app behavior.
31+
32+
React Native's macOS support is maintained by Microsoft (react-native-macos) and lacks many macOS conventions — proper menu bars, multi-window, and native panels require significant custom native code.
33+
34+
### Build Toolchain
35+
ActionUI: one Xcode project, `pip install` for the Python bridge. No node_modules, no Metro bundler, no Babel, no TypeScript transpiler, no CocoaPods/Gradle version matrix.
36+
37+
A fresh React Native project pulls hundreds of npm dependencies and requires coordinating versions across the JS and native toolchains. Build issues from version mismatches are common.
38+
39+
### Performance
40+
ActionUI has essentially zero overhead — calling SwiftUI is the entire rendering path. No JS-to-native bridge, no serialization, no virtual DOM diffing.
41+
42+
React Native's bridge adds latency to every interaction that crosses the JS/native boundary. The New Architecture (JSI, Fabric, TurboModules) reduces this but adds its own complexity.
43+
44+
### Language Agnostic
45+
ActionUI's C API means any language that can call C functions can drive the UI: Python, Swift, Objective-C, C++, JavaScript (via JavaScriptCore or WebKit). The UI definition (JSON) is completely separate from the client language.
46+
47+
React Native locks you into JavaScript/TypeScript for app logic.
48+
49+
### Dynamic UI Loading
50+
LoadableView loads new JSON UI definitions at runtime from local files or network URLs. This is a production feature — deployed apps can reconfigure their UI dynamically. This is comparable to React Native's hot reload but available in shipping apps, not just during development.
51+
52+
## Where React Native Excels
53+
54+
### Cross-Platform
55+
React Native targets iOS, Android, and Web from a single codebase. ActionUI is Apple-only. For apps that must run on Android, React Native (or similar cross-platform frameworks) is the practical choice.
56+
57+
### Dynamic UI Construction
58+
React Native's core model is dynamic — every render cycle can produce a completely different component tree based on state. Conditional rendering, lists of dynamic length, and component composition are natural.
59+
60+
ActionUI's UI structure is defined by JSON at window creation. Dynamic behavior comes from property changes (isHidden, items, values) and LoadableView for swapping sections. This covers most practical needs but isn't as flexible as arbitrary component trees.
61+
62+
### Ecosystem
63+
React Native has thousands of third-party components, navigation libraries (React Navigation, Expo Router), animation libraries (Reanimated), and form libraries. The npm ecosystem provides solutions for most common needs.
64+
65+
ActionUI is a focused library without a third-party ecosystem. Its 50+ built-in components cover common UI patterns, but specialized needs require extending the framework.
66+
67+
### Navigation and Routing
68+
React Native has mature navigation solutions with stack navigators, tab navigators, drawer navigators, deep linking, and animated transitions.
69+
70+
ActionUI has NavigationStack, NavigationSplitView, and TabView in JSON, but complex navigation flows with animated transitions between screens are not its primary use case.
71+
72+
### Animations
73+
React Native offers the Animated API and Reanimated library for complex, gesture-driven animations running on the native thread.
74+
75+
ActionUI inherits SwiftUI's built-in animations (which are excellent) but doesn't expose a programmatic animation API from the client side.
76+
77+
### Hot Reload (Development)
78+
React Native's Fast Refresh updates the running app as you edit JS source code, preserving component state. It's a developer tool that significantly speeds up iteration.
79+
80+
ActionUI's iteration cycle is: edit JSON, close window, reopen. No compilation step for UI changes, so the turnaround is fast, but it's not automatic. (A debug reload feature is under consideration.)
81+
82+
## Philosophical Difference
83+
84+
React Native is a **full application framework** — it wants to own the entire app, from navigation to state to rendering. It's designed for large consumer apps with complex interaction patterns.
85+
86+
ActionUI is a **UI rendering service** — it presents views and reports actions, staying out of the way of app logic. The client (Python, Swift, etc.) handles everything else. It's designed for tools, utilities, and applets where the UI is a means to an end, not the product itself.
87+
88+
This is not a limitation — it's a deliberate design choice. For applet-style apps, ActionUI's thin layer is an advantage: less to learn, less to debug, less that can go wrong. The right tool depends on the scope of what you're building.
89+
90+
## Summary
91+
92+
| For this need... | Better choice |
93+
|------------------|---------------|
94+
| macOS applets and tools | ActionUI |
95+
| Cross-platform consumer apps | React Native |
96+
| AI-generated UIs | ActionUI |
97+
| Complex navigation flows | React Native |
98+
| Native macOS integration (menus, panels, multi-window) | ActionUI |
99+
| Large team with JS/TS expertise | React Native |
100+
| Minimal toolchain and dependencies | ActionUI |
101+
| Third-party component ecosystem | React Native |
102+
| Language-agnostic client code | ActionUI |
103+
| Rapid prototyping on Apple platforms | ActionUI |
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# ActionUI Python Bridge vs tkinter
2+
3+
A comparison of ActionUI's Python module with Python's built-in tkinter for building desktop applications on macOS.
4+
5+
## Architectural Differences
6+
7+
| Aspect | ActionUI | tkinter |
8+
|--------|----------|---------|
9+
| UI definition | Declarative JSON | Imperative Python code |
10+
| Rendering | Native SwiftUI views | Tk widgets (non-native look) |
11+
| State model | Set/get values by view ID | Variable tracing (StringVar, IntVar) |
12+
| Event model | Action callbacks by ID | Widget event binding |
13+
| Layout | SwiftUI stacks, grids, modifiers | pack/grid/place geometry managers |
14+
| App structure | JSON defines UI, Python handles logic | Python defines both UI and logic |
15+
16+
## Where ActionUI Excels
17+
18+
### Native macOS Experience
19+
ActionUI renders real SwiftUI views. Buttons, pickers, toggles, tables — everything looks and behaves like a native macOS app. tkinter uses Tk widgets that look out of place on macOS despite theming efforts (ttk).
20+
21+
### Simplicity
22+
A form with text fields, pickers, and buttons is a JSON file. No widget instantiation, no layout manager calls, no variable binding boilerplate. The Python side only handles actions and state — it never constructs UI.
23+
24+
### AI-Friendly
25+
JSON is a format that LLMs generate reliably. Asking an AI to produce a tkinter UI means generating imperative Python code with correct widget hierarchies, geometry management, and callback wiring. ActionUI's JSON schema is regular and predictable.
26+
27+
### Multi-Window
28+
ActionUI has built-in multi-window support with per-window state, window lifecycle callbacks, and menu bar integration. tkinter can do multi-window with Toplevel, but window management, menu bars, and state isolation require manual work.
29+
30+
### macOS Integration
31+
ActionUI provides native file open/save panels, alert dialogs, application menu bar with CommandGroup/CommandMenu, keyboard shortcuts, and proper app lifecycle (will_terminate, should_terminate, etc.). tkinter's macOS integration is limited — file dialogs work but menu bars and app lifecycle are basic.
32+
33+
### Dynamic UI
34+
LoadableView allows swapping UI sections at runtime by loading new JSON from files or network — without rebuilding the window. tkinter requires destroying and recreating widgets.
35+
36+
### 50+ Native Components
37+
Table, NavigationSplitView, Map, VideoPlayer, Canvas, Gauge, DisclosureGroup, ColorPicker, DatePicker — these are SwiftUI components with no tkinter equivalent or with significantly inferior tkinter alternatives.
38+
39+
## Where tkinter Has More Features
40+
41+
### Dynamic Widget Construction
42+
tkinter can create and destroy widgets programmatically at any time. ActionUI's UI structure is defined by JSON at window creation. However, LoadableView, property changes (isHidden, items, etc.), and set/get APIs cover most practical cases.
43+
44+
### Rich Text
45+
tkinter's Text widget supports tags, marks, embedded widgets, and per-character styling. ActionUI's TextEditor is plain text.
46+
47+
### Canvas Drawing (Imperative)
48+
tkinter's Canvas allows imperative drawing — add/remove/move shapes interactively with hit testing and drag support. ActionUI has a Canvas view but it uses declarative drawing operations in JSON properties, which is a different (and arguably cleaner) model for static or data-driven graphics.
49+
50+
### Event Granularity
51+
tkinter exposes mouse motion, key press/release, focus, enter/leave, and drag events per widget. ActionUI fires action callbacks — sufficient for app logic but not for building custom interactive controls.
52+
53+
## Features That Seem Missing But Aren't Needed
54+
55+
### Timers
56+
tkinter has `after(ms, callback)` for scheduling. ActionUI doesn't expose a timer API, but Python threads handle periodic work fine, and UI updates are just `set_value()` calls. A timer synchronized to the UI run loop is rarely needed in applet-style apps.
57+
58+
### Clipboard
59+
tkinter provides `clipboard_get()`/`clipboard_append()`. In practice, the system Edit menu handles user-driven copy/paste in text fields automatically. For scripting, macOS `pbcopy`/`pbpaste` command-line tools cover programmatic clipboard needs. Clipboard operations should be user-initiated, not app-driven.
60+
61+
### Text Input Dialog
62+
tkinter has `simpledialog.askstring()`. In practice, text input belongs in the UI itself (a TextField in the form), not in a modal dialog. ActionUI supports alert dialogs with custom buttons for confirmations.
63+
64+
### Window Positioning/Resizing
65+
tkinter offers `geometry()`, `minsize()`, `maxsize()`. ActionUI sets window properties at creation via JSON. Programmatic window manipulation is rarely needed for applets — the window manager and user handle this.
66+
67+
## Summary
68+
69+
ActionUI is not a tkinter replacement for all use cases. It targets a specific and common pattern: **macOS applets and tools where the UI is a form/dashboard that displays data and collects user input**. For this pattern, ActionUI is simpler, produces better-looking results, and integrates deeply with macOS.
70+
71+
tkinter remains appropriate for cross-platform needs, highly dynamic widget construction, or interactive canvas applications (drawing tools, diagram editors). But on macOS, tkinter's non-native appearance and limited platform integration make ActionUI the better choice for most applet-style applications.

0 commit comments

Comments
 (0)