I recall the property passing model being a nasty abstraction breaker. HTML attributes are all strings, so if you wanted to pass objects or functions to children you had to do that via “props” instead of “attributes.”
I also recall the tag names of web components being a pain. Always need a dash, always need to be registered.
None of these problems broke it; they just made it irritating by comparison. There wasn’t really much upside either. No real performance gain or superior feature, and you got fewer features and a smaller ecosystem.
Even so, Lit is widely used to build very complex apps (Beaker, as you know, Photoshop, Reddit, Home Assistant, Microsoft App Store, SpaceX things, ...).
Property bindings are just as ergonomic as attributes with the .foo= syntax, and tag name declaration has rarely come up as a big friction point, especially with the declarative @customElement() decorator. The rest is indeed like a faster less proprietary React in many ways.
I also didn't often see Lit being used in a way that stuck to the idea that the DOM should be your state. That could very well be because most web devs are coming to it with a background in react or similar, but when I did see Lit used it often involved a heavy use of in-memory state tracked inside of components and never making it into the DOM.
Our decorators aren't required - you can use the static properties block. If you think the DX is better with decorators... that's why we support them!
And we support TypeScript's "experimental" decorators and standard TC39 decorators, which are supported in TypeScript, Babel, esbuild, and recently SWC and probably more.
Regarding state: Lit makes it easier to write web components. How you architect those web components and where they store their state is up to you. You can stick to attributes and DOM if that's what you want. Some component sets out there make heavy use of data-only elements: something of a DSL in the DOM, like XML.
It just turns out that most developer and most apps have an easier time of presenting state in JS, since JS has much richer facilities for that.
That's an ok choice in some cases, but the web clearly moved on from that to be able to have richer interaction, and in a lot of cases, much easier development.
My usual go-to rule is that business logic belongs where the state lives - almost always on the back end for state of any real complexity.
With true web apps like Figma I consider those entirely different use cases. They're really building what amounts to a native app that leverage the web as a distribution platform, it has nothing to do with HTML at all really.
I'm sure you could find counterexamples so that isn't a hard line I'm proposing, but it is my opinion that nearly all website or web app built today over uses client state.
Moving state out of HTML and into JS means we now have to walk this ridiculous tightrope walk trying to force state changes back into the DOM and our styles to keep everything in sync.
Given that problem, reactivity isn't the worst solution in my opinion. It tries to automate that syncing problem with tooling and convention, usually declaratively.
If I had to do it all again though, DOM would still be the source of truth and any custom components in JS would always be working with DOM directly. Custom elements are a great fit for that approach if you stick to using them for basic lifecycle hooks, events, and attribute getters/setters.