Skip to content

Vanilla JS (DOM)

@ecss/dom-adapter generates vanilla JS/TS classes for ECSS blocks on top of the native DOM API — without frameworks. The adapter's id is 'dom'.

This is an inline adapter (like React/Vue): the class definitions land directly in the compiled .ecss module, and no files are written to disk. The adapter does not need a framework — it works with plain DOM in the browser.

Installation

sh
npm i -D @ecss/dom-adapter
sh
pnpm add -D @ecss/dom-adapter
sh
yarn add -D @ecss/dom-adapter

Setup

The adapter is registered in ecss.config.ts via defineConfig from @ecss/config — the config is not tied to any particular bundler; it is read by the ECSS plugin of your bundler. defaultAdapter sets the adapter applied to .ecss files by default:

ts
// ecss.config.ts
import { defineConfig } from '@ecss/config';
import { domAdapter } from '@ecss/dom-adapter';

export default defineConfig({
  adapters: [domAdapter()],
  defaultAdapter: 'dom',
});

Usage

Each @block turns into a class that is imported directly from the .ecss file. An instance is created with new, and the methods return this — they can be chained. The class name is formed as {prefix}{BlockName} (the default prefix is E): @block ButtonEButton.

ts
import { EButton } from './Button.ecss';

const button = new EButton({
  as: 'button',
  params: { variant: 'primary' },
  content: 'Click me',
});

button.appendTo(document.body);

Constructor options: as (the tag), params (the block's parameters), and content (the content).

Parameters (params)

The parameter types come from the generated {Block}Params interface (for example ButtonParams), so you cannot pass a non-existent @enum value. If the block has at least one required @param (without ?), params is required; otherwise it can be omitted.

Parameters can be changed after creation — each change re-renders the class, the CSS variables, and the data attributes:

ts
button.setParams({ variant: 'danger' }); // replace entirely
button.setParams((prev) => ({ ...prev, size: 'lg' })); // functional updater
button.params.variant = 'ghost'; // live proxy → re-render

Content (content)

setContent replaces all content, append / prepend add to the end / beginning. Strings, numbers, DOM nodes, other Ecss elements, arrays of these values, and null are accepted:

ts
button.setContent('Save'); // replace
button.append(icon, ' done'); // append (icon is another Ecss element)
button.setContent(null); // clear

Events (events)

events assigns on* handlers in bulk (it sets the element's property, not addEventListener — a repeated call replaces the handler). Inside a handler, this is the component instance itself, not the DOM node:

ts
button.events({
  onclick() {
    this.setParams({ variant: 'danger' }); // this is the EButton instance
  },
});

The set of available handlers is typed by the tag from as (as: 'button'HTMLButtonElement events). null clears a previously assigned handler.

Tag (as)

The as option sets the HTML tag of the root element (the default is 'div'). It determines the exact typing of the element getter and of the handlers available in events. The DOM node itself is always available through element:

ts
const button = new EButton({ as: 'button', params: { variant: 'primary' } });
button.element.disabled = true; // element is typed as HTMLButtonElement

Sub-elements (@element)

If a @block declares @element, they are available as static properties of the class. These are standalone classes (without params) that are inserted into the parent with the usual methods:

ts
import { EButton } from './Button.ecss';

const button = new EButton({ as: 'button', params: { withIcon: true } });
const icon = new EButton.Icon({ as: 'span', content: '★' });

button.append(icon).appendTo(document.body);

Methods

All methods except the element and params getters return this (they support chaining):

MethodDescription
appendTo(parent) / prependTo()insert the element into parent (a DOM node or another Ecss element)
append(...children) / prepend()add children to the end / beginning
setContent(value)replace all content (null clears it)
setParams(obj | updater)update the parameters and re-render (only on @block)
events(handlers)assign on* handlers
remove()remove the element from the DOM
elementgetter — the native DOM node, typed by as
paramsa live proxy of the parameters (btn.params.x = v re-renders)

Options

The factory's only option is componentNamePrefix (the class name prefix, default 'E'): domAdapter({ componentNamePrefix: 'My' })MyButton. For more details, see the adapters overview.

See also