Closed Nefcanto closed 3 months ago
Hi @Nefcanto , as stated in the docs, you need to use onInput$
.
Here's a demo working: https://stackblitz.com/edit/qwik-starter-aqqd68?file=src%2Froutes%2Findex.tsx,src%2Fcomponents%2Flogin-form.tsx
I suggest to you — if you are not there — to join the Qwik discord channel.
Regards!
@fprl, to be honest, I needed onKeyDown$
. But that's not the point here. I want to know how the community creates headless components. How do they separate behavior from structure in Qwik?
@Nefcanto then this is not an issue for GH, right? I recommend you to visit the Discord and ask the community or check the multiple questions that have been done in the past. There is also qwik-ui and you can learn how to handle headless component from their codebase (and discord).
@fprl, with respect, I disagree. It could be a page in the advanced menu of the docs. Many teams come across this requirement and it's better to have an official way for doing so.
@Nefcanto no problem at all. I understand but sometimes it's a bit subjective topic how to build things. Maybe someone from the core team thinks this is a good idea!
You can have a look at QwikUI repository There are a lot of headless components to check. This is a special case but we can create a cookbook to show how do this kind of things. @thejackshelton WDYT?
https://qwikui.com/contributing/
Some of this is documented here. Although part of it is a bit out of date and could be updated, I will add it as a task in our upcoming sprint. Qwik UI is a good resource to look at.
We use PropsOf
to type it to a particular piece of markup, and then consumers have the ability to customize further by passing signals to the root component piece with the bind:x syntax.
@Nefcanto like @fprl mentioned it largely depends on the approach.
What you're doing with the props resembles a more hooks based approach (where it's assumed the user owns the markup), if you're doing this in a component then it is not composable.
Composability provides granular access to each component parts, so you can wrap them and add your own event listeners, props, etc.
I'm not sure yet if this is the responsibility of the Qwik docs to explain. We have learned some clever patterns though (for example inline components) that need to be documented which I will document in core here soon 👍 .
@Nefcanto I'd love to hear your thoughts on this. Did you implement your headless solution?
@thejackshelton, thank you for the explanation. The the user owns the markup was a key point in what you said.
@gioboa and @thejackshelton, for us we think of the domain. Domain is the basis here. Let's talk about a mini-cart component.
These are the domain requirements:
Based on these requirements, we come up with a hook:
import { useCart } from "Sales"
Then in an instance of a mini-cart, we will write:
const MiniCart = () => {
const {
increaseBehavior,
decreaseBehavior,
removeBehavior,
items,
total,
emptyCartBehavior,
} = useCart()
return <>
{
items.map(item => <div>
<h1>{item.title}</h1>
<button {...increaseBehavior>More</button>
<button {...decreaseBehavior}>Less</button>
</div>)
}
</>
}
As @thejackshelton said this is a hook-based approach that assumes the user owns the markup. But this means that creating good markup is a responsibility for the leaf developer. For example buttons and aria-* attributes.
Thus we use atomic UI to give them basic components with these built-in features:
import { Button } from "Base"
<Button {...increaseBehavior} class="bg-red-400">More</Button>
Or
import { OrderItem } from "Base"
<OrderItem
item={item}
class="bg-slate-400 mx-10 my-6"
itemClass="font-bold"
buttonClass="bg-red-400"
/>
This means that our leaf developers (who create instances of mini-carts on different websites) can:
That's what we do now.
Thanks @Nefcanto for the suggestion. I don't think any other framework has that kind of page in their docs, because it is either very specific to your application, or complex if you're a UI library because you need to support a lot of cases. Also it depends on the developer's preferences. I'm not sure we could condense all of that into one route, but maybe it's worth a try some time later once v2 is stable and the more urgent issues for the docs have been tackled.
Suggestion
I want to create a login form that developers can style for each project. Based on my experience in React, I tried to separate behavior from UI and pass the behavior, which is a common practice. For example in react-dropzone, you basically pass the props as
<input {...getInputProps()} />
.So, I tried to create the most basic headless component for a phone number field. I expect my developers to write this code in our projects:
So, I tried to create a signal in the base and create a $ function, and I passed them:
But nothing gets printed to the console.
So, can you please create a page in the advanced menu to show how should we create headless components in Qwik?