Getting Started with Espalier
Espalier is a web component library built on the Lit framework and distributed as standard ES modules. Because every Espalier element is a native custom element, it works in any framework — or no framework at all.
This guide walks you through installation, initial setup, and your first component.
Installation
Install the package from npm:
npm install @taprootio/taproot-controls
If your environment is not already configured for GitHub Packages, make sure the @taprootio scope points at https://npm.pkg.github.com and that an auth token is available.
Peer Requirements
Espalier ships with Lit as its only runtime dependency. If your project already uses Lit, the existing installation will be shared automatically through npm's dependency resolution.
Browser Support
Espalier requires Chrome/Edge 120+, Firefox 128+, or Safari 18+. If your deployment has a managed browser policy, check the Browser Support page for the full requirements matrix and required polyfills before proceeding.
Setting Up the Root
Every Espalier application starts with <esp-root>. This element is the orchestrator — it generates the CSS custom property cascade that every child component inherits for color, typography, and spacing.
Place it as high in the DOM as possible, typically wrapping your entire application:
<esp-root>
<!-- Your application content goes here -->
</esp-root>
<esp-root> accepts light-theme and dark-theme attributes, each of which holds a Base64-encoded partial theme object. Use the scheme attribute to choose which resolved theme is active:
<esp-root
scheme="light"
light-theme="eyJzZWVkQ29sb3IiOiJva2xjaCgwLjcgMC4xNSAyODUpIn0=">
<!-- themed content -->
</esp-root>
You can provide either scheme override, both, or neither. Omitted fields inherit from Espalier's built-in defaults. See the Theming guide for the full theme model.
Using Components
Import the components you need. Each import registers the corresponding custom element on the global registry:
import "@taprootio/taproot-controls/root";
import "@taprootio/taproot-controls/box";
import "@taprootio/taproot-controls/button";
import "@taprootio/taproot-controls/form";
import "@taprootio/taproot-controls/form-item";
import "@taprootio/taproot-controls/input";
import "@taprootio/taproot-controls/pickers/pick-one";
import "@taprootio/taproot-controls/pickers/item";
Or import everything at once:
import "@taprootio/taproot-controls";
Once imported, use the elements directly in HTML:
<esp-button label="Save" variant="primary"></esp-button>
Building a Simple Form
Espalier form components participate in the browser's native form lifecycle through ElementInternals. Wrap fields in <esp-form> and <esp-form-item> to get labels, validation, and layout for free:
<esp-form>
<esp-box>
<esp-form-item label="First name" field-name="firstName">
<esp-input required></esp-input>
</esp-form-item>
<esp-form-item label="Email" field-name="email">
<esp-input input-type="email" required></esp-input>
</esp-form-item>
<esp-form-item label="Country" field-name="country">
<esp-pick-one required placeholder="Choose a country">
<esp-picker-item text="United States" value="us"></esp-picker-item>
<esp-picker-item text="Canada" value="ca"></esp-picker-item>
<esp-picker-item text="United Kingdom" value="gb"></esp-picker-item>
</esp-pick-one>
</esp-form-item>
<esp-button label="Submit" variant="primary" button-type="submit"></esp-button>
</esp-box>
</esp-form>
Without any extra flags, <esp-form> behaves like a native form submission. If you add use-fetch, Espalier intercepts the submit and dispatches esp-submit, esp-submit-response, and esp-submit-error events around the request lifecycle.
Page Layout
For full-page applications, use <esp-page> inside <esp-root> to establish the document structure with a header, navigation, and content area:
<esp-root>
<esp-page>
<esp-header slot="header" text="My Application">
<esp-burger slot="burger"></esp-burger>
</esp-header>
<esp-vertical-menu slot="nav">
<!-- menu items -->
</esp-vertical-menu>
<main>
<!-- page content -->
</main>
</esp-page>
</esp-root>
Browser Polyfills
Espalier is built to browser standards. Where a standard is emerging but not yet universally available, the consuming application is responsible for loading the polyfill. This keeps the library dependency-free and ensures that polyfills are dropped the moment browser support lands — without waiting for a library update.
See Browser Support for the minimum version matrix and required polyfills, or the Caveats guide for detailed per-feature rationale.
Next Steps
- Browser Support — Minimum browser versions, required polyfills, and support policy.
- Caveats — Detailed per-feature compatibility rationale and known limitations.
- Color System — How Espalier uses OKLCH and APCA for perceptually accurate, accessible color.
- Typography — Fluid type scales and modular spacing.
- Layout — Grid, Flexbox, and Container Query patterns.
- Working with Forms — Deep dive into form participation, validation, and data collection.
- SVG Icons — How to create and reference icon sprite sheets.
- Documentation — How Espalier's docs are generated from source code.