Integrate
Plain HTML
The comic-strip custom element without Astro, in any page or framework.
@toonstrip/element is a custom element with no framework dependency. The Astro component
is a thin wrapper around it; everything it does, the element does on its own.
Install
npm install @toonstrip/element @toonstrip/pack-comic-chat
Serve the pack’s files somewhere the browser can fetch them. The pack package contains
pack.json, characters/, and backdrops/; copy that directory to your static assets, for
example public/packs/comic-chat/.
Use
<comic-strip id="strip"></comic-strip>
<script type="module">
import "@toonstrip/element";
const strip = document.getElementById("strip");
strip.packs = ["/packs/comic-chat/"];
strip.document = {
version: 1,
panels: [
{
backdrop: "pastoral",
camera: "establishing",
bodies: [{ character: "dan", emotion: { angle: 0, intensity: 0.6 } }],
speakers: [{ speaker: "caption", balloon: "caption", text: "A field outside town." }],
},
],
};
</script>
API
| Member | Type | Meaning |
|---|---|---|
packs |
string[] property |
Base URLs of asset packs, each serving pack.json and its files. Searched in order; duplicate ids across packs throw. |
document |
ComicStripDocument property |
The strip. Validated on set. Setting it again re-renders. |
columns |
number getter |
Column count from the last layout pass. |
Setting document before packs is fine; the element rebuilds on either change and the
last set wins.
Note
Validation errors and unknown ids are reported by replacing the strip with a short red notice and logging to the console. Nothing throws out of a property setter.
From a framework
React, Vue, Svelte, and the rest can all render a custom element and set properties on it.
The one thing to remember is that packs and document are properties, not
attributes: set them from a ref after mount, or use your framework’s property-binding
syntax (.document={doc} in Lit, prop:document={doc} in Solid, :document.prop in Vue).
For React and Vue specifically, @toonstrip/react and @toonstrip/vue package exactly
this pattern as a <ComicStrip> component. See React reference
and Vue reference.
Bundling
The element imports @toonstrip/core and @toonstrip/schema; any ESM bundler handles it.
The schema is embedded at build time as plain data, and validation runs as ordinary JS
with no eval, so a strict Content Security Policy does not need unsafe-eval.
No build step at all
The install/npm/bundler steps above assume something resolves the bare
import "@toonstrip/element" specifier. With no bundler and no import map, use
esm.sh instead, which resolves a package’s own dependencies for you:
<script type="module">
import "https://esm.sh/@toonstrip/[email protected]";
</script>
Point packs at a CDN too: unpkg serves a pack’s static files (pack.json, sprite
sheets, backdrops) as-is, with CORS enabled:
strip.packs = ["https://unpkg.com/@toonstrip/[email protected]/"];
The full worked example is examples/vanilla-html/index.html in the repo: one file, no
package.json, opens from file:// or any static file server. Pin exact versions in
both URLs, same as any other dependency. See the repo’s docs/vanilla-html.md for the
esm.sh-vs-unpkg reasoning in full.