Skip to content

🤳 Tiny library for simple web components. [1kB]

License

Notifications You must be signed in to change notification settings

nativew/nativeweb

Repository files navigation


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>