Skip to content

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
javascript
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;
      }`),
  ];
});
html
<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.

Tip of the day

Eat vegetables to stay healthy

html
<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
typescript
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:

javascript
define("vanjs-game", Hello);

Now we can just slap that custom element anywhere in our HTML πŸŽ‰

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.