# 🥥 Cocoanut
A minimal, declarative macOS GUI framework for Rust.
## Why Cocoanut?
| objc | Low | Unsafe | Steep | Raw FFI |
| cocoa | Low | Unsafe | Steep | Raw AppKit |
| cacao | Mid | Safe | Medium | Cross-platform |
| **cocoanut** | **High** | **Safe** | **Gentle** | **macOS native** |
## Quick Start
```rust
use cocoanut::prelude::*;
fn main() -> cocoanut::Result<()> {
let count = counter_state(1, 2, 3);
#[cfg(not(feature = "test-mock"))]
cocoanut::state::bind_label(&count, 100, |v| format!("Count: {}", v));
app("Counter")
.size(400.0, 300.0)
.build()
.root(
View::vstack()
.child(View::text("Counter").bold().font_size(20.0))
.child(View::label("Count: 0").font_size(32.0).tag(100))
.child(View::hstack()
.child(View::button("+1").on_click(1))
.child(View::button("-1").on_click(2))
.child(View::button("Reset").on_click(3))
)
)
.run()
}
```
## Architecture
7 source files. ~2000 lines. 26 view types. 29 tests.
```
view.rs → View + ViewKind enum (the ONE core type)
renderer.rs → View tree → AppKit NSViews (single pass)
app.rs → App lifecycle + Appearance (dark mode)
event.rs → Callback registry + ObjC action handler
state.rs → Reactive State<T> + bind_label
menu.rs → Menu bar with action dispatch
error.rs → Error types
```
## 26 View Types
- **Layout**: VStack, HStack, ZStack, Spacer
- **Text**: Text, Label
- **Controls**: Button, TextField, SecureField, Checkbox, Radio, Slider, Toggle, Dropdown
- **Extended**: TextArea, DatePicker, ColorPicker
- **Containers**: ScrollView, TabView, SplitView, GroupBox, WebView, TableView
- **Data**: ProgressBar, Image
- **Extensible**: Custom
## Features
- **Reactive State** — `State<T>` with `on_change` listeners
- **Event System** — `event::register(id, closure)` + ObjC target/action dispatch
- **Dark Mode** — `.dark()` / `.light()` / `set_appearance()` at runtime
- **Accessibility** — `.accessibility("label")` on any view
- **Menu Actions** — `MenuItem::on_action(id)` wires to callbacks
- **Style Modifiers** — `.width()`, `.bold()`, `.background()`, `.on_click()`
- **JSON Serializable** — `ViewDesc` for debugging/bridging
## Examples
```bash
cargo run --example minimal_app # basic view tree
cargo run --example counter_app # reactive state + dark mode
cargo run --example ui_showcase # all 26 view types
```
## License
Apache-2.0