Palette
    Preparing search index...

    In this guide, we'll make a Palette Component from scratch using two different approaches. First, we'll use the define() helper function. Then, we'll look at how to make a class-defined Component.

    A Component is just a JavaScript class that extends the HTMLElement class. That is the same base class for all standard HTML tags in JavaScript.

    We'll define our component with the define() helper. We'll call it <counting-button>,

    import { define, html } from "@rusticarcade/palette";

    define("counting-button", {
    template: html`
    <button>
    I've been clicked 0 times
    </button>
    `
    });

    What've we got here? Not a lot:

    1. We imported the define and html helpers
    2. We used define() to define a Palette component with the tag name counting-button
    3. We used the html helper to create an inline HTML template for our component

    If you load that script in an HTML file with <counting-button></counting-button> in the markup, your component will render right there! It should be a blank, boring, awful, terrible button.

    Before we go any further, our button needs to look fabulous. We'll add some css using the css helper.

    import { define, html, css } from "@rusticarcade/palette";

    const CountingButton = define("counting-button", {
    template: html`
    <button>
    I've been clicked 0 times
    </button>
    `

    styles: css`
    button {
    font-size: 2em;
    border: 3px dotted black;
    background-color: #ff33cc;
    }
    `,
    });

    Perfect.

    Now that our button is brilliant, we can take a look at what we've got.

    The css helper wraps a string of CSS into a CSSStyleSheet instance which the Component in turn uses for the template.

    Internally, the Component creates a ShadowRoot which it renders the template into. The stylesheet is adopted to the shadow root, so it only affects the contents of your Component.

    Put simply: Styles for Palette components are scoped to the component

    Now, about that counting button...

    Our button doesn't do anything because it is terrible but that is okay because we are going to make it wonderful by adding some stateful data.

    import { define, html, css } from "@rusticarcade/palette";

    const CountingButton = define("counting-button", {
    template: html`
    <button>
    I've been clicked ${"$count"} times
    </button>
    `,

    styles: css`
    button {
    font-size: 2em;
    border: 3px dotted black;
    background-color: #ff33cc;
    }
    `,

    initialState: { count: 0 },
    });

    A few changes here. Be sure to notice the change to the template!

    We're now using one of the features of the html helper: interpolating strings as placeholder notations. We'll dive further into templating later, but for now, all that matters is that "$count" string will be replaced with count from the state data we just added.

    The component will render the template, pull in the count from initialState, and BOOM! The button is exactly as it was and still doesn't do anything.

    But that's okay, we're so close! We just gotta make the number go up. Love that.

    The last piece of the puzzle is to add a handler when clicking on the button.

    Palette Components separate Events from Templates. You can define managed event listeners in your Component's script() hook:

    import { define, html, css } from "@rusticarcade/palette";

    const CountingButton = define("counting-button", {
    template: html`
    <button>
    I've been clicked ${"$count"} times
    </button>
    `,

    styles: css`
    button {
    font-size: 2em;
    border: 3px dotted black;
    background-color: #ff33cc;
    }
    `,

    initialState: { count: 0 },

    script() {
    this.listen("button", "click", () => {
    this.liveState.count += 1;
    });
    }
    });

    Bam. That button's destiny has been fulfilled, and you've created your first Palette Component.

    You can entirely forego the define() helper if you would prefer more verbose but finer-grained control over your component definition.

    Instead, just extend the Component class:

    import { Component, html, css } from "@rusticarcade/palette";

    class CountingButton extends Component {
    static tagName = "counting-button";

    static template = html`
    <button>
    I've been clicked ${"$count"} times
    </button>
    `;

    styles = css`
    button {
    font-size: 2em;
    border: 3px dotted black;
    background-color: #ff33cc;
    }
    `;

    initialState = { count: 0 };

    script() {
    this.listen("button", "click", () => {
    this.liveState.count += 1;
    });
    }
    };

    // You can also just use customElements.define()
    Component.register(CountingButton);