The minimalist reactive web-component
Brick is a thin layer to constructs native webcomponents and make them reactive.
Brick is:
- 👙 minimalist: 74 lines of readable code (non-optimised, uncompressed, no cheating)
- 🌱 low dependency: its single third-party is the minimalist Petit-Dom which itself has no dependency
- ♻️ reactive: updating the state recalculate the Virtual Dom when needed
- 🚀 fast: using virtual dom through a thin layer makes it close to bare-metal
- 💧 simple: that's Vanilla, there isn't much to know, it's a raw class to extend; no magic ✨
View the demo and their source 🧪.
If you're looking for a higher level Web-Components library, checkout Lego that builds Bricks out of HTML web-component files.
Here's a fully working example with no install.
Copy-paste the following in an HMTL file and run it in a browser:
<hello-world name="earth">
<script type=module>
import { h, Component } from '//unpkg.com/@polight/brick/lib'
class HelloWorld extends Component {
init() { this.state = { name: 'world' } }
toggleName() { this.render({ name: 'gaia' }) }
get vdom() {
return ({ state }) => [
h('p', {}, `Hello ${state.name}`),
h('button', { onclick: this.toggleName.bind(this) }, `toggle`),
]
}
}
customElements.define('hello-world', HelloWorld)
</script>
There isn't much to explain, but let's detail a little:
<hello-world name="earth">
is a web-component. That's native.name="earth"
will be sent to the component as{ state: 'earth' }
init() { this.state = { name: 'world' } }
declares thestate
with it's default values. Also, anything that is declared in the state—and only what is declared here—will be reactivetoggleName
is a custom method that will be called on clickget vdom()
is the property that should return a function reprenting your HTML. That function is itself called passing thestate
argument. It should returns a virtual-dom. If you know virtual-dom, React or elm, this writing will be familiarcustomElements.define('hello-world', HelloWorld)
that's the native way in HTML to declare the web-component.
The best documentation is reading the code.
Because it constructs native webcomponents, all the native web-components documentation applies.
You can therefore use slots, disable or enable Shadow DOM, the is
attribute and other web-component or HTML capabilities.
In addition, a couple of extra tools are brought by Brick:
this object is made available to the virtual-dom (and CSS styles). It can be reactive (when declared in the init) and can be updated by the app.
State is fed the following way:
- declared in the
init()
with the default values - attributes of the element in the HTML will overwrite the defaults
- changing values in the object or on the component attributes will update the state values (without re-rendering)
- call
this.render(state)
to update the state and update the interface.
You can initialize whatever you need here.
That's a convenient instance to declare your reactive state
object.
When declaring your state
here, it's properties will be made reactive.
Must return a function that returns a string, an array or a h()
instance.
The structure of h()
takes 3 arguments:
h(<html element (string)>, <attributes (object)>, <children (array, string, or h())>)
.
Same as vdom()
, but returning a CSS style node.
get vstyle() {
return ({ state }) => h('style', {}, 'p{ color: red }')
}
A convenient method to call when the component is attached to the dom.
A convenient method to call when the component is removed from the dom.
When participating to Brick you can simply tune the lib/index.js and import it. petit-dom is the only dependency. You may need to adapt its path.
Compiling is convenient but not future-proof. Compilation is done with Rollup and will break in the future. Therefore it is not a high dependency and should never be.
That said, plugins for bundling, minifying and gziping are set up.
You may install them all with npm i --env=dev
.
npm run build
to bundle/minimify/gzip dist/index.js.
That will be bandwidth-friendlier.