Zazz Design Framework
Scripts

Scripting

Vanilla JavaScript architecture, web component patterns, auto-initialization, and module dependencies.

Scripts in @zazz-ui/core live alongside their components: shared runtime in src/base/ and component logic in src/primitives/<name>/. Authored in TypeScript, they compile to readable .js files that run as native ES modules in modern browsers without a required bundler.

index.js imports all component scripts so pages can load behaviors with a single <script type="module" src="./zazz/index.js"> tag.

Principles

  • Vanilla JS: Shipped .js files are standard ES modules. External dependencies (signals polyfill, Embla) resolve through the page's import map.
  • HTML-driven: Components read configuration from data attributes (data-carousel-*, data-reveal-*). Custom element props are data-* attributes too (e.g. data-label-show / data-label-hide on <ui-password>), not bare attributes.
  • Progressive enhancement: Components fall back to native HTML behaviors if JavaScript is disabled.

File template

"use strict";

/**
 * @fileoverview Module title.
 * @description What this module does.
 */

import { Dependency } from "./dependency.js";

// Implementation

if (typeof window !== "undefined" && typeof document !== "undefined") {
  // Auto-init
}

if (typeof window !== "undefined") {
  window.MyExport = MyExport;
}

export { MyExport };

Module exports

Scripts expose an API on window and provide named exports for ES module consumers:

FileGlobalExports
utils.jswindow.Utils{ parseValue, parseDataAttributes }
signals.jswindow.Signals{ state, computed, effect }
reveal.jswindow.RevealReveal class
zazz-element.js(none)ZazzElement base, defineZazzElement, refresh registry
dialog-lifecycle.js(none)Emits zazz:dialog-open / zazz:dialog-close on every <dialog>
embla.jswindow.EmblaInit{ init, initRoot, addDotBtnsAndClickHandlers }
toaster.jswindow.ToasterToaster imperative API
navigation.jsNoneSide-effect only

Web component scripts (carousel.js, lightbox.js, password-group.js, tabs.js, toaster.js) register custom elements automatically.

Auto-initialization

if (typeof window !== "undefined" && typeof document !== "undefined") {
  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", init);
  } else {
    init();
  }
}

Initializers are idempotent and check element state (e.g. data-carousel-init) before binding.

Dependencies

The module graph resolves loading order automatically via index.js:

ScriptImportsNotes
utils.jsNoneExposes window.Utils
signals.jssignal-polyfillReactive state (window.Signals)
reveal.jsNoneStandalone viewport observer
dialog-lifecycle.jsNoneOwns <dialog> visibility; components subscribe
embla.jsutils.js, Embla packagesEmbla packages resolve through the import map
carousel.jsembla.js<ui-carousel> custom element
lightbox.jscarousel.js<ui-lightbox> custom element
password-group.jssignals.js<ui-password> custom element
tabs.jsNone<ui-tabs> custom element
toaster.jssignals.js<ui-toaster> custom element
navigation.jszazz-element.jsPage transitions; refreshes swapped-in content

Ensure the import map appears in the DOM before index.js.

On this page