macOS
A facet counter on AppKit
This is the facet + facet_appkit path that v0.0.27 recommends. A Component owns the state. build returns an @ui tree. A click handler finds the one keyed label and writes it. Nothing else in the tree is visited.
macOS only. Other backends wait for a later version.
Manifest
[package]
name = "counter"
version = "0.0.1"
edition = "2026"
[[bin]]
name = "counter"
path = "src/main.cplus"
[dependencies]
stdlib = "*"
facet = "*"
flex_layout = "*"
[macos.dependencies]
facet_appkit = "*"
objc = "*"
appkit = "*"
quartzcore = "*"
webkit = "*"
Source
import "facet/facet" as core;
import "facet/elements" as ui;
import "facet/component" as component;
import "facet/screen" as screen;
import "facet/runtime" as runtime;
import "facet/label" as label;
import "facet_appkit/facet_appkit" as backend;
import "stdlib/option" as option;
import "stdlib/status" as status;
import "stdlib/text" as text;
import "stdlib/vec" as vec;
struct Counter {
clicks: i64,
}
fn bump(_sender: *u8, ctx: *u8) {
let st: *Counter = ctx as *Counter;
{ (*st).clicks = { (*st).clicks } + (1 as i64) };
match label::find("count") {
option::Option[label::Label]::Some(l) => {
var msg: text::Text = text::from_str("clicked ");
let _a: status::Status = msg.append({ (*st).clicks }.to_text().view());
let _l: label::Label = l.set_text(msg.view());
}
option::Option[label::Label]::None => { }
}
return;
}
impl Counter: component::Component {
fn build(ref this) -> core::Node {
let me: *u8 = #addr_of(this) as *u8;
return @ui {
vstack(key: "body") {
label("clicked 0", key: "count")
button("click me", key: "go", on_click: bump, on_click_ctx: me)
}
};
}
}
impl Counter: component::Lifecycle {
fn on_attach(ref this) { return; }
fn on_detach(ref this) { return; }
}
impl Counter: screen::Screen {
fn chrome(this) -> screen::Chrome {
return screen::Chrome::new(title: "counter", width: 360.0f64, height: 200.0f64);
}
fn menu_items(this) -> vec::Vec[screen::MenuItem] {
return vec::new::[screen::MenuItem]();
}
}
fn counter_screen() -> screen::ScreenBox {
return screen::screen_box(Counter { clicks: 0 as i64 });
}
fn main() -> i32 {
backend::install();
var app: runtime::App = runtime::App::new("counter");
app.screen("counter", counter_screen);
match app.run("counter") {
status::Status::Ok => { return 0; }
_other => { return 1; }
}
}
key is the address: find("count"), the agent surface, and the accessibility identifier all use it. The { after vstack(key: "body") must be on the same line.
Build
cpc build && ./target/debug/counter
Click the button. The label should read clicked 1, then clicked 2. The rest of the tree is untouched.
The same tree on Linux or Windows is not recommended on 0.0.27. See facet and the manual overview.
‹ Back to all examples