← Back to context

Comment by bschwindHN

11 hours ago

Is your UI kit open source? I do think calling into the native OS toolkits is the way to go, when they exist.

I'm curious if you use winit for windowing, or something lower level that's just mac specific.

I ported the leptos rust web framework to run on native platforms. Currently it works on ios, macos and linux (GTK). Eventually want to also add support for windows and TUI as well. It uses taffy for layout - which gives you the same flexbox and grid layout engines that web browsers use. Components are all fully native for the platform, via their corresponding binding crates (objc, gtk4, etc).

UI library is here: https://github.com/josephg/leptos-native

And here's the schedule viewer app I made with it. It runs silky smooth on device: https://github.com/josephg/dweb-sched

The whole project is currently experimental & vibe coded. It's missing a lot of components, and it has bugs. I'm currently rewriting it by hand to do it properly.

  • SwiftUI’s diffing is such a mess that I wouldn’t be surprised if fine-grained reactivity of a toolkit binding UIKit like this worked better. Do you have decent support for long lists via UITableView yet? Edit: it seems so!

    • Yeah! I added it for my ios scheduling app.

      I tried to learn SwiftUI a few years ago. XCode was horribly slow, and it would hang and crash all the time, even when working on small example projects. I'm excited by the thought that I can use any rust IDE to write UI code. Rust's compiler, toolchain and IDEs seem way more reliable.

      The view! builder macro at the moment is designed to look like JSX, since it was ported directly from leptos. But I'm considering dropping the jsx and using a fluent API. Something like this:

          let count = RwSignal::new(0u32);
      
          let view = vstack().padding(16.0).gap(12.0)
              .child(label().text(move || format!("Count: {}", count.get())))
              .child(
                  hstack().gap(8.0)
                      .child(button()
                          .on_click(move |_| count.update(|c| *c = 0))
                          .text("Clear"))
                      .child(button()
                          .on_click(move |_| count.update(|c| *c -= 1))
                          .text("-1"))
                      .child(button()
                          .on_click(move |_| count.update(|c| *c += 1))
                          .text("+1"))
              );
      

      Code is a bit less readable like this, but autocomplete and cmd+click all works out of the box in your IDE.