nativeweb

๐Ÿคณ Tiny library for simple web components. [1kB]

Usage no npm install needed!

<script type="module">
  import nativeweb from 'https://cdn.skypack.dev/nativeweb';
</script>

README


Native Web

Tiny library for simple web components.
1kB



import { component, property, Element } from 'nativeweb';

@component('hey-internet')
class Component extends Element {
    @property() emoji;

    render() {
        return `
            <h1>Hey Internet ${this.emoji}</h1>
        `;
    }
}
<hey-internet emoji="๐Ÿ‘‹"></hey-internet>

Native web components

Encapsulated styles and scripts

Simplified with decorators

Tiny footprint


One command to start

npm init nativeweb

Or add to your existing project

npm install nativeweb

Decorators

@component

@property

@event

@customEvent

@query

@queryAll


@component

Define a custom element and add styles. From an external file or the same file. styles can be an array of styles.

import { component, Element } from 'nativeweb';
import styles from './hey-styles.css.js';

@component('some-styles', styles)
class Component extends Element {
    render() {
        return `
            <h1>Some Styles</h1>
        `;
    }
}
import { css } from 'nativeweb';

export default css`
    h1 {
        color: orange;
    }
`;
<hey-styles></hey-styles>

@property

Get an attribute converted to the specified type or define a property with an optional default value.
String, Boolean, Number, Array or Object.

import { component, property, Element } from 'nativeweb';

@component('cool-property')
class Component extends Element {
    @property() cool = 'Cool Prop';
    @property(String) title = 'Default Title';
    @property(Number) multiplier;

    render() {
        return `
            <h1>${this.title}</h1>
            <h2>${this.cool} โžก๏ธ ${2 * this.multiplier}</h2>
        `;
    }
}
<cool-property title="Cool Title ๐Ÿค™" multiplier="3"></cool-property>

@event

Add an event listener to a component, a child element named @name or an external component event.

import { component, event, Element } from 'nativeweb';

@component('easy-event')
class Component extends Element {
    @event() mouseenter = this.onHover();
    @event() click = {
        '@title': this.onClick(),
        '@button': this.onClick()
    };
    @event() ready = {
        'other-component': this.onReady()
    };

    onHover() {
        console.log('Hover Component');
    }
    onClick(e) {
        console.log(e.currentTarget);
    }
    onReady({ detail }) {
        console.log(detail);
    }

    render() {
        return `
            <h1 @title>Easy Event</h1>
            <button @button>Click Me</button>
        `;
    }
}
<easy-event></easy-event>

@customEvent

Create a custom global event, namespaced with the component name. Ready to be dispatched. The listener is in the component above.

import { component, customEvent, Element } from 'nativeweb';

@component('other-component')
class Component extends Element {
    @customEvent() ready = 'Ready ๐Ÿš€';

    connected() {
        dispatchEvent(this.ready);
    }

    render() {
        return `
            <h1>Other Component</h1>
        `;
    }
}
<other-component></other-component>

@query

Query selector an @name child element.

import { component, query, Element } from 'nativeweb';

@component('simple-query')
class Component extends Element {
    @query() title;

    connected() {
        this.title.innerText = 'Better Title ๐Ÿ’ฏ';
    }

    render() {
        return `
            <h1 @title>Good Title</h1>
        `;
    }
}
<simple-query></simple-query>

@queryAll

Query selector all @name child elements.

import { component, queryAll, Element } from 'nativeweb';

@component('all-query')
class Component extends Element {
    @queryAll() title;

    connected() {
        this.title.forEach(el => (el.style.color = 'lightgreen'));
    }

    render() {
        return `
            <h1 @title>One Title</h1>
            <h2 @title>Other Title</h2>
        `;
    }
}
<all-query></all-query>

Lifecycle

render()   โ†’   Renders the component.

connected()   โ†’   Called when the component is inserted in the DOM.

disconnected()   โ†’   Called when the component is removed from the DOM.

adopted()   โ†’   Called when the component is moved to a new document.

attributeChanged()   โ†’   Called when an observed attribute changes.


Methods

this.update()   โ†’   Rerenders the component.


Properties

this.properties   โ†’   Get all attributes.


Tips

Shared style

Composition

Conditional

Loop

Variable element


Shared style

Include global styles in a component.

import { css } from 'nativeweb';
import global from '../global-style.css.js';

export default [
    global,
    css`
        h1 {
            color: orange;
        }
    `
];

Composition

Component composition with default slot and named slot.

import { component, Element } from 'nativeweb';

@component('slot-example')
class Component extends Element {
    render() {
        return `
            <header>
                <h1><slot name="title"></slot></h1>
                <slot></slot>
            </header>
        `;
    }
}
<slot-example>
    <span slot="title">Named slot</span>
    <p>Default slot</p>
</slot-example>

Conditional

Conditional rendering in vanilla JS.

import { component, property, Element } from 'nativeweb';

@component('condition-example')
class Component extends Element {
    @property() isGood = false;

    render() {
        return `
            ${this.isGood ? `<h1>Good</h1>` : ``}
        `;
    }
}

Loop

Render loop in vanilla JS.

import { component, property, Element } from 'nativeweb';

@component('loop-example')
class Component extends Element {
    @property() emojis = ['๐Ÿคณ', '๐Ÿงจ', '๐Ÿงฑ'];

    render() {
        return `
            ${this.emojis.map(item => `<span>${item}</span>`).join('')}
        `;
    }
}

Variable element

Render an element from a property.

import { component, property, Element } from 'nativeweb';

@component('element-example')
class Component extends Element {
    @property() as = 'p';

    render() {
        return `
            <${this.as}>Heading 1</${this.as}>
        `;
    }
}
<element-example as="h1"></element-example>