Greenwood aims to support and optimize around the standard capabilities of the web platform and its features. In particular, the concept of using Web Components as a way to add and isolate interactivity and dynamic content into your application and that it can all be prerendered for you, just like you could do with any server side templating language.
The options for how to design your app effectively comes down to what you're trying to build, so if that's with the native HTMLElement
or something based on it like LitElement (installed separately), Greenwood will take care of the rest.
Below are a couple examples to get you going.
Check out our README for more examples of sites built with Greenwood to see what's possible.
Below is an example of creating a footer component using native HTMLElement
within a page template of a Greenwood project. This is all just vanilla HTML / CSS / JS.
Our component, in a file called src/components/footer.js could look like this
class FooterComponent extends HTMLElement {
constructor() {
super();
// create a closed Shadow DOM
this.root = this.attachShadow({ mode: 'closed' });
}
// run some code when the component is ready
connectedCallback() {
this.root.innerHTML = this.getTemplate();
}
// function can be called anything you want
// return a string to be set to innerHTML, can include variable interpolation!
getTemplate() {
const year = new Date().getFullYear();
return `<footer>This is the header component. © ${year}</footer>`;
}
}
customElements.define('my-footer', FooterComponent);
You can use anything you want for the element's tag name (e.g.
app-footer
,x-footer
, etc), it just needs to have a-
in the name.
You can then use it within a page template.
<!DOCTYPE html>
<html lang="en" prefix="og:http://ogp.me/ns#">
<head>
<script type="module" src="/components/footer.js"></script>
</head>
<body>
<my-footer></my-footer>
</body>
</html>
An alternative like LitElement would work the same way.
Make sure you have installed LitElement with npm first!
src/components/greeting.js
import { html, LitElement } from 'lit';
class GreetingComponent extends LitElement {
constructor() {
super();
}
render() {
return html`
<div>
<h1>Hello World!</h1>
</div>
`;
}
}
customElements.define('x-greeting', GreetingComponent);
<!DOCTYPE html>
<html lang="en" prefix="og:http://ogp.me/ns#">
<head>
<script type="module" src="/components/greeting.js"></script>
</head>
<body>
<x-greeting></x-greeting>
</body>
</html>
Some notes / recommendations about ShadowDOM from our research
<slot>
should be named<slot>
only supports a shallow (one) level of nesting. A<slot>
tag must be within a direct descendant of its:host
.<h3>Content from inside the custom element. (inside HTMLElement)</h3> <h3> <slot name="content"></slot> <!-- will show --> <h3> <div> <h3> <slot name="content"></slot> <!-- wont show --> <h3> </div>