--- url: /start.md description: >- Get started with Elena. Learn how to install the library, build your first Progressive Web Component, and bundle a library of Progressive Web Components. --- # Quick start The fastest way to get started is to include the following directly into your webpage: ```html ``` ```html ``` > \[!WARNING] > This relies on the unpkg CDN and is not recommended for production. For production use, install `@elenajs/core` locally and bundle your components with `@elenajs/bundler`. ## Installation To install Elena as a dependency in your project, run: ::: code-group ```sh [npm] npm install @elenajs/core ``` ```sh [yarn] yarn add @elenajs/core ``` ```sh [pnpm] pnpm add @elenajs/core ``` ```sh [bun] bun add @elenajs/core ``` ::: Then import Elena in your component files: ```js import { Elena } from "@elenajs/core"; ``` ## Building your first component There are three types of Progressive Web Components: 1. **Composite Components** that wrap and enhance the HTML composed inside them. All of their HTML and CSS lives in the Light DOM. You could also call these [HTML Web Components](https://adactio.com/journal/20618). 2. **Primitive Components** that are self-contained and render their own HTML. All of their CSS lives in the Light DOM together with the base HTML required for rendering the initial state. 3. **Declarative Components** that are a hybrid of these and utilize [Declarative Shadow DOM](#_3-declarative-components). > \[!TIP] > Elena doesn’t force you to think about this taxonomy. They’re all just components, and you choose how to build yours. But since [Progressive Web Components](/components/overview) is a design philosophy rather than a library feature, understanding the distinction between these approaches helps when deciding what fits your use case. ### 1. Composite Components A Composite Component enhances whatever HTML is composed inside it, applying styling and behavior around it. It has no `render()` method and never touches its children. ::: code-group ```js [JavaScript] import { Elena } from "@elenajs/core"; /** ░█ [ELENA]: Composite Component example */ export default class Stack extends Elena(HTMLElement) { static tagName = "my-stack"; static props = ["direction"]; direction = "column"; } Stack.define(); ``` ```css [Styles] @scope (my-stack) { :scope { display: flex; justify-content: flex-start; align-items: flex-start; flex-flow: column wrap; flex-direction: column; gap: 0.5rem; } :scope[direction="row"] { flex-direction: row; } } ``` ::: #### Usage ```html
First
Second
Third
``` ### 2. Primitive Components A Primitive Component owns and controls its inner HTML markup. Two things to know to get started: * **`html`** is Elena’s tagged template function. It auto-escapes interpolated values to prevent XSS, and nested `html` fragments pass through without double-escaping. * **`this.text`** is a built-in reactive property. Elena captures any text content placed inside the element before hydration, so you can pass text as a child node or set it as a property. Utilizing this helps to avoid layout shifts. ::: code-group ```js [JavaScript] import { Elena, html } from "@elenajs/core"; /** ░█ [ELENA]: Primitive Component example */ export default class Button extends Elena(HTMLElement) { static tagName = "my-button"; static props = ["variant"]; variant = "default"; render() { return html` `; } } Button.define(); ``` ```css [Styles] @scope (my-button) { :scope, *:where(:not(img, svg):not(svg *)), *::before, *::after { all: unset; display: revert; } :scope { --my-button-bg: pink; display: inline-block; } :scope:not([hydrated]), .my-button:is(button) { background: var(--my-button-bg); display: inline-flex; } :scope[variant="primary"] { --my-button-bg: green; } :scope[variant="danger"] { --my-button-bg: red; } } ``` ::: #### Usage ```html Save Cancel ``` ### 3. Declarative Components A Declarative Component utilizes Declarative Shadow DOM which lets you define a shadow root directly in HTML using a `