I'm sure many will disagree, but I have doubts that pure declarative-reactive is the "right" shape for an all-purpose native UI framework. In my experience, Kotlin+Compose shares many of the same warts… its main redeeming quality is that it's better than Android Framework (most of the time), which is low bar to clear.

These frameworks have a number of good ideas but they don't necessarily combine in a way that transcends high quality traditional imperative frameworks with declarative-reactive bits sprinkled throughout, at least for more complex apps. SwiftUI and its ilk work best for super simple tabs-and-flat-lists sorts of apps.

Do you have an example of where "the ideas don't combine well"? Or where an imperative approach is truly better?

In my experience the solution is often to use the appropriate architecture underneath your UI layer. Basically you build a data structure that represents your UI and always hand this entire structure to the declarative UI layer. Underneath the UI layer, you can still use imperative code to manipulate the data structures. The benefit of the reactive/declarative approach is that you don't have to think about how changes in the data need to be reflected in the UI. That's the framework's job.

Note: With "data structure" I don't mean "build a shadow DOM". I mean something specialized to your use case.

One example of where I think imperative generally does better is UI that requires substantial setup or customization.

In SwiftUI, that means endless chains of modifiers, and in Compose this means monstrous constructors and modifier chains. Both get really ugly and painful to read quickly, and there's not a lot that can be done about it apart from breaking everything out into smaller views (which only goes so far). The amount of boilerplate saved isn't worth the trade, in my opinion.

In an imperative setup, there's still a lot of code but there are more options for organization, readability, and overall clarity. One can break things up with comments, break out setup into functions with self-explanatory names (that the IDE can then quick jump to, as a bonus), etc.

Yes, it's easier to get tripped up with imperative frameworks if one isn't thoughtful with managing their data, but much of the time that code only needs to be gotten right once.

I think open source is the right move here. The great thing about Flutter is you get the declarative UI to build a lot of standard screens easily but you can always drop down to lower levels, inspect the standard components, mix and match with your custom implementation. You can mix UKit and SwiftUI but there’s way more friction due to the closed nature of the SDK.

Fully agree (been an early Flutter adopter!). It's always the right too for the right job, declarativness makes a lot of sense for most UIs. UIs are surprisingly more complicated than one might think, there is accessibility/ theming/ keyboard traversal etc., just declaring UI and letting the framework figure out the rest has held up pretty well.

And because of the open source nature you can always drop down in layers, just a few weeks ago I made a very specific engine optimization, all while the application code on-top can stay declarative!

Perhaps. Certainly source visibility makes life easier as a dev who has to live with these frameworks on a daily basis. That said, I think frameworks should strive to have a wide and deep enough set of widgets that in most cases, devs won't need to resort to custom implementations to do what they need to.

It also doesn't fix problems inherent to declarative UI, like readability breaking down easily and certain things that would be a cinch in an imperative framework being extremely awkward to implement.