# Cocoanut Specification
## Purpose
A minimal, declarative macOS GUI framework for Rust. Build native AppKit applications using a view tree pattern: one `View` type, one `ViewKind` enum, composable children, single renderer.
## Core Concepts
- **View Tree**: Rust defines a declarative tree of views (VStack, HStack, Text, Button, etc.)
- **Single Renderer**: One `renderer.rs` maps the entire view tree to AppKit NSViews
- **Style Modifiers**: Chainable `.width()`, `.background()`, `.bold()`, `.accessibility()` etc.
- **Event System**: `.on_click()`, `.on_change()` dispatch through ObjC target/action to Rust closures
- **Reactive State**: `State<T>` with `on_change` listeners, `counter_state()`, `bind_label(state, tag, fmt)`
- **Dark Mode**: `Appearance` enum, `.dark()`/`.light()` builder, `set_appearance()` runtime toggle
- **Menu Actions**: `MenuItem::on_action(id)` wires menu items to event callbacks
- **JSON Serializable**: View tree can be serialized via `ViewDesc` for debugging/bridging
## Supported View Types
| VStack | `spacing` | layout only |
| HStack | `spacing` | layout only |
| ZStack | — | layout only |
| Spacer | `min_length` | layout only |
| Text | `text` | NSTextField (non-editable) |
| Label | `text` | NSTextField (non-editable) |
| Button | `title` | NSButton |
| TextField | `placeholder`, `value` | NSTextField |
| SecureField | `placeholder` | NSSecureTextField |
| Checkbox | `title`, `checked` | NSButton (type 3) |
| Radio | `title`, `selected` | NSButton (type 4) |
| Slider | `min`, `max`, `value` | NSSlider |
| Toggle | `title`, `on` | NSButton (type 3) |
| Dropdown | `title`, `options`, `selected` | NSPopUpButton |
| ScrollView | `direction` | NSScrollView |
| TabView | `tabs`, `selected` | NSTabView |
| SplitView | `orientation`, `ratio` | NSSplitView |
| GroupBox | `title` | NSBox |
| ProgressBar | `value`, `max` | NSProgressIndicator |
| Image | `name` | NSImageView |
| TextArea | `placeholder`, `value` | NSScrollView + NSTextView |
| DatePicker | `date` | NSDatePicker |
| ColorPicker | `color` | NSColorWell |
| WebView | `url` | WKWebView |
| TableView | `columns`, `rows` | NSScrollView + NSTableView |
| Custom | `type_name`, `properties` | — |
## Architecture
```
src/
├── lib.rs # Exports, prelude
├── error.rs # CocoanutError enum, Result type
├── view.rs # View + ViewKind + ViewDesc (THE core type)
├── renderer.rs # View tree → AppKit NSViews (single rendering pass)
├── app.rs # App + AppBuilder + Appearance (lifecycle, dark mode)
├── menu.rs # Menu + MenuItem (with action dispatch)
├── event.rs # Global callback registry + ObjC action handler
└── state.rs # Reactive State<T> + bind_label
```
**7 source files. ~2000 lines total.**
## Data Flow
```
Rust: View::vstack().child(View::text("Hi"))
→ ViewKind enum tree with children Vec<View>
→ renderer::render() walks tree recursively
→ Each ViewKind maps to one AppKit NSView class
→ Controls with events get target/action wired to CocoanutActionHandler
→ NSViews added to window's contentView
→ NSApplication event loop runs
→ User clicks button → ObjC handleAction: → dispatch_by_tag → Rust closure
→ State<T>.set() → on_change listeners → bind_label updates NSTextField
```
## Constraints
- macOS only (AppKit)
- Rust edition 2024
- Minimal dependencies: objc, cocoa, thiserror, serde, serde_json