/velvet

Experimental JavaScript framework for building supercharged web components. Mirror.

Primary LanguageJavaScriptMIT LicenseMIT

Velvet

Velvet, an experimental JavaScript framework for building supercharged web components.

Summary

A template like this...

<script>
  let count = 0;

  function increment () {
    count += 1;
  }
</script>

<button @click={increment}>
  Clicked {count} times
</button>

...is transformed into a web component with efficient DOM mutations...

import { append, clone, define, html, on, signal, text, traverse } from '@intrnl/velvet/internal';

let template0 = html('<button>Clicked <!> times</button>');

function setup ($$root, $$host) {
	let count = signal(0);

	function increment () {
		count.value += 1;
	}

	let fragment0 = clone(template0);

	let marker0 = traverse(fragment0, [0, 1]);
	let child0 = traverse(fragment0, [0]);

	text(marker0, () => count.value);
	on(child0, 'click', increment);

	append($$root, fragment0);
}

export default define('x-app', setup, {}, []);

Overview

Hello, world!

Velvet components are self-contained fragments of HTML-like templating along with related scripting and styling code for it, written in a .velvet file.

<h1>Hello, world!</h1>

These components are generated into a valid web component, and are named based off their file names by default, so Greeting.velvet becomes x-greeting, and you can use it as you would with regular HTML elements.

<x-greeting name='world'></x-greeting>
let greet = document.createElement('x-greeting');
greet.name = 'world';

Expressions

Our current component looks a little empty, so let's give it some flair by first defining a <script> element to define our name variable in.

<script>
  let name = 'world';
</script>

<h1>Hello, world!</h1>

We can then refer to the name variable within the template:

<h1>Hello, {name}!</h1>

These curly braces here acts as a window to running JS expressions right within the template, so we can do other things like calling a format function like so:

<script>
  const today = new Date();
  const formatter = new Intl.DateTimeFormat('en-US', { weekday: 'long' });
</script>

<p>Today is {formatter.format(today)}</p>

These curly braces can also be used to control element attributes

<script>
  let name = 'Katherine Johnson';
  let src = 'https://i.imgur.com/MK3eW3As.jpg';
</script>

<h3>Amazing scientists</h3>

<img src={src} alt={name} />

Styling

Velvet components can have a <style> tag, where all the styling are scoped to the component. They can't affect other elements that are elsewhere in your app.

<p>This is a paragraph.</p>

<style>
	p {
		color: purple;
		font-size: 2em;
	}
</style>