Examples β
INFO
This page is under construction.
Contributions are most welcomed! π
This page will focus on showing more practical examples that reflect real world problems that can find a solution with Van Elements.
These examples were written with the following philosophy:
- most problems involving reactive UIs can be solved with VanJS
- custom elements are a good fit for hydrating reactive logic into the DOM
TIP
Shadow DOM can be useful for isolating specific styles. Parts that need to be exposed can just live in the slots.
If it gets in the way, just disable it. It is not as big of a deal as you might think.
1. Reusable confirmation modal β
This example illustrates how to create a self-contained confirmation modal. It uses a few techniques:
- slots to populate a custom trigger
- a custom
submit
event that allows to intercept actions from outside the component - Shadow DOM isolation
Please confirm
Are you sure you want to do this?
Code
define("confirmation-modal", ({ attr, $this }) => {
const confirmLabel = attr("confirm");
const cancelLabel = attr("cancel", "Close");
const onConfirm = () => {
modal.close();
$this.dispatchEvent(new Event("submit"));
};
const modal = dialog(
div({ class: "mainContent" }, slot()),
div(
{ class: "actions" },
button({ onclick: () => modal.close() }, cancelLabel),
() => confirmLabel.val && button({ onclick: onConfirm }, confirmLabel.val)
)
);
return [
slot({ name: "trigger", onclick: () => modal.showModal() }),
modal,
// Some styles
style(`
dialog{
padding: 2rem;
}
dialog::backdrop{
backdrop-filter:blur(5px);
}
.mainContent{
text-align: center;
}
.actions{
display: flex;
justify-content: space-around;
}
button{
border:1px solid;
font: inherit;
padding: .5rem 1rem;
background: transparent;
cursor: pointer;
}`),
];
});
<confirmation-modal cancel="No" confirm="Yes" onsubmit="alert('Confirmed')">
<button slot="trigger">Click to confirm</button>
<h3>Confirmation</h3>
<p>Are you sure you want to do this?</p>
</confirmation-modal>
Now, thanks to the power of custom element reusability, we can reuse that confirmation modal anywhere, with custom text and actions.
Eat vegetables to stay healthy
<confirmation-modal>
<button slot="trigger">Open tip π‘</button>
<b>Tip of the day</b>
<p>Eat vegetables to stay healthy</p>
</confirmation-modal>
2. Normal VanJS code β
Van Element is just a way to hydrate VanJS. So we could simply take VanJS code and bind it to a custom element tag, and Van Element will put it in the DOM for us!
As an example, let's shamefully take the Hello world program from VanJS's home page π€«
Code
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
const Run = (sleepMs: number) => {
const steps = van.state(0);
(async () => {
for (; steps.val < 40; ++steps.val) await sleep(sleepMs);
})();
return pre(
() =>
`${" ".repeat(40 - steps.val)}ππ¨Hello VanJS!${"_".repeat(steps.val)}`
);
};
const Hello = () => {
const dom = div();
return p(
dom,
button({ onclick: () => van.add(dom, Run(2000)) }, "Hello π"),
button({ onclick: () => van.add(dom, Run(500)) }, "Hello π’"),
button({ onclick: () => van.add(dom, Run(100)) }, "Hello πΆββοΈ"),
button({ onclick: () => van.add(dom, Run(10)) }, "Hello ποΈ"),
button({ onclick: () => van.add(dom, Run(2)) }, "Hello π")
);
};
In order to hydrate this into the DOM, we just have to bind that VanJS function to a custom element tag:
define("vanjs-game", Hello);
Now we can just slap that custom element anywhere in our HTML π
<vanjs-game></vanjs-game>
As it is now, this component looks ugly because we did not style it. We have 2 solutions:
- Style it within the Shadow DOM. This will make our component truly isolated and reusable.
- Disable the Shadow DOM, and style it with external stylesheets. Our component will depend on those stylesheets and isn't truly reusable anymore, but we can now use our favorite CSS framework to make it look beautiful!
Choose whichever option you prefer. People like to get emotional over the Shadow DOM, but in most cases it's not needed.