Getting Started

Monster is a web components library. The fastest way to get productive is to think in three layers: markup for the component itself, options via data-monster-option-*, and optional JavaScript for richer behavior.

This page shows the two practical entry points: direct browser usage for quick prototypes, and package-based usage for real projects. It also explains how the documentation examples in this repository are structured.

Quick Start in the Browser

For a first experiment you only need an HTML file and a module import. This keeps the feedback loop short and is ideal for checking component behavior before integrating Monster into a larger application.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Build fantastic websites!</title>
  <style>
    *:not(:defined) {
      visibility: hidden;
    }
  </style>
</head>
<body>
  <main>
    <monster-select>
      <div data-monster-value="value1">label-1</div>
      <div data-monster-value="value2">label-2</div>
      <div data-monster-value="value3">label-3</div>
    </monster-select>

    <script type="module">
      import 'https://esm.sh/@schukai/monster/source/components/form/select.mjs';
      import { PropertyStyleSheet } from 'https://esm.sh/@schukai/monster/source/components/stylesheet/property.mjs';

      document.adoptedStyleSheets = [PropertyStyleSheet];
    </script>
  </main>
</body>
</html>
Test code on the playground

Two details matter here:

  1. *:not(:defined) hides unresolved custom elements until the browser has upgraded them.
  2. You only import the modules you actually use. Monster does not require an all-or-nothing runtime bundle.

For quick demos, CDN-based imports are fine. For production projects, package-based imports are usually the better choice because you control versioning, bundling and caching explicitly.

Install via NPM, Yarn or PNPM

In an application repo, install Monster as a package and import only the components and stylesheets you need.

  1. Add the package: npm install @schukai/monster or yarn add @schukai/monster or pnpm add @schukai/monster

To pin a specific version, append @version to the package name.

A minimal package-based setup usually looks like this:

import "@schukai/monster/source/components/form/select.mjs";
import { PropertyStyleSheet } from "@schukai/monster/source/components/stylesheet/property.mjs";

document.adoptedStyleSheets = [
  ...document.adoptedStyleSheets,
  PropertyStyleSheet,
];

That gives you the component module and the foundational property stylesheet. Depending on the control, you may add further stylesheets or neighboring components, but the import principle stays the same.

Core Markup Rules

Most Monster components follow a small set of conventions:

  1. The tag name is the component API, for example <monster-select>.
  2. Declarative options use data-monster-option-*.
  3. Structural data is often passed via children, labels, slots or datasource references.
  4. Advanced behavior is added with JavaScript events and method calls, not by re-implementing the component UI yourself.
<monster-select
  data-monster-option-features-filterable="true"
  data-monster-option-labels-placeholder="Choose an option"
>
  <div data-monster-value="one">One</div>
  <div data-monster-value="two">Two</div>
</monster-select>

The documentation pages list all supported options, methods, properties and events for each component. The important point is that the declarative HTML API is the default, and JavaScript should extend it instead of replacing it.

Attributes, Options and Properties

Monster uses three different API layers and they should not be mixed up:

Layer
Where it lives
Best for
Typical example
attributes
Directly on the HTML element
Static structure, ids, labels, flags, referenced nodes
data-monster-value="one"
data-monster-option-*
Declarative option mapping in markup
Configuration that should be readable in source HTML
data-monster-option-features-filterable="true"
properties / methods
JavaScript on the element instance
Runtime changes, fetched data, imperative control
element.value = "two", element.fetch()

The default path is: start with HTML, add data-monster-option-* for declarative behavior, then move to properties or methods only when state becomes dynamic.

<monster-select
  data-monster-option-features-filterable="true"
  data-monster-option-labels-placeholder="Choose an option"
  value="two"
>
  <div data-monster-value="one">One</div>
  <div data-monster-value="two">Two</div>
</monster-select>
const select = document.querySelector("monster-select");

select.value = "one";
select.setOption("labels.placeholder", "Select a value");
select.addEventListener("change", (event) => {
  console.log("new value", event.target.value);
});

Events and Methods

Monster components usually expose two extension points for JavaScript:

  1. Listen to DOM or custom events when you want to react to user interaction.
  2. Call methods when you want to update state, load data or trigger component behavior from outside.

For example, a simple select can often be configured entirely in markup, while a more workflow-oriented component such as monster-api-button becomes interesting when you react to events like monster-api-button-successful or call runtime functions that fetch and import actions.

const apiButton = document.querySelector("monster-api-button");

apiButton.addEventListener("monster-api-button-successful", (event) => {
  console.log("request completed", event.detail);
});

apiButton.addEventListener("monster-api-button-failed", (event) => {
  console.error("request failed", event.detail);
});

The rule of thumb is simple: markup explains what a component is, JavaScript explains what should happen over time.

How Documentation Examples Are Structured

The examples in monsterjs-org deliberately split source view and runtime view. That keeps the docs readable and avoids leaking demo-only IDs or bootstrapping code into the copy-paste source examples.

File
Purpose
Used for
Fallback
main.html
The source HTML shown in the docs.
Code tab and default component markup.
Falls back to run.html if needed.
run.html
The HTML actually rendered in the live demo.
Runtime-only IDs, wrappers or demo shell markup.
Falls back to main.html.
script.mjs
The source JavaScript shown in the docs.
Readable import and setup example.
Optional.
run.mjs
The JavaScript executed by the live demo.
Runtime-only IDs, listeners or boot logic.
Optional; appended after script.mjs in code view.
readme.html
Short explanation of the example.
Context above the tabs.
Optional.
style.css
Additional example-local CSS.
Code tab documentation.
Optional.

In practice this means: main.html and script.mjs should be the clearest source you want a user to learn from. run.html and run.mjs may diverge where the live demo needs extra plumbing.

Generated example sections in the documentation now also include an Open in playground action. That sends the runtime HTML, CSS and JavaScript directly to playground.html?load=true, so readers can tweak a working example immediately instead of rebuilding it by hand.

When to Use Which Layer

  1. Use pure HTML first when the component API is already expressive enough.
  2. Add JavaScript when you need events, runtime state, async data or dynamic options.
  3. Add custom CSS only when Monster tokens and built-in styles are not sufficient.
  4. Prefer Monster tokens for color, spacing and radius so the result remains compatible with dark mode and theming.

Where to Go Next

After this page, the best next steps are:

  1. Read the foundations pages for color, layout and typography.
  2. Open a component page like Select and inspect its API section together with the live examples.
  3. Reuse the example structure from this repo when you write your own documentation or internal showcases, or start from the playground.

The current width of the area is too small to display the content correctly.