Oh this is also a really really good idea too. I hadn’t yet thought about the fact that you might want to reuse the renderer callback across different signals
And having an attribute is certainly a much nicer way of setting that vs doing so in JS multiple times
Really nice. I like the approach!
An issue ppl tend to forget is the dom mutation queuing process.
Frameworkers tend to forget the ominous layout reflow, because thr framework takes care of it for them.
Oh fear not! There's gonna be a part 2 (if not part 3). Just needed some more time to think through the details of reactive properties:
- Should one nested element or multiple be allowed?
- Two way data binding a la Svelte?
- What does a custom renderer entail/even mean in this context?
- Etc etc
yeah that’s always been my stumbling block when i imagine this stuff haha. i think two way binding would be ideal because that unlocks the network too — if you wrapped like yjs with the signals library you could create a realtime multiplayer app declaratively with HTML.
But to be honest, if you have the energy/desire you have my *full* permission to riff on what I've been doing and add a sprinkle of local first to it for a blog post
You're definitely the resident expert in this realm and I would genuinely love to see/read where you would take it
will slot it in behind the four other unfinished posts in my drafts 🥲 don’t think i have the energy rn to figure out the signal binding semantics but i’d be down to take what you come up with and try to make it multiplayer!
This is a super cool post and it has me wondering what a custom element that renders optimized lists and conditionals (e.g. Solid’s mapArray/ and ) would look like and how it would work 🤔
I would say you could drop a in as one of its child elements and then use that to render the data you pass to the element… but what I’m not sure about is how you would determine what has already been server rendered and what you might need to render on the client without diffing.
FAST has a repeat directive that enables you to iterate over an array of data and bind a provided template to each item for rendering. Great for client-side scenarios, not so much for SSR. https://fast.design/docs/getting-started/html-directives#repeat
Thank you! And yes, rendering optimized lists and conditionals is totally a direction I want to explore with Stellar once I've finished exploring about a few more HTML signal ideas (i.e. currently working on a follow up blog post right now)
This seems like the way to go to enable progressive enhancement — always was confused why more frameworks didn’t start with HTML-based state. Love this approach and curious to follow along with your next steps!
Thanks! There are some valid reasons for avoiding. Namely the use of coercion and innerHTML are a bit sketchy
But I also agree on the progressive enhancement point. It feels like a really promising and not very well explored approach! And I feel hopeful there are ways to make it less sketchy
The gist is that it works using a global context variable that all of these functions (signal, computed, effect) are modifying under the hood. Here’s a very simple implementation of a reactive system that uses auto-tracking like this:
Of course! And agreed this is gnarlyyy stuff — literally had to reread that code like 30+ times before it started to sink in and even now it’s still only a loose understanding
3. this.render contains a call to this.signal.get() -- THIS is where the signal gets associated with the effect
4. The computed signal is placed in a watcher
5. When the tracked signal changes the watcher will somehow know and then eventually run the computed signal/effect callback
Yes! I saw and liked your post when you shared it last week! Especially liked the strategy of wrapping styles and markup in computed/signal -- I've never seen anyone do that before
Comments
Have you seen Catalyst? I like how there's referentiality, attributes pointing elements at other elements.
https://github.github.io/catalyst/guide/targets/
Also I do know of Catalyst but have never taken a close look at it. I'll definitely give this docs page a read, thanks for sharing!
SignalElement.addRender(value => typeof number === “number”, () => {/* render */})
window.todoList = () => {}
https://bsky.app/profile/chrisshank.com/post/3lakjvj66us2c
And having an attribute is certainly a much nicer way of setting that vs doing so in JS multiple times
An issue ppl tend to forget is the dom mutation queuing process.
Frameworkers tend to forget the ominous layout reflow, because thr framework takes care of it for them.
whenever i see experiments like this i think about @lea.verou.me’s mavo from way back in 2016. would love to see a modern signals-based take on that.
- Should one nested element or multiple be allowed?
- Two way data binding a la Svelte?
- What does a custom renderer entail/even mean in this context?
- Etc etc
Also I loveeeee that idea. Combining custom elements, signals, and local first has been on my todo list for a very long time now!
You're definitely the resident expert in this realm and I would genuinely love to see/read where you would take it
But I also agree on the progressive enhancement point. It feels like a really promising and not very well explored approach! And I feel hopeful there are ways to make it less sketchy
https://techhub.social/@develwithoutacause/113745127521879756
1. The effect function creates a computed signal
2. The computed signal is passed a callback which calls this.render
1/N
4. The computed signal is placed in a watcher
5. When the tracked signal changes the watcher will somehow know and then eventually run the computed signal/effect callback
2/N
But hopefully that helps a little bit!
https://github.com/hawkticehurst/stellar/blob/vnext/signal-element.js
https://bsky.app/profile/rodydavis.com/post/3lfnncit7ak2g
I also use lit-html for trusted types on the return values which make script injection way harder if not impossible.