From 378b40fd7ecff47faff5bc64ed24f0bf64fd06c9 Mon Sep 17 00:00:00 2001 From: Matteo Bruni <176620+matteobruni@users.noreply.github.com> Date: Thu, 4 Jun 2026 14:13:35 +0200 Subject: [PATCH 1/4] docs: website updates --- websites/confetti/index.html | 54 +- websites/confetti/public/llms.txt | 19 + websites/confetti/public/robots.txt | 3 + websites/confetti/public/sitemap.xml | 6 +- websites/confetti/vite.config.js | 2 +- websites/ribbons/index.html | 51 ++ websites/ribbons/public/llms.txt | 15 + websites/ribbons/public/robots.txt | 3 + websites/ribbons/public/sitemap.xml | 6 +- websites/ribbons/vite.config.js | 2 +- websites/website/docs/.vitepress/config.ts | 86 ++ websites/website/docs/guides/angular.md | 631 +++++++++++++++ websites/website/docs/guides/astro.md | 384 +++++++++ websites/website/docs/guides/ember.md | 346 ++++++++ websites/website/docs/guides/index.md | 58 ++ websites/website/docs/guides/inferno.md | 373 +++++++++ websites/website/docs/guides/jquery.md | 273 +++++++ websites/website/docs/guides/lit.md | 301 +++++++ websites/website/docs/guides/nextjs.md | 492 ++++++++++++ websites/website/docs/guides/nuxt.md | 463 +++++++++++ websites/website/docs/guides/preact.md | 280 +++++++ websites/website/docs/guides/qwik.md | 392 ++++++++++ websites/website/docs/guides/react.md | 570 ++++++++++++++ websites/website/docs/guides/riot.md | 370 +++++++++ websites/website/docs/guides/solid.md | 512 ++++++++++++ websites/website/docs/guides/stencil.md | 359 +++++++++ websites/website/docs/guides/svelte.md | 580 ++++++++++++++ websites/website/docs/guides/vanilla.md | 736 ++++++++++++++++++ websites/website/docs/guides/vue3.md | 620 +++++++++++++++ websites/website/docs/guides/webcomponents.md | 359 +++++++++ websites/website/docs/guides/wordpress.md | 314 ++++++++ websites/website/docs/public/llms.txt | 199 +++++ websites/website/docs/public/robots.txt | 3 + 33 files changed, 8853 insertions(+), 9 deletions(-) create mode 100644 websites/confetti/public/llms.txt create mode 100644 websites/confetti/public/robots.txt create mode 100644 websites/ribbons/public/llms.txt create mode 100644 websites/ribbons/public/robots.txt create mode 100644 websites/website/docs/guides/angular.md create mode 100644 websites/website/docs/guides/astro.md create mode 100644 websites/website/docs/guides/ember.md create mode 100644 websites/website/docs/guides/index.md create mode 100644 websites/website/docs/guides/inferno.md create mode 100644 websites/website/docs/guides/jquery.md create mode 100644 websites/website/docs/guides/lit.md create mode 100644 websites/website/docs/guides/nextjs.md create mode 100644 websites/website/docs/guides/nuxt.md create mode 100644 websites/website/docs/guides/preact.md create mode 100644 websites/website/docs/guides/qwik.md create mode 100644 websites/website/docs/guides/react.md create mode 100644 websites/website/docs/guides/riot.md create mode 100644 websites/website/docs/guides/solid.md create mode 100644 websites/website/docs/guides/stencil.md create mode 100644 websites/website/docs/guides/svelte.md create mode 100644 websites/website/docs/guides/vanilla.md create mode 100644 websites/website/docs/guides/vue3.md create mode 100644 websites/website/docs/guides/webcomponents.md create mode 100644 websites/website/docs/guides/wordpress.md create mode 100644 websites/website/docs/public/llms.txt create mode 100644 websites/website/docs/public/robots.txt diff --git a/websites/confetti/index.html b/websites/confetti/index.html index 81fcd7e7f4a..59bb9e6c491 100644 --- a/websites/confetti/index.html +++ b/websites/confetti/index.html @@ -15,8 +15,60 @@ + + + + + + + + + + + + + + + + + + - tsParticles 🎉🎊 | JavaScript Confetti, Particles and Fireworks animations for your website + tsParticles Confetti | JavaScript Confetti, Particles and Fireworks animations for your + website diff --git a/websites/confetti/public/llms.txt b/websites/confetti/public/llms.txt new file mode 100644 index 00000000000..556518bd9c2 --- /dev/null +++ b/websites/confetti/public/llms.txt @@ -0,0 +1,19 @@ +# tsParticles Confetti + +> Interactive showcase and playground for tsParticles confetti animations. Explore confetti modes, customize settings with a live editor, and generate code snippets for your own projects. Hosted at confetti.js.org. + +## Docs + +- [Confetti Modes](https://confetti.js.org/): Interactive confetti animation demos with live code editor +- [tsParticles Documentation](https://particles.js.org/): Main tsParticles documentation site +- [tsParticles GitHub](https://github.com/tsparticles/tsparticles): Source code and issue tracker + +## Core + +- [Confetti Bundle](https://particles.js.org/guide/bundles-confetti): Guide for using the @tsparticles/confetti bundle +- [Confetti Presets](https://particles.js.org/demos/recipes/confetti): Confetti preset demos and recipes +- [Confetti Cannon Preset](https://particles.js.org/demos/recipes/confetti-cannon): Confetti cannon recipe +- [Confetti Explosions Preset](https://particles.js.org/demos/recipes/confetti-explosions): Confetti explosions recipe +- [Confetti Falling Preset](https://particles.js.org/demos/recipes/confetti-falling): Confetti falling animation recipe +- [Confetti Parade Preset](https://particles.js.org/demos/recipes/confetti-parade): Confetti parade recipe +- [npm: @tsparticles/confetti](https://www.npmjs.com/package/@tsparticles/confetti): npm package for @tsparticles/confetti diff --git a/websites/confetti/public/robots.txt b/websites/confetti/public/robots.txt new file mode 100644 index 00000000000..7059127bd50 --- /dev/null +++ b/websites/confetti/public/robots.txt @@ -0,0 +1,3 @@ +User-agent: * +Allow: / +Sitemap: https://confetti.js.org/sitemap.xml diff --git a/websites/confetti/public/sitemap.xml b/websites/confetti/public/sitemap.xml index caa6e0ebde6..53598be2e6d 100644 --- a/websites/confetti/public/sitemap.xml +++ b/websites/confetti/public/sitemap.xml @@ -2,14 +2,14 @@ https://confetti.js.org/ - 2026-04-05 + 2026-06-04 monthly 1 https://confetti.js.org/cookie-policy.html - 2026-04-06 + 2026-06-04 monthly - 0.5 + 0.3 \ No newline at end of file diff --git a/websites/confetti/vite.config.js b/websites/confetti/vite.config.js index c3d98539f89..48bb91429e9 100644 --- a/websites/confetti/vite.config.js +++ b/websites/confetti/vite.config.js @@ -14,6 +14,6 @@ export default defineConfig({ ], build: { outDir: 'dist', - minify: false, + minify: true, }, }); diff --git a/websites/ribbons/index.html b/websites/ribbons/index.html index 3e53c2a713c..1529459aa25 100644 --- a/websites/ribbons/index.html +++ b/websites/ribbons/index.html @@ -15,6 +15,57 @@ + + + + + + + + + + + + + + + + + + tsParticles Ribbons | JavaScript Ribbon animations for your website diff --git a/websites/ribbons/public/llms.txt b/websites/ribbons/public/llms.txt new file mode 100644 index 00000000000..88b7c38ab2f --- /dev/null +++ b/websites/ribbons/public/llms.txt @@ -0,0 +1,15 @@ +# tsParticles Ribbons + +> Interactive showcase and playground for tsParticles ribbon animations. Explore ribbon modes (basic, custom colors, multiple bursts, continuous fall, custom canvas, fixed position) with a live code editor. Hosted at ribbons.js.org. + +## Docs + +- [Ribbons Modes](https://ribbons.js.org/): Interactive ribbon animation demos with live code editor +- [tsParticles Documentation](https://particles.js.org/): Main tsParticles documentation site +- [tsParticles GitHub](https://github.com/tsparticles/tsparticles): Source code and issue tracker + +## Core + +- [Ribbons Preset](https://particles.js.org/demos/recipes/ribbons): Ribbon animation demo and recipe +- [Ribbon Shape Plugin](https://particles.js.org/options/plugin-shapes): Documentation for the ribbon shape plugin options +- [npm: @tsparticles/ribbons](https://www.npmjs.com/package/@tsparticles/ribbons): npm package for @tsparticles/ribbons diff --git a/websites/ribbons/public/robots.txt b/websites/ribbons/public/robots.txt new file mode 100644 index 00000000000..01e958fa289 --- /dev/null +++ b/websites/ribbons/public/robots.txt @@ -0,0 +1,3 @@ +User-agent: * +Allow: / +Sitemap: https://ribbons.js.org/sitemap.xml diff --git a/websites/ribbons/public/sitemap.xml b/websites/ribbons/public/sitemap.xml index 11bd60fba4e..40f572b954a 100644 --- a/websites/ribbons/public/sitemap.xml +++ b/websites/ribbons/public/sitemap.xml @@ -2,14 +2,14 @@ https://ribbons.js.org/ - 2026-04-05 + 2026-06-04 monthly 1 https://ribbons.js.org/cookie-policy.html - 2026-04-06 + 2026-06-04 monthly - 0.5 + 0.3 diff --git a/websites/ribbons/vite.config.js b/websites/ribbons/vite.config.js index 3b39010f4f9..69e8f6d09bf 100644 --- a/websites/ribbons/vite.config.js +++ b/websites/ribbons/vite.config.js @@ -14,6 +14,6 @@ export default defineConfig({ ], build: { outDir: 'dist', - minify: false, + minify: true, }, }); diff --git a/websites/website/docs/.vitepress/config.ts b/websites/website/docs/.vitepress/config.ts index 744995e5a65..13203f058dd 100644 --- a/websites/website/docs/.vitepress/config.ts +++ b/websites/website/docs/.vitepress/config.ts @@ -10,6 +10,7 @@ const gaMeasurementId = loadedEnv.VITE_GA_MEASUREMENT_ID ?? ""; const nav: DefaultTheme.NavItem[] = [ { text: "Start", link: "/guide/getting-started" }, { text: "Playground", link: "/playground/" }, + { text: "Guides", link: "/guides/" }, { text: "Demos", link: "/demos/" }, { text: "Wrappers", link: "/guide/wrappers" }, { text: "Options", link: "/options/" }, @@ -296,6 +297,33 @@ const baseSidebar: DefaultTheme.Sidebar = { ], }, ], + "/guides/": [ + { + text: "Guides", + items: [ + { text: "Overview", link: "/guides/" }, + { text: "Vanilla JS", link: "/guides/vanilla" }, + { text: "React", link: "/guides/react" }, + { text: "Vue 3", link: "/guides/vue3" }, + { text: "Angular", link: "/guides/angular" }, + { text: "Svelte", link: "/guides/svelte" }, + { text: "Next.js", link: "/guides/nextjs" }, + { text: "Nuxt", link: "/guides/nuxt" }, + { text: "Solid", link: "/guides/solid" }, + { text: "Preact", link: "/guides/preact" }, + { text: "Lit", link: "/guides/lit" }, + { text: "Qwik", link: "/guides/qwik" }, + { text: "jQuery", link: "/guides/jquery" }, + { text: "Astro", link: "/guides/astro" }, + { text: "Web Components", link: "/guides/webcomponents" }, + { text: "Stencil", link: "/guides/stencil" }, + { text: "Ember", link: "/guides/ember" }, + { text: "Riot", link: "/guides/riot" }, + { text: "Inferno", link: "/guides/inferno" }, + { text: "WordPress", link: "/guides/wordpress" }, + ], + }, + ], }; function prefixSidebarItems(items: DefaultTheme.SidebarItem[], prefix: string): DefaultTheme.SidebarItem[] { @@ -338,6 +366,35 @@ export default defineConfig({ lastUpdated: false, base, ignoreDeadLinks: [], + transformHead: ({ pageData }) => { + const path = pageData.relativePath.replace(/\.md$/, "").replace(/index$/, ""); + const canonical = `https://particles.js.org/${path}`; + const localePrefixesMap: Record = { + root: "x-default", + it: "it", + fr: "fr", + es: "es", + de: "de", + pt: "pt", + ru: "ru", + zh: "zh", + ja: "ja", + hi: "hi", + }; + const head: any[] = []; + for (const [locale, hreflang] of Object.entries(localePrefixesMap)) { + const prefix = locale === "root" ? "" : `/${locale}`; + head.push([ + "link", + { + rel: "alternate", + href: `https://particles.js.org${prefix}/${path}`, + hreflang, + }, + ]); + } + return head; + }, locales: { root: { label: "English", @@ -464,6 +521,9 @@ export default defineConfig({ "vue", "svelte", "astro", + "riot", + "hbs", + "php", ], }, }, @@ -475,6 +535,32 @@ export default defineConfig({ ["meta", { property: "og:type", content: "website" }], ["meta", { property: "og:title", content: "tsParticles" }], ["meta", { property: "og:description", content: "TypeScript particle engine for websites and apps" }], + ["meta", { property: "og:url", content: "https://particles.js.org" }], + ["meta", { property: "og:site_name", content: "tsParticles" }], + ["meta", { property: "og:locale", content: "en_US" }], + ["meta", { property: "og:image", content: "https://particles.js.org/images/banner3.png" }], + ["meta", { property: "og:image:width", content: "1200" }], + ["meta", { property: "og:image:height", content: "630" }], + ["meta", { name: "twitter:card", content: "summary_large_image" }], + ["meta", { name: "twitter:title", content: "tsParticles" }], + ["meta", { name: "twitter:description", content: "TypeScript particle engine for websites and apps" }], + ["meta", { name: "twitter:image", content: "https://particles.js.org/images/banner3.png" }], + [ + "script", + { type: "application/ld+json" }, + JSON.stringify({ + "@context": "https://schema.org", + "@type": "WebSite", + name: "tsParticles", + url: "https://particles.js.org", + description: "Modern particle animations for the web. TypeScript particle engine for websites and apps.", + author: { + "@type": "Person", + name: "Matteo Bruni", + url: "https://github.com/matteobruni", + }, + }), + ], ...(gaMeasurementId ? [ [ diff --git a/websites/website/docs/guides/angular.md b/websites/website/docs/guides/angular.md new file mode 100644 index 00000000000..26143aa454a --- /dev/null +++ b/websites/website/docs/guides/angular.md @@ -0,0 +1,631 @@ +--- +title: Angular Integration +description: Step-by-step guide for integrating tsParticles into Angular applications using @tsparticles/angular. +--- + +# Angular Integration + +The `@tsparticles/angular` package provides Angular components, modules, and services for tsParticles. This guide covers the traditional `NgModule` approach as well as Angular 17+ standalone components. + +--- + +## Installation + +```bash +npm install @tsparticles/angular @tsparticles/engine +``` + +For the full feature set, install the complete bundle: + +```bash +npm install tsparticles +``` + +Optional preset packages: + +```bash +npm install @tsparticles/preset-confetti +npm install @tsparticles/preset-fireworks +npm install @tsparticles/preset-snow +npm install @tsparticles/preset-stars +``` + +--- + +## Basic Usage (NgModule) + +### 1. Import the Module + +```typescript +import { NgModule } from "@angular/core"; +import { BrowserModule } from "@angular/platform-browser"; +import { NgParticlesModule } from "@tsparticles/angular"; +import { AppComponent } from "./app.component"; + +@NgModule({ + declarations: [AppComponent], + imports: [BrowserModule, NgParticlesModule], + bootstrap: [AppComponent], +}) +export class AppModule {} +``` + +### 2. Initialise the Engine + +```typescript +import { Component, OnInit } from "@angular/core"; +import type { Container, Engine, ISourceOptions } from "@tsparticles/engine"; +import { loadFull } from "tsparticles"; +import { NgParticlesService } from "@tsparticles/angular"; + +@Component({ + selector: "app-root", + templateUrl: "./app.component.html", + styleUrls: ["./app.component.css"], +}) +export class AppComponent implements OnInit { + constructor(private readonly ngParticlesService: NgParticlesService) {} + + ngOnInit(): void { + void this.ngParticlesService.init(async (engine: Engine) => { + await loadFull(engine); + }); + } + + particlesOptions: ISourceOptions = { + background: { + color: "#0d47a1", + }, + fpsLimit: 120, + particles: { + number: { + value: 80, + }, + color: { + value: "#ffffff", + }, + shape: { + type: "circle", + }, + opacity: { + value: 0.5, + }, + size: { + value: { min: 1, max: 5 }, + }, + links: { + enable: true, + distance: 150, + color: "#ffffff", + opacity: 0.4, + width: 1, + }, + move: { + enable: true, + speed: 2, + outModes: "out", + }, + }, + }; + + particlesLoaded(container: Container): void { + console.log("Particles container loaded", container); + } +} +``` + +### 3. Template + +```html + +``` + +--- + +## Engine Initialisation Details + +The `NgParticlesService.init()` method must be called exactly once, typically in `AppComponent.ngOnInit()`. It receives a callback where you load the plugins/presets your application needs. + +```typescript +import { Component, OnInit } from "@angular/core"; +import { NgParticlesService } from "@tsparticles/angular"; +import type { Engine } from "@tsparticles/engine"; + +@Component({ ... }) +export class AppComponent implements OnInit { + constructor(private readonly ngParticlesService: NgParticlesService) {} + + ngOnInit(): void { + void this.ngParticlesService.init(async (engine: Engine) => { + // Load only what you need for smaller bundles + await loadBasic(engine); // basic shapes + move + await loadEmittersPlugin(engine); // emitter shapes + }); + } +} +``` + +Available loader functions from `tsparticles`: + +| Function | Description | +| ------------------- | ------------------------------------------- | +| `loadFull(engine)` | All features (largest bundle) | +| `loadBasic(engine)` | Core shapes (circle, square, polygon, etc.) | +| `loadSlim(engine)` | Most features minus rarely used plugins | +| `loadAll(engine)` | Deprecated alias for `loadFull` | + +--- + +## Confetti Effect + +```bash +npm install @tsparticles/preset-confetti +``` + +```typescript +import { loadConfettiPreset } from "@tsparticles/preset-confetti"; + +// In NgParticlesService.init callback: +await loadConfettiPreset(engine); +``` + +```typescript +particlesOptions: ISourceOptions = { + preset: "confetti", + background: { + color: "transparent", + }, +}; +``` + +Or use the convenience `` component: + +```typescript +// app.module.ts +import { NgParticlesModule } from "@tsparticles/angular"; + +@NgModule({ + imports: [NgParticlesModule], +}) +export class AppModule {} +``` + +```html + +``` + +--- + +## Fireworks Effect + +```bash +npm install @tsparticles/preset-fireworks +``` + +```typescript +import { loadFireworksPreset } from "@tsparticles/preset-fireworks"; + +// In NgParticlesService.init callback: +await loadFireworksPreset(engine); +``` + +```typescript +particlesOptions: ISourceOptions = { + preset: "fireworks", + background: { + color: "#000000", + }, +}; +``` + +Or use the `` component: + +```html + +``` + +> Avoid auto-starting fireworks; bind them to a user action (click, scroll) to prevent unwanted resource usage. + +--- + +## Custom Particles Configuration + +Full-featured custom particle setup with interactivity: + +```typescript +import { Component, OnInit } from "@angular/core"; +import type { Container, Engine, ISourceOptions } from "@tsparticles/engine"; +import { loadFull } from "tsparticles"; +import { NgParticlesService } from "@tsparticles/angular"; + +@Component({ + selector: "app-particles", + templateUrl: "./particles.component.html", +}) +export class ParticlesComponent implements OnInit { + constructor(private readonly ngParticlesService: NgParticlesService) {} + + ngOnInit(): void { + void this.ngParticlesService.init(async (engine: Engine) => { + await loadFull(engine); + }); + } + + particlesOptions: ISourceOptions = { + background: { + color: "#0d0d0d", + }, + fpsLimit: 60, + particles: { + number: { + value: 100, + density: { + enable: true, + }, + }, + color: { + value: ["#ff0000", "#00ff00", "#0000ff", "#ffff00", "#ff00ff"], + }, + shape: { + type: ["circle", "square", "triangle"], + }, + opacity: { + value: 0.8, + random: true, + anim: { + enable: true, + speed: 1, + sync: false, + }, + }, + size: { + value: { min: 2, max: 8 }, + random: true, + anim: { + enable: true, + speed: 4, + size_min: 1, + sync: false, + }, + }, + links: { + enable: true, + distance: 150, + color: "#ffffff", + opacity: 0.3, + width: 1, + triangles: { + enable: true, + color: "#ffffff", + opacity: 0.05, + }, + }, + move: { + enable: true, + speed: 3, + direction: "none", + random: true, + straight: false, + outModes: "bounce", + attract: { + enable: true, + rotateX: 600, + rotateY: 600, + }, + }, + life: { + duration: { + value: 5, + random: true, + }, + count: 0, + }, + }, + interactivity: { + events: { + onHover: { + enable: true, + mode: "grab", + }, + onClick: { + enable: true, + mode: "push", + }, + resize: { + enable: true, + }, + }, + modes: { + grab: { + distance: 200, + links: { + opacity: 0.5, + }, + }, + push: { + quantity: 4, + }, + }, + }, + detectRetina: true, + }; + + particlesLoaded(container: Container): void { + console.log("Container loaded", container); + } +} +``` + +```html + +``` + +--- + +## Events + +The `ngx-particles` component emits the `particlesLoaded` event: + +```typescript +import type { Container } from "@tsparticles/engine"; + +// Component method +onParticlesLoaded(container: Container): void { + // Access the container API + container.pause(); + container.play(); + container.destroy(); + container.exportImage().then((blob) => { /* ... */ }); +} +``` + +```html + +``` + +The container reference gives you full programmatic control: pause, resume, destroy, export, and more. + +--- + +## Template Syntax & Conditional Rendering + +Use Angular structural directives to toggle the component: + +```html + + + +``` + +```typescript +export class AppComponent { + showParticles = true; + // ... +} +``` + +When `*ngIf` evaluates to `false`, the component is destroyed (including the canvas and all particle instances). Re-creating it re-initialises everything from scratch. + +--- + +## Standalone Components (Angular 17+) + +In Angular 17+, you can import `NgParticlesModule` directly into a standalone component: + +```typescript +import { Component, OnInit } from "@angular/core"; +import { NgParticlesModule, NgParticlesService } from "@tsparticles/angular"; +import { loadFull } from "tsparticles"; +import type { Container, Engine, ISourceOptions } from "@tsparticles/engine"; + +@Component({ + selector: "app-particles", + standalone: true, + imports: [NgParticlesModule], + template: ` + + `, +}) +export class ParticlesComponent implements OnInit { + constructor(private readonly ngParticlesService: NgParticlesService) {} + + ngOnInit(): void { + void this.ngParticlesService.init(async (engine: Engine) => { + await loadFull(engine); + }); + } + + particlesOptions: ISourceOptions = { + background: { color: "#000" }, + particles: { + number: { value: 50 }, + color: { value: "#fff" }, + shape: { type: "circle" }, + move: { enable: true, speed: 2 }, + }, + }; + + particlesLoaded(container: Container): void { + console.log("Loaded", container); + } +} +``` + +No `NgModule` wrapper needed — just import `NgParticlesModule` in the component's `imports` array. + +--- + +## Full Component Example + +### app.component.ts + +```typescript +import { Component, OnInit } from "@angular/core"; +import type { Container, Engine, ISourceOptions } from "@tsparticles/engine"; +import { loadSlim } from "tsparticles"; +import { NgParticlesService } from "@tsparticles/angular"; + +@Component({ + selector: "app-root", + templateUrl: "./app.component.html", + styleUrls: ["./app.component.css"], +}) +export class AppComponent implements OnInit { + title = "tsParticles Angular Demo"; + + constructor(private readonly ngParticlesService: NgParticlesService) {} + + ngOnInit(): void { + void this.ngParticlesService.init(async (engine: Engine) => { + await loadSlim(engine); + }); + } + + particlesOptions: ISourceOptions = { + autoPlay: true, + background: { + color: "#1e1e2e", + image: "", + position: "50% 50%", + repeat: "no-repeat", + size: "cover", + }, + backgroundMask: { + cover: { + color: "#1e1e2e", + }, + enable: false, + }, + fullScreen: { + enable: true, + zIndex: -1, + }, + detectRetina: true, + fpsLimit: 60, + particles: { + color: { + value: "#cdd6f4", + }, + links: { + color: "#cdd6f4", + distance: 150, + enable: true, + opacity: 0.3, + width: 1, + }, + move: { + enable: true, + speed: 1, + }, + number: { + value: 60, + }, + opacity: { + value: 0.6, + }, + size: { + value: { min: 1, max: 3 }, + }, + }, + }; + + particlesLoaded(container: Container): void { + console.log("Particles loaded", container); + } +} +``` + +### app.component.html + +```html +
+ + +
+

{{ title }}

+

Particles are running in the background.

+
+
+``` + +### app.component.css + +```css +:host { + display: block; + width: 100%; + height: 100%; +} +``` + +--- + +## API Reference + +| Component | Selector | Description | +| --------- | --------------- | ------------------------------- | +| Particles | `ngx-particles` | Full particle system component | +| Confetti | `ngx-confetti` | Pre-configured confetti effect | +| Fireworks | `ngx-fireworks` | Pre-configured fireworks effect | + +### `ngx-particles` Inputs + +| Input | Type | Default | Description | +| --------- | ---------------- | --------------- | ---------------------- | +| `id` | `string` | `"tsparticles"` | Canvas element ID | +| `options` | `ISourceOptions` | `{}` | Particle configuration | +| `url` | `string` | — | Remote JSON config URL | + +### `ngx-particles` Outputs + +| Output | Payload | Description | +| ----------------- | ----------- | ----------------------------------------- | +| `particlesLoaded` | `Container` | Emitted when the container is initialised | + +--- + +## Troubleshooting + +- **Blank / invisible canvas** — Ensure the parent element has a defined height (e.g., `height: 100vh`). The canvas takes the container dimensions. +- **`NgParticlesService.init()` called multiple times** — Call it only once, typically in `AppComponent.ngOnInit()`. Subsequent calls are safe but redundant. +- **Module not found** — Verify `@tsparticles/angular` is listed in `package.json` dependencies and that you imported `NgParticlesModule`. +- **`NullInjectorError: No provider for NgParticlesService`** — You must import `NgParticlesModule` (or re-export it) in the module where you provide the component. diff --git a/websites/website/docs/guides/astro.md b/websites/website/docs/guides/astro.md new file mode 100644 index 00000000000..7690cbdf32f --- /dev/null +++ b/websites/website/docs/guides/astro.md @@ -0,0 +1,384 @@ +# Astro Integration + +Use tsParticles in your Astro site with the official `@tsparticles/astro` integration package. + +## Installation + +Install the Astro integration and tsParticles core via your package manager: + +```bash +npm install @tsparticles/astro tsparticles +``` + +```bash +pnpm add @tsparticles/astro tsparticles +``` + +```bash +yarn add @tsparticles/astro tsparticles +``` + +## Engine Initialization + +tsParticles uses a modular architecture. Before rendering particles, you must initialize the engine with the features you need. Create a client script (e.g., `src/scripts/particles-init.ts`) or use an inline ` +``` + +> The `id` prop is passed to the underlying canvas container `
`. Use it for styling or imperative access via `document.getElementById()`. + +## TypeScript Support + +The integration ships full TypeScript declarations. Use `ISourceOptions` from `@tsparticles/engine` to type your configuration: + +```typescript +import type { ISourceOptions } from "@tsparticles/engine"; + +const options: ISourceOptions = { + background: { color: "#0d47a1" }, + fpsLimit: 60, + particles: { + color: { + value: ["#ff0000", "#00ff00", "#0000ff"], + }, + move: { + enable: true, + speed: 3, + outModes: "bounce", + }, + number: { + value: 50, + density: { enable: true }, + }, + opacity: { value: 0.5 }, + shape: { type: "circle" }, + size: { value: { min: 2, max: 6 } }, + }, + interactivity: { + events: { + onHover: { enable: true, mode: "repulse" }, + }, + modes: { + repulse: { distance: 200 }, + }, + }, +}; +``` + +## Custom Configuration + +Below is a more elaborate configuration that you can drop into any Astro page: + +```astro +--- +import Particles from "@tsparticles/astro"; +import type { ISourceOptions } from "@tsparticles/engine"; + +const options: ISourceOptions = { + autoPlay: true, + background: { + color: "#0d47a1", + image: "", + position: "50% 50%", + repeat: "no-repeat", + size: "cover", + }, + backgroundMode: { + enable: true, + zIndex: -1, + }, + fpsLimit: 120, + particles: { + color: { + value: "#ffffff", + animation: { + enable: true, + speed: 20, + sync: false, + }, + }, + links: { + enable: true, + distance: 150, + color: "#ffffff", + opacity: 0.4, + width: 1, + triangles: { + enable: true, + opacity: 0.1, + }, + }, + move: { + enable: true, + speed: 3, + direction: "none", + random: true, + straight: false, + outModes: "out", + attract: { enable: false }, + }, + number: { + value: 80, + density: { + enable: true, + }, + }, + opacity: { + value: 0.5, + animation: { + enable: true, + speed: 1, + sync: false, + }, + }, + shape: { + type: "circle", + }, + size: { + value: { min: 1, max: 5 }, + animation: { + enable: true, + speed: 3, + sync: false, + }, + }, + }, + interactivity: { + events: { + onHover: { + enable: true, + mode: "grab", + }, + onClick: { + enable: true, + mode: "push", + }, + resize: true, + }, + modes: { + grab: { + distance: 200, + links: { opacity: 0.5 }, + }, + push: { quantity: 4 }, + }, + }, + detectRetina: true, +}; +--- + + + + +``` + +## Using Presets + +Instead of building a configuration manually, load a preset during engine initialization and reference it in the options: + +```astro +--- +import Particles from "@tsparticles/astro"; +import type { ISourceOptions } from "@tsparticles/engine"; + +const options: ISourceOptions = { + preset: "stars", + background: { color: "#000000" }, +}; +--- + + + + +``` + +## Integration with Other Frameworks + +Because Astro supports UI frameworks like React, Vue, Svelte, and Solid, you can use the framework-specific tsParticles component within `.astro` files: + +### React in Astro + +```astro +--- +import Particles from "@tsparticles/react"; +import type { ISourceOptions } from "@tsparticles/engine"; + +const options: ISourceOptions = { + background: { color: "#000" }, + particles: { + number: { value: 60 }, + links: { enable: true }, + move: { enable: true }, + }, +}; +--- + + +``` + +### Vue in Astro + +```astro +--- +import Particles from "@tsparticles/vue3"; +import type { ISourceOptions } from "@tsparticles/engine"; + +const options: ISourceOptions = { + background: { color: "#000" }, + particles: { + number: { value: 60 }, + links: { enable: true }, + move: { enable: true }, + }, +}; +--- + + +``` + +> The `client:load` directive tells Astro to hydrate the component immediately on page load. Use `client:visible` for deferred loading. + +## Full Page Example + +A complete Astro page with particles serving as an animated background: + +```astro +--- +import Layout from "../layouts/Layout.astro"; +import Particles from "@tsparticles/astro"; +import type { ISourceOptions } from "@tsparticles/engine"; + +const options: ISourceOptions = { + background: { color: "#0d47a1" }, + fpsLimit: 60, + particles: { + number: { value: 100 }, + color: { value: "#ffffff" }, + links: { + enable: true, + distance: 150, + color: "#ffffff", + opacity: 0.4, + }, + move: { + enable: true, + speed: 2, + outModes: "out", + }, + size: { + value: { min: 1, max: 4 }, + }, + }, + interactivity: { + events: { + onHover: { enable: true, mode: "grab" }, + onClick: { enable: true, mode: "push" }, + }, + modes: { + grab: { distance: 200, links: { opacity: 0.5 } }, + push: { quantity: 4 }, + }, + }, +}; +--- + + +
+

Welcome

+

This page has a particle background powered by tsParticles.

+
+ +
+ + + + +``` + +## Component Props + +| Prop | Type | Default | Description | +| -------------------- | ---------------- | ------------------------- | -------------------------------------------- | +| `id` | `string` | `"tsparticles"` | DOM element id for the container | +| `options` | `ISourceOptions` | `{}` | Full tsParticles configuration object | +| `url` | `string` | — | Load configuration from a remote JSON URL | +| `particlesClassName` | `string` | `"tsparticles-canvas-el"` | CSS class for the canvas element | +| `container` | `object` | — | Pre-existing `Container` instance (advanced) | diff --git a/websites/website/docs/guides/ember.md b/websites/website/docs/guides/ember.md new file mode 100644 index 00000000000..fc0d3376bb3 --- /dev/null +++ b/websites/website/docs/guides/ember.md @@ -0,0 +1,346 @@ +--- +title: Ember Guide +description: Complete guide for integrating tsParticles with Ember.js applications. +--- + +# Ember Guide + +## Table of Contents + +1. [Installation](#installation) +2. [Engine Initialization](#engine-initialization) +3. [Basic Usage](#basic-usage) +4. [Custom Configuration](#custom-configuration) +5. [Event Handling](#event-handling) +6. [Conditional Rendering](#conditional-rendering) +7. [TypeScript Example](#typescript-example) + +--- + +## Installation + +Install the Ember addon and the tsParticles engine via ember-cli: + +```bash +ember install @tsparticles/ember +``` + +This will install the addon and its peer dependency `tsparticles`. You can optionally add preset packages: + +```bash +npm install @tsparticles/slim +``` + +--- + +## Engine Initialization + +The addon exports an `initParticlesEngine` utility that you call once at the application level. It receives an async callback where you load the features, presets, or shapes your app needs. + +```typescript +import { initParticlesEngine } from "@tsparticles/ember/utils/init-particles-engine"; +import { loadFull } from "tsparticles"; + +// Call this during application bootstrap +if (typeof window !== "undefined") { + void initParticlesEngine(async (engine) => { + await loadFull(engine); + }); +} +``` + +Typical locations for this call are the application route's `beforeModel` hook, an application controller's constructor, or an instance initializer. The engine singleton is initialized once and shared across all `` components in your app. + +--- + +## Basic Usage + +After initializing the engine, use the `` component in any template. Pass your particle configuration via the `@options` argument. + +```hbs +{{! app/templates/application.hbs }} + + +``` + +```typescript +// app/controllers/application.ts +import Controller from "@ember/controller"; +import type { ISourceOptions } from "@tsparticles/engine"; + +export default class ApplicationController extends Controller { + options: ISourceOptions = { + fpsLimit: 60, + particles: { + number: { value: 80 }, + color: { value: "#00d4ff" }, + shape: { type: "circle" }, + opacity: { value: 0.6 }, + size: { value: { min: 2, max: 5 } }, + links: { + enable: true, + distance: 150, + color: "#00d4ff", + opacity: 0.3, + width: 1, + }, + move: { + enable: true, + speed: 1.5, + direction: "none", + random: true, + outModes: { default: "bounce" }, + }, + }, + background: { color: "#0d1117" }, + }; +} +``` + +--- + +## Custom Configuration + +Build a richer configuration with interactivity, multiple shapes, and responsive density. + +```typescript +import Controller from "@ember/controller"; +import type { ISourceOptions } from "@tsparticles/engine"; + +export default class IndexController extends Controller { + options: ISourceOptions = { + fullScreen: { enable: true, zIndex: -1 }, + fpsLimit: 60, + particles: { + number: { + value: 60, + density: { enable: true, width: 800, height: 800 }, + }, + color: { + value: ["#ff6b6b", "#feca57", "#48dbfb", "#ff9ff3", "#54a0ff"], + }, + shape: { + type: ["circle", "triangle", "polygon"], + options: { + polygon: { sides: 6 }, + }, + }, + opacity: { value: { min: 0.4, max: 0.8 } }, + size: { value: { min: 3, max: 8 } }, + links: { + enable: true, + distance: 200, + color: "#ffffff", + opacity: 0.15, + width: 1, + }, + move: { + enable: true, + speed: 2, + direction: "none", + random: true, + straight: false, + outModes: { default: "out" }, + }, + }, + interactivity: { + events: { + onHover: { enable: true, mode: "attract" }, + onClick: { enable: true, mode: "repulse" }, + }, + modes: { + attract: { distance: 200, duration: 0.4, factor: 1 }, + repulse: { distance: 200, duration: 0.4 }, + }, + }, + background: { color: "#0f0f23" }, + }; +} +``` + +```hbs + +``` + +--- + +## Event Handling + +The `` component fires a `@particlesLoaded` action when the container has finished initializing and the first frame is rendered. Use this to access the `Container` instance for programmatic control. + +```typescript +import Controller from "@ember/controller"; +import { action } from "@ember/object"; +import type { Container, ISourceOptions } from "@tsparticles/engine"; + +export default class ApplicationController extends Controller { + options: ISourceOptions = { + /* ... */ + }; + + @action + loadedCallback(container: Container) { + console.log("Particles loaded", container.id); + + // Programmatic control example: + setTimeout(() => { + container.pause(); + console.log("Particles paused after 5 seconds"); + }, 5000); + } +} +``` + +```hbs + +``` + +You can also use the callback pattern inline with a template helper if you prefer not to define a separate action. + +--- + +## Conditional Rendering + +Use Ember's `{{if}}` helper together with a `@tracked` property to control when the `` component renders. This is useful when the engine initialization is asynchronous and you want to avoid rendering the component before the engine is ready. + +```typescript +import Controller from "@ember/controller"; +import { tracked } from "@glimmer/tracking"; +import { action } from "@ember/object"; +import type { Container, Engine, ISourceOptions } from "@tsparticles/engine"; +import { initParticlesEngine } from "@tsparticles/ember/utils/init-particles-engine"; +import { loadSlim } from "@tsparticles/slim"; + +export default class ApplicationController extends Controller { + @tracked engineReady = false; + + options: ISourceOptions = { + particles: { + number: { value: 50 }, + color: { value: "#ffffff" }, + shape: { type: "circle" }, + opacity: { value: 0.6 }, + size: { value: { min: 1, max: 4 } }, + move: { enable: true, speed: 1, outModes: { default: "bounce" } }, + }, + background: { color: "#1a1a2e" }, + }; + + constructor(...args: any[]) { + super(...args); + if (typeof window !== "undefined") { + void initParticlesEngine(async (engine: Engine) => { + await loadSlim(engine); + }).then(() => { + this.engineReady = true; + }); + } + } +} +``` + +```hbs +{{#if this.engineReady}} + +{{else}} +

Loading particles...

+{{/if}} +``` + +The `@tracked` decorator ensures the template re-renders automatically once the promise resolves. + +--- + +## TypeScript Example + +Below is a complete, typed Ember application controller demonstrating the full integration pattern with slim preset, interactivity, and lifecycle management. + +```typescript +// app/controllers/application.ts +import Controller from "@ember/controller"; +import { tracked } from "@glimmer/tracking"; +import { action } from "@ember/object"; +import type { Container, Engine, ISourceOptions } from "@tsparticles/engine"; +import { initParticlesEngine } from "@tsparticles/ember/utils/init-particles-engine"; +import { loadSlim } from "@tsparticles/slim"; + +export default class ApplicationController extends Controller { + @tracked private engineReady = false; + + private container?: Container; + + private readonly options: ISourceOptions = { + fullScreen: { enable: true, zIndex: -1 }, + fpsLimit: 60, + particles: { + number: { value: 80, density: { enable: true } }, + color: { value: "#6366f1" }, + shape: { type: "circle" }, + opacity: { value: { min: 0.3, max: 0.7 } }, + size: { value: { min: 2, max: 6 } }, + links: { + enable: true, + distance: 160, + color: "#6366f1", + opacity: 0.25, + width: 1, + }, + move: { + enable: true, + speed: 1.2, + direction: "none", + random: false, + straight: false, + outModes: { default: "bounce" }, + }, + }, + interactivity: { + events: { + onHover: { enable: true, mode: "grab" }, + onClick: { enable: true, mode: "push" }, + }, + modes: { + grab: { distance: 180, links: { opacity: 0.6 } }, + push: { quantity: 3 }, + }, + }, + background: { color: "#0a0a1a" }, + }; + + constructor(...args: any[]) { + super(...args); + if (typeof window !== "undefined") { + void initParticlesEngine(async (engine: Engine) => { + await loadSlim(engine); + }).then(() => { + this.engineReady = true; + }); + } + } + + @action + private handleParticlesLoaded(container: Container): void { + this.container = container; + console.log("Particles loaded in container:", container.id); + } +} +``` + +```hbs +{{! app/templates/application.hbs }} + +{{#if this.engineReady}} +
+

tsParticles + Ember

+ +
+{{else}} +
+

Initializing particle engine...

+
+{{/if}} +``` + +--- + +You now have everything needed to integrate tsParticles into an Ember.js application. Each example is self-contained and ready to be copied into your project. diff --git a/websites/website/docs/guides/index.md b/websites/website/docs/guides/index.md new file mode 100644 index 00000000000..b8d46c32d7f --- /dev/null +++ b/websites/website/docs/guides/index.md @@ -0,0 +1,58 @@ +--- +title: Step-by-Step Guides +description: Explore framework-specific guides for integrating tsParticles into your project. +--- + +# Step-by-Step Guides + +Welcome to the tsParticles guides section. Whether you are building a static Vanilla JS site, a single-page app in React or Vue, or a full-stack application with Next.js or Nuxt, these step-by-step tutorials will walk you through installation, basic usage, advanced configurations, and interactive effects. + +Each guide is self-contained and includes copy-pasteable code examples so you can get started quickly. + +## Available Guides + +| Framework / Wrapper | Package | Description | +| --------------------------------- | ------------------------------------- | --------------------------------------------------- | +| [Vanilla JS](./vanilla) | `tsparticles` (CDN or npm) | Direct DOM integration with `tsParticles.load()` | +| [React](./react) | `@tsparticles/react` | Official React wrapper with hooks and component API | +| [Vue 3](./vue3) | `@tsparticles/vue3` | Official Vue 3 plugin with composables | +| [Angular](./angular) | `@tsparticles/angular` | Official Angular component and module | +| [Svelte](./svelte) | `@tsparticles/svelte` | Official Svelte component | +| [Next.js](./nextjs) | `@tsparticles/react` (with Next.js) | Server-side rendering and dynamic imports | +| [Nuxt](./nuxt) | `@tsparticles/vue3` (with Nuxt) | SSR-safe integration as a Nuxt plugin | +| [Solid](./solid) | `@tsparticles/solid` | Official SolidJS wrapper | +| [Preact](./preact) | `@tsparticles/preact` | Preact-compatible component | +| [Lit](./lit) | `@tsparticles/lit` | Lit web component wrapper | +| [Qwik](./qwik) | `@tsparticles/qwik` | Qwik-optimized integration | +| [jQuery](./jquery) | `@tsparticles/jquery` | jQuery plugin for legacy projects | +| [Astro](./astro) | `@tsparticles/react` (or any wrapper) | Island architecture with client directives | +| [Web Components](./webcomponents) | `@tsparticles/webcomponents` | Custom Elements API integration | +| [Stencil](./stencil) | `@tsparticles/stencil` | Stencil component wrapper | +| [Ember](./ember) | `@tsparticles/ember` | Ember addon integration | +| [Riot](./riot) | `@tsparticles/riot` | Riot.js wrapper | +| [Inferno](./inferno) | `@tsparticles/inferno` | Inferno-compatible component | +| [WordPress](./wordpress) | Plugin + `tsparticles` | Block editor / shortcode integration | + +## Choose Your Guide + +- [Vanilla JS (plain JavaScript)](./vanilla) +- [React](./react) +- [Vue 3](./vue3) +- [Angular](./angular) +- [Svelte](./svelte) +- [Next.js](./nextjs) +- [Nuxt](./nuxt) +- [Solid](./solid) +- [Preact](./preact) +- [Lit](./lit) +- [Qwik](./qwik) +- [jQuery](./jquery) +- [Astro](./astro) +- [Web Components](./webcomponents) +- [Stencil](./stencil) +- [Ember](./ember) +- [Riot](./riot) +- [Inferno](./inferno) +- [WordPress](./wordpress) + +Happy building! diff --git a/websites/website/docs/guides/inferno.md b/websites/website/docs/guides/inferno.md new file mode 100644 index 00000000000..6ab2937e1ea --- /dev/null +++ b/websites/website/docs/guides/inferno.md @@ -0,0 +1,373 @@ +--- +title: Inferno Guide +description: Complete guide for integrating tsParticles with Inferno applications. +--- + +# Inferno Guide + +## Table of Contents + +1. [Installation](#installation) +2. [Basic Usage](#basic-usage) +3. [Engine Initialization](#engine-initialization) +4. [Custom Configuration](#custom-configuration) +5. [Preset Usage](#preset-usage) +6. [Component Pattern](#component-pattern) +7. [TypeScript Example](#typescript-example) + +--- + +## Installation + +Install the Inferno wrapper and the tsParticles engine via npm: + +```bash +npm install @tsparticles/inferno tsparticles +``` + +Optionally install the slim preset for a smaller bundle: + +```bash +npm install @tsparticles/slim +``` + +--- + +## Basic Usage + +The `@tsparticles/inferno` package exports two items: `ParticlesProvider` and `Particles`. Wrap your particle components with `ParticlesProvider` which accepts an `init` callback for engine setup, then use `` to render the particle canvas. + +```tsx +import { render } from "inferno"; +import { Particles, ParticlesProvider } from "@tsparticles/inferno"; +import { loadSlim } from "@tsparticles/slim"; + +const options = { + fpsLimit: 60, + particles: { + number: { value: 80 }, + color: { value: "#00d4ff" }, + shape: { type: "circle" }, + opacity: { value: 0.6 }, + size: { value: { min: 2, max: 5 } }, + links: { + enable: true, + distance: 150, + color: "#00d4ff", + opacity: 0.3, + width: 1, + }, + move: { + enable: true, + speed: 1.5, + direction: "none", + random: true, + outModes: { default: "bounce" }, + }, + }, + background: { color: "#0d1117" }, +}; + +function App() { + return ( + { + await loadSlim(engine); + }} + > + + + ); +} + +render(, document.getElementById("app")); +``` + +`ParticlesProvider` must be an ancestor of every `` component. It initializes the engine once and provides it via context to all children. + +--- + +## Engine Initialization + +The `ParticlesProvider` accepts an `init` prop that receives the engine instance. This is where you load the features, shapes, presets, or updaters your app needs. + +```tsx +// Lightweight — circle particles, basic movement, links + { + const { loadSlim } = await import("@tsparticles/slim"); + await loadSlim(engine); +}}> + +// Full feature set — all shapes, interactions, effects + { + const { loadFull } = await import("tsparticles"); + await loadFull(engine); +}}> + +// Preset-specific — confetti, fireworks, snow, stars + { + const { loadConfettiPreset } = await import("@tsparticles/preset-confetti"); + await loadConfettiPreset(engine); +}}> +``` + +Using dynamic `import()` inside the callback enables code splitting: the preset or feature modules are loaded only when the particle component mounts. + +--- + +## Custom Configuration + +Below is a fully featured configuration with interactivity, multiple shape types, and a dark gradient background. + +```tsx +import { render } from "inferno"; +import { Particles, ParticlesProvider } from "@tsparticles/inferno"; +import type { ISourceOptions } from "@tsparticles/engine"; + +const options: ISourceOptions = { + fullScreen: { enable: true, zIndex: -1 }, + fpsLimit: 60, + particles: { + number: { + value: 60, + density: { enable: true, width: 800, height: 800 }, + }, + color: { + value: ["#ff6b6b", "#feca57", "#48dbfb", "#ff9ff3", "#54a0ff"], + }, + shape: { + type: ["circle", "triangle", "polygon"], + options: { + polygon: { sides: 6 }, + }, + }, + opacity: { value: { min: 0.4, max: 0.8 } }, + size: { value: { min: 3, max: 8 } }, + links: { + enable: true, + distance: 200, + color: "#ffffff", + opacity: 0.15, + width: 1, + }, + move: { + enable: true, + speed: 2, + direction: "none", + random: true, + straight: false, + outModes: { default: "out" }, + }, + }, + interactivity: { + events: { + onHover: { enable: true, mode: "attract" }, + onClick: { enable: true, mode: "repulse" }, + }, + modes: { + attract: { distance: 200, duration: 0.4, factor: 1 }, + repulse: { distance: 200, duration: 0.4 }, + }, + }, + background: { color: "#0f0f23" }, +}; + +function App() { + return ( + { + const { loadSlim } = await import("@tsparticles/slim"); + await loadSlim(engine); + }} + > + + + ); +} + +render(, document.getElementById("app")); +``` + +--- + +## Preset Usage + +The `@tsparticles/configs` package offers pre-built configurations that you can pass straight to the `options` prop. Combine them with the corresponding preset loader in the `ParticlesProvider` init callback. + +```tsx +import { render } from "inferno"; +import { Particles, ParticlesProvider } from "@tsparticles/inferno"; +import configs from "@tsparticles/configs"; + +function App() { + return ( + { + const { loadFull } = await import("tsparticles"); + await loadFull(engine); + }} + > + + + ); +} + +render(, document.getElementById("app")); +``` + +You can swap `configs.confetti` with any available preset: `configs.basic`, `configs.fireworks`, `configs.snow`, `configs.stars`, etc. + +--- + +## Component Pattern + +For larger applications, structure your particle logic into a dedicated component with a `particlesLoaded` callback for accessing the `Container` instance. + +```tsx +import { render, Component } from "inferno"; +import { Particles, ParticlesProvider } from "@tsparticles/inferno"; +import type { Container, ISourceOptions } from "@tsparticles/engine"; + +const options: ISourceOptions = { + fpsLimit: 60, + particles: { + number: { value: 80 }, + color: { value: "#00d4ff" }, + shape: { type: "circle" }, + opacity: { value: 0.6 }, + size: { value: { min: 2, max: 5 } }, + links: { + enable: true, + distance: 150, + color: "#00d4ff", + opacity: 0.3, + width: 1, + }, + move: { + enable: true, + speed: 1.5, + outModes: { default: "bounce" }, + }, + }, + interactivity: { + events: { + onHover: { enable: true, mode: "grab" }, + onClick: { enable: true, mode: "push" }, + }, + modes: { + grab: { distance: 180, links: { opacity: 0.6 } }, + push: { quantity: 3 }, + }, + }, + background: { color: "#0a0a1a" }, +}; + +class ParticlesBackground extends Component { + private container?: Container; + + handleParticlesLoaded(container?: Container) { + this.container = container; + console.log("Particles loaded:", container?.id); + } + + render() { + return ( + { + const { loadSlim } = await import("@tsparticles/slim"); + await loadSlim(engine); + }} + > + + + ); + } +} + +function App() { + return ( +
+

tsParticles + Inferno

+ +
+ ); +} + +render(, document.getElementById("app")); +``` + +--- + +## TypeScript Example + +Here is a complete, typed Inferno application with a responsive particle configuration and full-screen background. + +```tsx +import { render } from "inferno"; +import { Particles, ParticlesProvider } from "@tsparticles/inferno"; +import type { Container, Engine, ISourceOptions } from "@tsparticles/engine"; + +const particlesOptions: ISourceOptions = { + fullScreen: { enable: true, zIndex: -1 }, + fpsLimit: 60, + particles: { + number: { value: 80, density: { enable: true } }, + color: { value: "#6366f1" }, + shape: { type: "circle" }, + opacity: { value: { min: 0.3, max: 0.7 } }, + size: { value: { min: 2, max: 6 } }, + links: { + enable: true, + distance: 160, + color: "#6366f1", + opacity: 0.25, + width: 1, + }, + move: { + enable: true, + speed: 1.2, + direction: "none", + random: false, + straight: false, + outModes: { default: "bounce" }, + }, + }, + interactivity: { + events: { + onHover: { enable: true, mode: "grab" }, + onClick: { enable: true, mode: "push" }, + }, + modes: { + grab: { distance: 180, links: { opacity: 0.6 } }, + push: { quantity: 3 }, + }, + }, + background: { color: "#0a0a1a" }, +}; + +function handleInit(engine: Engine): Promise { + return import("@tsparticles/slim").then(({ loadSlim }) => loadSlim(engine)); +} + +function handleParticlesLoaded(container?: Container): void { + console.log("tsParticles container ready:", container?.id); +} + +function App() { + return ( + +
+

tsParticles + Inferno

+

Full TypeScript integration

+
+ +
+ ); +} + +render(, document.getElementById("app")); +``` + +--- + +You now have everything needed to integrate tsParticles into an Inferno application. Each example is self-contained and ready to be copied into your project. diff --git a/websites/website/docs/guides/jquery.md b/websites/website/docs/guides/jquery.md new file mode 100644 index 00000000000..01f457caf36 --- /dev/null +++ b/websites/website/docs/guides/jquery.md @@ -0,0 +1,273 @@ +# jQuery Integration + +Integrate tsParticles into your jQuery-based projects with the official jQuery plugin wrapper. + +## Installation + +### Via CDN + +Include jQuery, tsParticles, and the jQuery plugin via script tags: + +```html + + + +``` + +### Via npm + Build + +Install the required packages: + +```bash +npm install jquery @tsparticles/jquery tsparticles +``` + +Import into your project: + +```javascript +import $ from "jquery"; +import "@tsparticles/jquery"; +``` + +## Engine Initialization + +Before particles can be rendered, the tsParticles engine must be initialized with the features you need. This is done via `$.particles.init`: + +```javascript +(async () => { + await $.particles.init(async (engine) => { + const { loadFull } = await import("tsparticles"); + await loadFull(engine); + }); +})(); +``` + +> **Why is this needed?** tsParticles uses a modular architecture. `loadFull` registers all built-in shapes, interactions, and updaters. You can import smaller bundles (e.g., `tsparticles-slim`) to reduce bundle size. + +## Basic Usage + +Once the engine is initialized and the DOM is ready, select a container element and call `.particles().load()`: + +```javascript +$(document).ready(async () => { + await $.particles.init(async (engine) => { + const { loadFull } = await import("tsparticles"); + await loadFull(engine); + }); + + $("#tsparticles") + .particles() + .load({ + background: { + color: "#0d47a1", + }, + particles: { + number: { value: 80 }, + links: { enable: true, color: "#ffffff" }, + move: { enable: true }, + }, + }); +}); +``` + +The container element must exist in the DOM: + +```html +
+``` + +## Custom Configuration + +The `.load()` method accepts the full `ISourceOptions` object. Here is a comprehensive example: + +```javascript +$("#tsparticles") + .particles() + .load({ + background: { + color: "#000000", + }, + fpsLimit: 120, + particles: { + color: { + value: ["#ff0000", "#00ff00", "#0000ff"], + }, + move: { + direction: "none", + enable: true, + outModes: "bounce", + speed: 4, + }, + number: { + density: { + enable: true, + }, + value: 60, + }, + opacity: { + value: 0.6, + }, + shape: { + type: ["circle", "square", "triangle"], + }, + size: { + value: { min: 2, max: 8 }, + }, + links: { + enable: true, + distance: 150, + color: "#ffffff", + opacity: 0.4, + width: 1, + }, + }, + interactivity: { + events: { + onClick: { + enable: true, + mode: "push", + }, + onHover: { + enable: true, + mode: "repulse", + }, + }, + modes: { + push: { + quantity: 4, + }, + repulse: { + distance: 200, + }, + }, + }, + }); +``` + +## Preset Loading + +If you have installed a preset package (e.g. `tsparticles-preset-stars`), load it during engine initialization and reference it in the configuration: + +```bash +npm install tsparticles-preset-stars +``` + +```javascript +(async () => { + await $.particles.init(async (engine) => { + const { loadStarsPreset } = await import("tsparticles-preset-stars"); + await loadStarsPreset(engine); + }); + + $("#tsparticles") + .particles() + .load({ + preset: "stars", + background: { color: "#0d47a1" }, + }); +})(); +``` + +## Event Handling and Container Control + +`.particles()` returns a jQuery plugin instance. To access the underlying tsParticles `Container` and call methods like `play()`, `pause()`, or `destroy()`: + +```javascript +const $container = $("#tsparticles"); + +// Load particles +$container.particles().load({ + /* options */ +}); + +// Play/pause after a few seconds +setTimeout(() => { + const container = $container.particles().getContainer(); + container?.pause(); +}, 5000); +``` + +## Full Example + +Below is a complete, self-contained HTML page that loads tsParticles via CDN and renders a particle scene with interactive effects: + +```html + + + + + + tsParticles + jQuery + + + +
+ + + + + + + +``` + +## API Reference + +| Method | Description | +| ---------------------------------- | -------------------------------------------------------- | +| `$.particles.init(fn)` | Initialize the engine with a loader callback | +| `$(el).particles()` | Create a particles plugin instance on the element | +| `$(el).particles().load(opts)` | Load and start the particle configuration | +| `$(el).particles().destroy()` | Destroy the particle instance and clean up | +| `$(el).particles().getContainer()` | Return the underlying `Container` for imperative control | diff --git a/websites/website/docs/guides/lit.md b/websites/website/docs/guides/lit.md new file mode 100644 index 00000000000..7ee88894630 --- /dev/null +++ b/websites/website/docs/guides/lit.md @@ -0,0 +1,301 @@ +--- +title: Lit +description: Integrate tsParticles with Lit using the official @tsparticles/lit web component wrapper. +--- + +# Lit Integration + +The `@tsparticles/lit` package provides a `` custom element built with Lit, allowing you to use tsParticles declaratively in any Lit project or plain HTML page. + +## Installation + +```bash +npm install @tsparticles/lit tsparticles +``` + +The package is fully typed and includes Lit's reactive controller patterns for reactively updating particle options. + +## Engine Initialization + +Call `initParticlesEngine` before registering the `` component or importing it in your application. This must happen exactly once. + +```typescript +import { initParticlesEngine } from "@tsparticles/lit"; +import { loadFull } from "tsparticles"; + +void initParticlesEngine(async (engine) => { + await loadFull(engine); +}); +``` + +For optimized bundle sizes, import only the features your project needs: + +```typescript +import { initParticlesEngine } from "@tsparticles/lit"; +import { loadBasic } from "@tsparticles/basic"; +import { loadConfettiPreset } from "@tsparticles/preset-confetti"; + +void initParticlesEngine(async (engine) => { + await loadBasic(engine); + await loadConfettiPreset(engine); +}); +``` + +## Basic Usage + +After the engine is initialized, use the `` element in any Lit template or HTML file: + +```typescript +import { LitElement, html } from "lit"; +import { customElement } from "lit/decorators.js"; +import "@tsparticles/lit"; + +@customElement("my-app") +class MyApp extends LitElement { + private options = { + background: { + color: "#0d1117", + }, + particles: { + number: { value: 60 }, + color: { value: "#58a6ff" }, + links: { + enable: true, + color: "#58a6ff", + }, + move: { enable: true, speed: 2 }, + }, + }; + + render() { + return html` `; + } +} +``` + +The `.options` syntax (with leading dot) is Lit's property binding, ensuring the object is passed by reference rather than serialized as an attribute. + +## Plain HTML Usage + +Once `@tsparticles/lit` is bundled or loaded, the element works in plain HTML too: + +```html + + + + + + + + + +``` + +You can pass a minimal options object as a JSON attribute: + +```html + +``` + +## Custom Configuration + +Pass a full tsParticles configuration as a Lit property: + +```typescript +import { LitElement, html } from "lit"; +import { customElement, property } from "lit/decorators.js"; +import type { ISourceOptions } from "@tsparticles/engine"; +import "@tsparticles/lit"; + +@customElement("my-particles") +class MyParticles extends LitElement { + @property({ type: Object }) + options: ISourceOptions = { + background: { + color: "#0d1117", + }, + fpsLimit: 120, + fullScreen: { + enable: true, + zIndex: -1, + }, + particles: { + color: { + value: ["#ff5733", "#33ff57", "#3357ff"], + }, + links: { + color: "#ffffff", + enable: true, + opacity: 0.3, + distance: 150, + }, + move: { + enable: true, + speed: 1.5, + direction: "none", + random: true, + }, + number: { + value: 100, + density: { + enable: true, + }, + }, + opacity: { + value: 0.6, + animation: { + enable: true, + speed: 0.5, + minimumValue: 0.1, + }, + }, + size: { + value: { min: 1, max: 5 }, + animation: { + enable: true, + speed: 2, + minimumValue: 1, + }, + }, + }, + interactivity: { + events: { + onHover: { + enable: true, + mode: "grab", + }, + onClick: { + enable: true, + mode: "push", + }, + }, + modes: { + grab: { + distance: 180, + links: { + opacity: 0.5, + }, + }, + push: { + quantity: 4, + }, + }, + }, + }; + + render() { + return html` `; + } +} +``` + +## Event Handling + +Listen for the `particles-loaded` custom event dispatched by the `` element: + +```typescript +import { LitElement, html } from "lit"; +import { customElement } from "lit/decorators.js"; +import type { Container } from "@tsparticles/engine"; +import "@tsparticles/lit"; + +@customElement("my-app") +class MyApp extends LitElement { + private handleParticlesLoaded(e: CustomEvent) { + const container = e.detail; + console.log("Particles loaded:", container); + container?.refresh(); + } + + render() { + return html` `; + } +} +``` + +## TypeScript Example + +A fully typed Lit element with `initParticlesEngine`, reactive options, and event handling: + +```typescript +import { LitElement, html } from "lit"; +import { customElement, property } from "lit/decorators.js"; +import { initParticlesEngine } from "@tsparticles/lit"; +import type { Container, ISourceOptions } from "@tsparticles/engine"; +import { loadFull } from "tsparticles"; +import "@tsparticles/lit"; + +void initParticlesEngine(async (engine) => { + await loadFull(engine); +}); + +@customElement("particles-background") +class ParticlesBackground extends LitElement { + @property({ type: Object }) + options: ISourceOptions = {}; + + @property({ type: Boolean, attribute: "fullscreen" }) + fullscreen = true; + + protected onParticlesLoaded(e: CustomEvent) { + console.log("Container ready:", e.detail.id); + } + + render() { + return html` + + + `; + } +} +``` + +## Dynamic Updates + +Because `` uses Lit's reactive properties, changing the `options` property automatically updates the particles: + +```typescript +import { LitElement, html } from "lit"; +import { customElement, state } from "lit/decorators.js"; +import type { ISourceOptions } from "@tsparticles/engine"; +import "@tsparticles/lit"; + +@customElement("dynamic-particles") +class DynamicParticles extends LitElement { + @state() + private theme: "light" | "dark" = "dark"; + + private get options(): ISourceOptions { + return this.theme === "dark" + ? { + background: { color: "#0d1117" }, + particles: { color: { value: "#58a6ff" } }, + } + : { + background: { color: "#ffffff" }, + particles: { color: { value: "#0969da" } }, + }; + } + + private toggleTheme() { + this.theme = this.theme === "dark" ? "light" : "dark"; + } + + render() { + return html` + + + `; + } +} +``` + +The component watches the `options` property and calls `refresh()` internally whenever it changes, seamlessly updating the particle configuration at runtime. diff --git a/websites/website/docs/guides/nextjs.md b/websites/website/docs/guides/nextjs.md new file mode 100644 index 00000000000..01a06709943 --- /dev/null +++ b/websites/website/docs/guides/nextjs.md @@ -0,0 +1,492 @@ +--- +title: Next.js Integration +description: Step-by-step guide to integrating tsParticles into a Next.js application using the App Router. +--- + +# Next.js Integration + +This guide covers integrating tsParticles into a Next.js project using the **App Router** (Next.js 13+). For the legacy Pages Router, see the [Legacy Pages Router](#legacy-pages-router) section at the bottom. + +## Installation + +Install the `@tsparticles/react` wrapper and the full `tsparticles` engine (or a slim bundle for smaller builds): + +```bash +npm install @tsparticles/react tsparticles +``` + +If you prefer the smaller `@tsparticles/slim` bundle: + +```bash +npm install @tsparticles/react @tsparticles/slim +``` + +## Basic Usage (App Router) + +Next.js App Router components are server-side by default. Since tsParticles requires the browser `canvas` API, you must mark the component with the `"use client"` directive. + +```tsx +"use client"; + +import Particles from "@tsparticles/react"; +import { useCallback, useMemo } from "react"; +import type { Container, ISourceOptions } from "@tsparticles/engine"; + +export default function ParticlesBackground() { + const particlesLoaded = useCallback((container?: Container) => { + console.log("Particles loaded", container); + }, []); + + const options: ISourceOptions = useMemo( + () => ({ + fullScreen: { zIndex: -1 }, + background: { color: "#0d47a1" }, + particles: { + number: { value: 80 }, + links: { enable: true, color: "#ffffff" }, + move: { enable: true }, + size: { value: 3 }, + }, + }), + [], + ); + + return ; +} +``` + +Create this as `components/particles-background.tsx` and import it into any page or layout. Because the file starts with `"use client"`, it will be rendered on the client — exactly where tsParticles needs to be. + +## Theme Switching + +Combine tsParticles with Next.js theme toggles by deriving the options from the current theme state: + +```tsx +"use client"; + +import Particles from "@tsparticles/react"; +import { useMemo, useState, useCallback } from "react"; +import type { Container, ISourceOptions } from "@tsparticles/engine"; + +export default function ThemeAwareParticles() { + const [theme, setTheme] = useState<"light" | "dark">("dark"); + + const toggleTheme = useCallback(() => { + setTheme((t) => (t === "dark" ? "light" : "dark")); + }, []); + + const particlesLoaded = useCallback((_container?: Container) => {}, []); + + const options: ISourceOptions = useMemo( + () => ({ + fullScreen: { zIndex: -1 }, + background: { + color: theme === "dark" ? "#000000" : "#ffffff", + }, + particles: { + color: { value: theme === "dark" ? "#ffffff" : "#000000" }, + number: { value: 100 }, + links: { + enable: true, + color: theme === "dark" ? "#ffffff" : "#000000", + }, + move: { enable: true }, + }, + }), + [theme], + ); + + return ( + <> + + + + ); +} +``` + +The `options` object is recreated via `useMemo` whenever `theme` changes, so the canvas updates automatically. + +## Confetti Effect + +Use the `@tsparticles/preset-confetti` to trigger celebratory confetti on events like button clicks: + +```bash +npm install @tsparticles/preset-confetti +``` + +```tsx +"use client"; + +import Particles from "@tsparticles/react"; +import { useCallback, useMemo, useState } from "react"; +import { loadConfettiPreset } from "@tsparticles/preset-confetti"; +import type { Container, ISourceOptions, Engine } from "@tsparticles/engine"; + +export default function ConfettiButton() { + const [active, setActive] = useState(false); + + const particlesInit = useCallback(async (engine: Engine) => { + await loadConfettiPreset(engine); + }, []); + + const particlesLoaded = useCallback( + async (container?: Container) => { + if (active && container) { + await container.play(); + } + }, + [active], + ); + + const options: ISourceOptions = useMemo( + () => ({ + preset: "confetti", + fullScreen: { zIndex: 1000 }, + }), + [], + ); + + const handleCelebrate = useCallback(() => { + setActive(true); + setTimeout(() => setActive(false), 5000); + }, []); + + return ( + <> + {active && } + + + ); +} +``` + +The `init` callback loads the confetti preset into the engine before the particles are created. + +## Fireworks Effect + +Similarly, the fireworks preset creates a spectacular firework display: + +```bash +npm install @tsparticles/preset-fireworks +``` + +```tsx +"use client"; + +import Particles from "@tsparticles/react"; +import { useCallback, useMemo, useRef } from "react"; +import { loadFireworksPreset } from "@tsparticles/preset-fireworks"; +import type { Container, Engine } from "@tsparticles/engine"; + +export default function FireworksBackground() { + const containerRef = useRef(undefined); + + const particlesInit = useCallback(async (engine: Engine) => { + await loadFireworksPreset(engine); + }, []); + + const particlesLoaded = useCallback((container?: Container) => { + containerRef.current = container; + }, []); + + const options = useMemo( + () => ({ + preset: "fireworks" as const, + fullScreen: { zIndex: -1 }, + background: { + color: "#000", + }, + }), + [], + ); + + return ; +} +``` + +## Full TypeScript Example with Container Ref + +Access the `Container` instance to control the animation programmatically (play, pause, destroy, export image): + +```tsx +"use client"; + +import Particles from "@tsparticles/react"; +import { useCallback, useMemo, useRef } from "react"; +import { loadFull } from "tsparticles"; +import type { Container, Engine, ISourceOptions } from "@tsparticles/engine"; + +export default function ControllableParticles() { + const containerRef = useRef(undefined); + + const particlesInit = useCallback(async (engine: Engine) => { + await loadFull(engine); + }, []); + + const particlesLoaded = useCallback((container?: Container) => { + containerRef.current = container; + }, []); + + const options: ISourceOptions = useMemo( + () => ({ + fullScreen: { zIndex: -1 }, + fpsLimit: 120, + interactivity: { + events: { + onClick: { enable: true, mode: "push" }, + onHover: { enable: true, mode: "repulse" }, + }, + modes: { + push: { quantity: 4 }, + repulse: { distance: 100 }, + }, + }, + particles: { + color: { value: "#ff0000" }, + links: { + enable: true, + color: "#ff0000", + distance: 150, + }, + move: { enable: true, speed: 2 }, + number: { value: 60 }, + size: { value: { min: 1, max: 5 } }, + }, + }), + [], + ); + + const handlePause = useCallback(() => { + containerRef.current?.pause(); + }, []); + + const handlePlay = useCallback(() => { + containerRef.current?.play(); + }, []); + + return ( +
+ +
+ + +
+
+ ); +} +``` + +Key points: + +- `particlesInit` loads the engine features (only runs once per component mount). +- `particlesLoaded` fires every time the container is fully initialized. +- `containerRef` holds the `Container` instance so you can call its methods later. + +## Performance: useMemo and useCallback + +Always wrap static or rarely-changing options in `useMemo` and event handlers in `useCallback` to prevent unnecessary re-renders of the canvas: + +```tsx +"use client"; + +import Particles from "@tsparticles/react"; +import { useCallback, useMemo, useState } from "react"; +import type { Container, ISourceOptions } from "@tsparticles/engine"; + +export default function PerformanceExample() { + const [particlesCount, setParticlesCount] = useState(80); + + // Stable callback — never recreates unless deps change + const particlesLoaded = useCallback((container?: Container) => { + console.log("Container ready", container?.id); + }, []); + + // Stable options object — prevents canvas re-initialization + const options: ISourceOptions = useMemo( + () => ({ + fullScreen: { zIndex: -1 }, + particles: { + number: { value: particlesCount }, + links: { enable: true }, + move: { enable: true }, + }, + }), + [particlesCount], + ); + + return ( +
+ + +
+ ); +} +``` + +Without these optimizations, every parent re-render would create a new `options` object, causing the canvas to be recreated. + +## Page Integration + +Add a particle background to a page layout without affecting the page content: + +```tsx +// app/layout.tsx (server component) +import dynamic from "next/dynamic"; + +const ParticlesBackground = dynamic(() => import("@/components/particles-background"), { ssr: false }); + +export default function RootLayout({ children }: { children: React.ReactNode }) { + return ( + + + +
{children}
+ + + ); +} +``` + +Use `dynamic()` with `ssr: false` to ensure the component never runs during server-side rendering. The particle canvas sits behind the main content via CSS `z-index`. + +## Multiple Instances + +You can render several independent `Particles` components on the same page, each with its own configuration: + +```tsx +"use client"; + +import Particles from "@tsparticles/react"; +import { useCallback, useMemo } from "react"; +import type { Container, ISourceOptions } from "@tsparticles/engine"; + +function ParticlesGallery() { + const loaded = useCallback((c?: Container) => {}, []); + + const redOptions: ISourceOptions = useMemo( + () => ({ + fullScreen: false, + height: 200, + background: { color: "#1a0000" }, + particles: { + color: { value: "#ff0000" }, + number: { value: 30 }, + move: { enable: true }, + }, + }), + [], + ); + + const blueOptions: ISourceOptions = useMemo( + () => ({ + fullScreen: false, + height: 200, + background: { color: "#00001a" }, + particles: { + color: { value: "#0000ff" }, + number: { value: 30 }, + move: { enable: true }, + }, + }), + [], + ); + + return ( +
+ + +
+ ); +} +``` + +Each `Particles` component creates an independent canvas with its own animation loop. Set `fullScreen: false` and give each a fixed height so they coexist in the document flow. + +## Legacy Pages Router + +If you are using the Next.js **Pages Router** (`pages/` directory), the approach is similar but without the `"use client"` directive. Instead, you can use a dynamic import in the page component: + +```tsx +// pages/index.tsx +import dynamic from "next/dynamic"; +import type { NextPage } from "next"; + +const ParticlesComponent = dynamic(() => import("../components/particles-component"), { ssr: false }); + +const Home: NextPage = () => { + return ( +
+ +

Welcome

+
+ ); +}; + +export default Home; +``` + +The component itself (`components/particles-component.tsx`) is a plain React component: + +```tsx +import Particles from "@tsparticles/react"; +import { useCallback, useMemo } from "react"; +import type { Container, ISourceOptions } from "@tsparticles/engine"; + +export default function ParticlesComponent() { + const particlesLoaded = useCallback((container?: Container) => {}, []); + + const options: ISourceOptions = useMemo( + () => ({ + fullScreen: { zIndex: -1 }, + particles: { + number: { value: 80 }, + links: { enable: true }, + move: { enable: true }, + }, + }), + [], + ); + + return ; +} +``` + +Note that the Pages Router does **not** require `"use client"` because page components are already client-rendered by default. + +## Troubleshooting + +| Symptom | Cause | Fix | +| ---------------------------- | --------------------------------------- | ---------------------------------------------------------------- | +| Blank white page | SSR rendering a canvas-dependent module | Use `dynamic(..., { ssr: false })` or wrap in a client component | +| Canvas not showing | Container has zero height | Set `fullScreen: { zIndex: -1 }` or give it explicit dimensions | +| Options change not reflected | New object reference not created | Use `useMemo` with proper dependency array | +| Preset not working | Preset not loaded before container init | Call `loadXPreset(engine)` inside the `init` callback | + +## Next Steps + +- Browse the [Interactive Demos](/demos/) for ready-made configurations. +- Read the full [Options Reference](/options/) for every available parameter. +- Check the [Presets](/demos/presets) page for more pre-built presets like snow, stars, and firefly. diff --git a/websites/website/docs/guides/nuxt.md b/websites/website/docs/guides/nuxt.md new file mode 100644 index 00000000000..d573f8d3555 --- /dev/null +++ b/websites/website/docs/guides/nuxt.md @@ -0,0 +1,463 @@ +--- +title: Nuxt Integration +description: Step-by-step guide to integrating tsParticles into a Nuxt 3 / Nuxt 4 application. +--- + +# Nuxt Integration + +This guide covers integrating tsParticles into a **Nuxt 3** (and Nuxt 4) project using the official `@tsparticles/vue3` wrapper. Nuxt runs both server-side and client-side, so you must guard particle components against SSR. + +## Installation + +Install the Vue 3 wrapper and the engine bundle of your choice: + +```bash +npm install @tsparticles/vue3 tsparticles +``` + +For a smaller bundle, install `@tsparticles/slim` instead of `tsparticles`: + +```bash +npm install @tsparticles/vue3 @tsparticles/slim +``` + +## Basic Usage + +Nuxt renders components on the server by default. Since tsParticles needs the browser `canvas` API, you must wrap the `` component in a `` tag: + +```vue + + + + + +``` + +The `` wrapper ensures the `` component is only mounted in the browser, preventing hydration mismatches. + +## Configuration + +Use the full `ISourceOptions` type for type-safe configuration. You can define your options inline or import them from a separate config file: + +```vue + +``` + +## Snow Effect + +Create a wintery snowfall effect using the snow preset: + +```bash +npm install @tsparticles/preset-snow +``` + +```vue + + + +``` + +Because the preset is loaded with top-level `await` in the ` +``` + +Available interaction modes include: `grab`, `bubble`, `connect`, `repulse`, `push`, `remove`, `attract`, and `slow`. + +## Event Handling + +The `` component emits several lifecycle events: + +```vue + + + +``` + +| Event | Payload | Description | +| -------------------- | ----------- | ------------------------------------------------------------ | +| `@particles-init` | `Engine` | Fires once when the tsParticles engine initializes | +| `@particles-loaded` | `Container` | Fires every time the container finishes loading or reloading | +| `@particles-destroy` | none | Fires when the container is destroyed | + +## Full TypeScript Example + +A complete, typed component with explicit imports and lifecycle awareness: + +```vue + + + + + +``` + +## Page Integration + +Add a particle background to a specific Nuxt page by placing the component in the page's template: + +```vue + + + + + +``` + +If you want particles on **every** page, add the component to `layouts/default.vue` instead of individual pages. + +## Nuxt 4 Notes + +Nuxt 4 maintains backward compatibility with Nuxt 3's `` and ` +``` + +## Troubleshooting + +| Symptom | Cause | Fix | +| --------------------------------- | ---------------------------------------- | ------------------------------------------------------------- | +| Blank screen / hydration error | `` rendered on the server | Wrap in `` | +| Preset has no effect | Preset not loaded before component mount | Call `loadXPreset()` with top-level await in ` + +``` + +The engine initializes once and is shared across all `` instances in your app. + +--- + +## Basic Usage + +After initializing the engine, use the `` component in your template. Pass the configuration as a JSON-stringified options object or a reference to a property on your component. + +```riot + + + + + +``` + +--- + +## Conditional Rendering + +Use Riot's `if={}` directive with a state property to delay rendering the particles component until the engine has finished initializing. This avoids layout shifts and ensures the component receives a ready engine. + +```riot + + + + + +``` + +Calling `this.update()` triggers a re-render so the `` tag appears once the promise resolves. + +--- + +## Preset Usage + +The `@tsparticles/configs` package provides pre-built configurations for common effects like confetti, fireworks, snow, and stars. Use them directly as your options object. + +```riot + + + + + +``` + +Available presets include `basic`, `confetti`, `fireworks`, `snow`, `stars`, and more. Each preset requires its corresponding preset package to be loaded in the engine callback. For example, `configs.fireworks` requires `loadFireworksPreset`. + +--- + +## Custom Configuration + +Build a custom configuration with interactivity, multiple shapes, and advanced animation options. + +```riot + + + + + +``` + +--- + +## Full Component + +Below is a complete `.riot` file that ties everything together: engine initialization in `onBeforeMount`, conditional rendering with state, a rich configuration with interactivity, and a `particlesLoaded` callback via the component's built-in support for loaded events. + +```riot + +
+

tsParticles + Riot.js

+ + {#if state.particlesInitialized} + + {:else} +

Loading particle engine...

+ {/if} +
+ + + + +
+``` + +--- + +You now have everything needed to integrate tsParticles into a Riot.js application. Each example is self-contained and ready to be copied into your project. diff --git a/websites/website/docs/guides/solid.md b/websites/website/docs/guides/solid.md new file mode 100644 index 00000000000..1ec1ee170ff --- /dev/null +++ b/websites/website/docs/guides/solid.md @@ -0,0 +1,512 @@ +--- +title: SolidJS Integration +description: Step-by-step guide to integrating tsParticles into a SolidJS application using the official @tsparticles/solid wrapper. +--- + +# SolidJS Integration + +This guide covers integrating tsParticles into a **SolidJS** project using the official `@tsparticles/solid` wrapper. SolidJS's fine-grained reactivity model works well with tsParticles — options changes trigger targeted canvas updates without full re-initialization. + +## Installation + +Install the SolidJS wrapper and the engine bundle of your choice: + +```bash +npm install @tsparticles/solid tsparticles +``` + +For a smaller bundle, use `@tsparticles/slim` instead: + +```bash +npm install @tsparticles/solid @tsparticles/slim +``` + +## Basic Usage + +SolidJS runs entirely in the browser (no SSR), so you do not need to guard against server rendering. However, the engine must be initialized asynchronously before rendering particles. + +Use `initParticlesEngine` inside `onMount` to load the engine features, then conditionally render the `` component with ``: + +```tsx +import { loadFull } from "tsparticles"; +import { createSignal, Show, onMount } from "solid-js"; +import type { Component } from "solid-js"; +import Particles, { initParticlesEngine } from "@tsparticles/solid"; +import type { Engine, ISourceOptions } from "@tsparticles/engine"; + +const App: Component = () => { + const [initialized, setInitialized] = createSignal(false); + + onMount(() => { + initParticlesEngine(async (engine: Engine) => { + await loadFull(engine); + }).then(() => setInitialized(true)); + }); + + const options: ISourceOptions = { + fullScreen: { zIndex: -1 }, + background: { color: "#0d47a1" }, + particles: { + number: { value: 80 }, + links: { enable: true, color: "#ffffff" }, + move: { enable: true }, + size: { value: 3 }, + }, + }; + + return ( + + + + ); +}; + +export default App; +``` + +The `` component ensures the `` element is only inserted into the DOM after the engine is ready. + +## Engine Initialization + +The `initParticlesEngine` function accepts a callback that receives the `Engine` instance. Use this callback to register the features your configuration needs: + +```tsx +import { initParticlesEngine } from "@tsparticles/solid"; +import { loadFull } from "tsparticles"; +import { loadSlim } from "@tsparticles/slim"; +import { loadConfettiPreset } from "@tsparticles/preset-confetti"; +import type { Engine } from "@tsparticles/engine"; + +// Minimal — only basic shapes and moves +initParticlesEngine((engine: Engine) => loadSlim(engine)).then(() => { + console.log("Engine ready (slim)"); +}); + +// Full — every feature included +initParticlesEngine((engine: Engine) => loadFull(engine)).then(() => { + console.log("Engine ready (full)"); +}); + +// Preset-only — just the features needed for a specific preset +initParticlesEngine((engine: Engine) => loadConfettiPreset(engine)).then(() => { + console.log("Confetti preset loaded"); +}); +``` + +Call `initParticlesEngine` once in your app — typically in the root component's `onMount`. The engine instance is cached, so subsequent calls return immediately. + +## Conditional Rendering + +Use SolidJS's `` control flow to defer rendering until the engine is initialized: + +```tsx +import { createSignal, Show, onMount } from "solid-js"; +import Particles, { initParticlesEngine } from "@tsparticles/solid"; +import { loadFull } from "tsparticles"; +import type { Engine } from "@tsparticles/engine"; +import type { Component } from "solid-js"; + +const App: Component = () => { + const [ready, setReady] = createSignal(false); + + onMount(() => { + initParticlesEngine((engine: Engine) => loadFull(engine)).then(() => setReady(true)); + }); + + return ( + Loading particles...

}> + +
+ ); +}; +``` + +The `fallback` prop shows a loading indicator while the engine initializes. + +## Preset Usage + +Use `@tsparticles/configs` for quick, pre-designed configurations: + +```bash +npm install @tsparticles/configs +``` + +```tsx +import configs from "@tsparticles/configs"; +import { loadFull } from "tsparticles"; +import { createSignal, Show, onMount } from "solid-js"; +import type { Component } from "solid-js"; +import Particles, { initParticlesEngine } from "@tsparticles/solid"; +import type { Engine } from "@tsparticles/engine"; + +const App: Component = () => { + const [ready, setReady] = createSignal(false); + + onMount(() => { + initParticlesEngine((engine: Engine) => loadFull(engine)).then(() => setReady(true)); + }); + + return ( + +
+ + +
+
+ ); +}; + +export default App; +``` + +Available configs include: `basic`, `bubbles`, `snow`, `stars`, `fireworks`, `confetti`, `links`, and more. + +## Interactive Particles + +Add click and hover interactions by configuring the `interactivity` section: + +```tsx +import { loadFull } from "tsparticles"; +import { createSignal, Show, onMount } from "solid-js"; +import type { Component } from "solid-js"; +import Particles, { initParticlesEngine } from "@tsparticles/solid"; +import type { Engine, ISourceOptions } from "@tsparticles/engine"; + +const App: Component = () => { + const [ready, setReady] = createSignal(false); + + onMount(() => { + initParticlesEngine((engine: Engine) => loadFull(engine)).then(() => setReady(true)); + }); + + const options: ISourceOptions = { + fullScreen: { zIndex: -1 }, + particles: { + number: { value: 60 }, + links: { enable: true, distance: 150 }, + move: { enable: true, speed: 2 }, + size: { value: { min: 1, max: 4 } }, + }, + interactivity: { + events: { + onHover: { enable: true, mode: "grab" }, + onClick: { enable: true, mode: "push" }, + }, + modes: { + grab: { distance: 200, links: { opacity: 0.5 } }, + push: { quantity: 4 }, + }, + }, + }; + + return ( + + + + ); +}; + +export default App; +``` + +- **Hover modes**: `grab`, `bubble`, `repulse`, `attract`, `slow`, `connect` +- **Click modes**: `push`, `remove`, `repulse`, `bubble`, `attract`, `pause` + +## Custom Configuration + +A full custom configuration with multiple particle shapes, color palettes, and motion settings: + +```tsx +import { loadFull } from "tsparticles"; +import { createSignal, Show, onMount } from "solid-js"; +import type { Component } from "solid-js"; +import Particles, { initParticlesEngine } from "@tsparticles/solid"; +import type { Engine, ISourceOptions } from "@tsparticles/engine"; + +const App: Component = () => { + const [ready, setReady] = createSignal(false); + + onMount(() => { + initParticlesEngine((engine: Engine) => loadFull(engine)).then(() => setReady(true)); + }); + + const options: ISourceOptions = { + fullScreen: { zIndex: -1 }, + background: { color: "#0a0a23" }, + fpsLimit: 60, + particles: { + color: { + value: ["#ff0000", "#00ff00", "#0000ff", "#ffff00", "#ff00ff"], + }, + move: { + enable: true, + speed: 1.5, + direction: "none", + random: true, + straight: false, + outModes: "bounce", + attract: { enable: true, rotateX: 600, rotateY: 1200 }, + }, + number: { + value: 40, + density: { enable: true }, + }, + opacity: { + value: { min: 0.3, max: 0.8 }, + animation: { + enable: true, + speed: 0.5, + sync: false, + }, + }, + size: { + value: { min: 2, max: 8 }, + animation: { + enable: true, + speed: 2, + sync: false, + }, + }, + links: { + enable: true, + distance: 200, + color: "#ffffff", + opacity: 0.3, + width: 1, + }, + shape: { + type: ["circle", "square", "triangle", "polygon"], + options: { + polygon: { sides: 6 }, + }, + }, + twinkle: { + particles: { + enable: true, + frequency: 0.05, + opacity: 1, + }, + }, + }, + interactivity: { + events: { + onHover: { enable: true, mode: "repulse" }, + onClick: { enable: true, mode: "bubble" }, + }, + modes: { + repulse: { distance: 120 }, + bubble: { distance: 200, size: 10, opacity: 0.8 }, + }, + }, + detectRetina: true, + }; + + return ( + + + + ); +}; + +export default App; +``` + +## Full TypeScript Example + +A complete typed component with container reference, engine initialization, and manual controls: + +```tsx +import { loadFull } from "tsparticles"; +import { createSignal, Show, onMount } from "solid-js"; +import type { Component } from "solid-js"; +import Particles, { initParticlesEngine } from "@tsparticles/solid"; +import type { Container, Engine, ISourceOptions } from "@tsparticles/engine"; + +const App: Component = () => { + const [ready, setReady] = createSignal(false); + const [container, setContainer] = createSignal(undefined); + const [paused, setPaused] = createSignal(false); + + onMount(() => { + initParticlesEngine(async (engine: Engine) => { + await loadFull(engine); + }).then(() => setReady(true)); + }); + + const options: ISourceOptions = { + fullScreen: { zIndex: -1 }, + background: { color: "#1a1a2e" }, + particles: { + color: { value: "#e94560" }, + number: { value: 80 }, + links: { enable: true, color: "#e94560", distance: 150 }, + move: { enable: true, speed: 2 }, + size: { value: { min: 1, max: 5 } }, + }, + }; + + const particlesLoaded = (c: Container) => { + setContainer(c); + }; + + const togglePause = () => { + const c = container(); + if (c) { + if (paused()) { + c.play(); + } else { + c.pause(); + } + setPaused(!paused()); + } + }; + + return ( + + + + + ); +}; + +export default App; +``` + +## Dynamic Options with Signals + +One of SolidJS's strengths is fine-grained reactivity — you can use signals to drive particle options and the canvas will update efficiently: + +```tsx +import { loadFull } from "tsparticles"; +import { createSignal, Show, onMount } from "solid-js"; +import type { Component } from "solid-js"; +import Particles, { initParticlesEngine } from "@tsparticles/solid"; +import type { Container, Engine, ISourceOptions } from "@tsparticles/engine"; + +const App: Component = () => { + const [ready, setReady] = createSignal(false); + const [color, setColor] = createSignal("#ff0000"); + const [particleCount, setParticleCount] = createSignal(60); + + onMount(() => { + initParticlesEngine((engine: Engine) => loadFull(engine)).then(() => setReady(true)); + }); + + // options are a regular object — it will be read reactively through + // the Particle component's internal tracking + const options = (): ISourceOptions => ({ + fullScreen: { zIndex: -1 }, + background: { color: "#000" }, + particles: { + color: { value: color() }, + number: { value: particleCount() }, + links: { enable: true, color: color() }, + move: { enable: true }, + }, + }); + + return ( + + {}} /> +
+ + +
+
+ ); +}; + +export default App; +``` + +Because `options` is a function that accesses signals, every time `color()` or `particleCount()` changes, the `` component receives a new options object and applies only the changed properties to the existing canvas. + +## Preset with Custom Overrides + +Load a preset, then merge custom overrides for a tailored effect: + +```tsx +import { loadSnowPreset } from "@tsparticles/preset-snow"; +import { createSignal, Show, onMount } from "solid-js"; +import type { Component } from "solid-js"; +import Particles, { initParticlesEngine } from "@tsparticles/solid"; +import type { Container, Engine, ISourceOptions } from "@tsparticles/engine"; + +const App: Component = () => { + const [ready, setReady] = createSignal(false); + + onMount(() => { + initParticlesEngine(async (engine: Engine) => { + await loadSnowPreset(engine); + }).then(() => setReady(true)); + }); + + const options: ISourceOptions = { + preset: "snow", + fullScreen: { zIndex: -1 }, + background: { color: "#0d0d2b" }, + particles: { + // Override the snow color to blue + color: { value: "#88ccff" }, + // Increase the number of flakes + number: { value: 300 }, + }, + }; + + return ( + + + + ); +}; + +export default App; +``` + +The preset provides default values for every option, and your overrides are merged on top — you only need to specify the properties you want to change. + +## Troubleshooting + +| Symptom | Cause | Fix | +| ---------------------------- | --------------------------------------- | ------------------------------------------------------------------------ | +| Blank DOM element | Engine not initialized before render | Wrap `` in `` | +| No particles visible | Missing `move.enable` or `number.value` | Ensure `particles.move.enable: true` and `particles.number.value > 0` | +| Canvas behind content | Missing `zIndex` in fullScreen | Use `fullScreen: { zIndex: -1 }` | +| Options change not reflected | Object reference not changing | Wrap options in a function or store; avoid static objects | +| Engine not found | Missing `loadFull` or `loadSlim` import | Install `tsparticles` or `@tsparticles/slim` and call `loadFull(engine)` | + +## Next Steps + +- Explore the [Configs playground](/playground/configs) for ready-to-use configurations. +- Read the [Options Reference](/options/) for the complete list of parameters. +- Browse the [SolidJS source](https://github.com/tsparticles/solid) on GitHub for wrapper internals. diff --git a/websites/website/docs/guides/stencil.md b/websites/website/docs/guides/stencil.md new file mode 100644 index 00000000000..83a0bfce600 --- /dev/null +++ b/websites/website/docs/guides/stencil.md @@ -0,0 +1,359 @@ +--- +title: Stencil Guide +description: Complete guide for integrating tsParticles with Stencil components. +--- + +# Stencil Guide + +## Table of Contents + +1. [Installation](#installation) +2. [Custom Elements Registration](#custom-elements-registration) +3. [Basic Usage](#basic-usage) +4. [Engine Initialization](#engine-initialization) +5. [Custom Configuration](#custom-configuration) +6. [Component Lifecycle](#component-lifecycle) +7. [TypeScript Example](#typescript-example) + +--- + +## Installation + +Install the Stencil wrapper and the tsParticles engine via npm: + +```bash +npm install @tsparticles/stencil tsparticles +``` + +Optionally install a preset bundle to reduce manual configuration: + +```bash +npm install @tsparticles/slim +``` + +--- + +## Custom Elements Registration + +The `@tsparticles/stencil` package provides a `defineCustomElements` function that registers the `` custom element with the browser. Call it once before using the component anywhere in your app. + +```tsx +import { defineCustomElements } from "@tsparticles/stencil/loader"; + +// Register the element +defineCustomElements(); +``` + +For Stencil projects using lazy-loading, call this inside `componentWillLoad` or in your app's root component to ensure the element is available before rendering. + +--- + +## Basic Usage + +Once the custom element is registered, you can use `` in your JSX with an `options` prop and an `init` callback to load the required engine features. + +```tsx +import { Component, h } from "@stencil/core"; +import type { ISourceOptions } from "@tsparticles/engine"; +import { loadSlim } from "@tsparticles/slim"; + +const options: ISourceOptions = { + fpsLimit: 60, + particles: { + number: { value: 80 }, + color: { value: "#00d4ff" }, + shape: { type: "circle" }, + opacity: { value: 0.6 }, + size: { value: { min: 2, max: 5 } }, + links: { + enable: true, + distance: 150, + color: "#00d4ff", + opacity: 0.3, + width: 1, + }, + move: { + enable: true, + speed: 1.5, + direction: "none", + random: true, + outModes: { default: "bounce" }, + }, + }, + background: { color: "#0d1117" }, +}; + +@Component({ tag: "my-particles" }) +export class MyParticles { + render() { + return ( + { + await loadSlim(engine); + }} + /> + ); + } +} +``` + +--- + +## Engine Initialization + +The `init` prop receives the engine instance and lets you load the features you need. This is the recommended place to call `loadSlim`, `loadFull`, or individual updater/interaction plugins. + +```tsx +import { loadSlim } from "@tsparticles/slim"; +import { loadFull } from "tsparticles"; +import { loadConfettiPreset } from "@tsparticles/preset-confetti"; + +// Option A: lightweight (circles, basic movement, links) +init={async engine => { await loadSlim(engine); }} + +// Option B: full feature set (all shapes, effects, presets) +init={async engine => { await loadFull(engine); }} + +// Option C: presets (confetti, fireworks, snow, stars) +init={async engine => { await loadConfettiPreset(engine); }} +``` + +The engine instance is also accessible after initialization through the `container-id` attribute, allowing you to programmatically control the particle system later if needed. + +--- + +## Custom Configuration + +Below is a full configuration with interactivity, multiple shape types, and hover/click modes. + +```tsx +import { Component, h } from "@stencil/core"; +import type { ISourceOptions } from "@tsparticles/engine"; +import { loadSlim } from "@tsparticles/slim"; + +const fullOptions: ISourceOptions = { + fpsLimit: 60, + particles: { + number: { + value: 60, + density: { enable: true, width: 800, height: 800 }, + }, + color: { + value: ["#ff6b6b", "#feca57", "#48dbfb", "#ff9ff3", "#54a0ff"], + }, + shape: { + type: ["circle", "triangle", "polygon"], + options: { + polygon: { sides: 6 }, + }, + }, + opacity: { value: { min: 0.4, max: 0.8 } }, + size: { value: { min: 3, max: 8 } }, + links: { + enable: true, + distance: 200, + color: "#ffffff", + opacity: 0.15, + width: 1, + }, + move: { + enable: true, + speed: 2, + direction: "none", + random: true, + straight: false, + outModes: { default: "out" }, + }, + }, + interactivity: { + events: { + onHover: { enable: true, mode: "attract" }, + onClick: { enable: true, mode: "repulse" }, + }, + modes: { + attract: { distance: 200, duration: 0.4, factor: 1 }, + repulse: { distance: 200, duration: 0.4 }, + }, + }, + background: { + color: "#0f0f23", + }, +}; + +@Component({ tag: "app-particles" }) +export class AppParticles { + render() { + return ( + { + await loadSlim(engine); + }} + /> + ); + } +} +``` + +--- + +## Component Lifecycle + +In Stencil, the recommended lifecycle hook for one-time setup is `componentWillLoad`. Use it to register custom elements and manage initialization state so that the `` component only renders when the engine is prepared. + +```tsx +import { Component, h, State } from "@stencil/core"; +import type { ISourceOptions } from "@tsparticles/engine"; +import { defineCustomElements } from "@tsparticles/stencil/loader"; +import { loadSlim } from "@tsparticles/slim"; + +@Component({ tag: "app-root" }) +export class AppRoot { + @State() private engineReady = false; + + private options: ISourceOptions = { + particles: { + number: { value: 50 }, + color: { value: "#ffffff" }, + shape: { type: "circle" }, + opacity: { value: 0.6 }, + size: { value: { min: 1, max: 4 } }, + move: { + enable: true, + speed: 1, + outModes: { default: "bounce" }, + }, + }, + background: { color: "#1a1a2e" }, + }; + + componentWillLoad() { + defineCustomElements(); + this.engineReady = true; + } + + render() { + return ( +
+

tsParticles + Stencil

+ {this.engineReady && ( + { + await loadSlim(engine); + }} + /> + )} +
+ ); + } +} +``` + +Using `@State()` ensures the component re-renders when the engine becomes ready, and the conditional render prevents the particles container from mounting before the custom element is defined. + +--- + +## TypeScript Example + +Here is a complete, typed Stencil application component that integrates tsParticles with the slim preset, hover interactivity, and a custom dark theme. + +```tsx +import { Component, h, State, Prop } from "@stencil/core"; +import type { Container, Engine, ISourceOptions } from "@tsparticles/engine"; +import { defineCustomElements } from "@tsparticles/stencil/loader"; +import { loadSlim } from "@tsparticles/slim"; + +@Component({ + tag: "app-home", + styleUrl: "app-home.css", + shadow: true, +}) +export class AppHome { + @State() private initialized = false; + + @Prop() readonly title: string = "Welcome"; + + private container?: Container; + + private readonly options: ISourceOptions = { + fullScreen: { enable: true, zIndex: -1 }, + fpsLimit: 60, + particles: { + number: { value: 80, density: { enable: true } }, + color: { value: "#6366f1" }, + shape: { type: "circle" }, + opacity: { value: { min: 0.3, max: 0.7 } }, + size: { value: { min: 2, max: 6 } }, + links: { + enable: true, + distance: 160, + color: "#6366f1", + opacity: 0.25, + width: 1, + }, + move: { + enable: true, + speed: 1.2, + direction: "none", + random: false, + straight: false, + outModes: { default: "bounce" }, + }, + }, + interactivity: { + events: { + onHover: { enable: true, mode: "grab" }, + onClick: { enable: true, mode: "push" }, + }, + modes: { + grab: { distance: 180, links: { opacity: 0.6 } }, + push: { quantity: 3 }, + }, + }, + background: { color: "#0a0a1a" }, + }; + + componentWillLoad() { + defineCustomElements(); + this.initialized = true; + } + + private handleInit = async (engine: Engine): Promise => { + await loadSlim(engine); + }; + + private handleLoaded = async (container?: Container): Promise => { + this.container = container; + console.log("Particles container loaded:", container?.id); + }; + + render() { + return ( +
+

{this.title}

+

Powered by tsParticles and Stencil

+ + {this.initialized && ( + + )} +
+ ); + } +} +``` + +The `particlesLoaded` event fires once the first frame is rendered, giving you access to the `Container` instance for programmatic control (play, pause, stop, switch themes). + +--- + +You now have everything needed to integrate tsParticles into a Stencil application. Each example is self-contained and ready to be copied into your project. diff --git a/websites/website/docs/guides/svelte.md b/websites/website/docs/guides/svelte.md new file mode 100644 index 00000000000..c7833ff1c2c --- /dev/null +++ b/websites/website/docs/guides/svelte.md @@ -0,0 +1,580 @@ +--- +title: Svelte Integration +description: Step-by-step guide for integrating tsParticles into Svelte and SvelteKit applications using @tsparticles/svelte. +--- + +# Svelte Integration + +The `@tsparticles/svelte` package provides a native Svelte component for tsParticles. This guide covers Svelte (with Vite) and SvelteKit, including reactive options, event handling, and multiple instances. + +--- + +## Installation + +```bash +npm install @tsparticles/svelte @tsparticles/engine +``` + +For the full bundle or presets: + +```bash +npm install tsparticles +npm install @tsparticles/preset-snow +npm install @tsparticles/preset-stars +npm install @tsparticles/preset-confetti +npm install @tsparticles/preset-fireworks +``` + +--- + +## Basic Usage + +```svelte + + + +``` + +--- + +## Engine Initialisation + +Pass an `on:init` event handler to load the plugins and presets your app needs: + +```svelte + + + +``` + +Alternatively, use the `initParticlesEngine` utility before mounting: + +```svelte + + +{#if ready} + +{/if} +``` + +--- + +## Snow Effect + +```bash +npm install @tsparticles/preset-snow +``` + +```svelte + + + +``` + +Customise the preset behaviour by merging additional options: + +```svelte + +``` + +--- + +## Stars Effect + +```bash +npm install @tsparticles/preset-stars +``` + +```svelte + + + +``` + +--- + +## Interactive Particles + +Add mouse hover and click interactivity: + +```svelte + + + +``` + +--- + +## Event Handling + +```svelte + + +
+ + + +
+ + +``` + +| Event | Detail | Fires | +| -------------------- | ----------- | ---------------------------------- | +| `on:init` | `Engine` | After the engine is initialised | +| `on:particlesLoaded` | `Container` | After the container is fully ready | + +--- + +## TypeScript Example + +Full typed component: + +```svelte + + + +``` + +--- + +## Dynamic Options + +Reactive options update the particles without recreating the instance: + +```svelte + + +
+ +
+ + +``` + +The `$:` reactive declaration recomputes `options` whenever `color` changes, and the `Particles` component picks up the new configuration automatically. + +--- + +## Multiple Instances + +Render several independent particle systems on the same page: + +```svelte + + +
+
+ +
+
+ +
+
+``` + +Each `` component gets its own `id`, canvas, and engine context. + +--- + +## SvelteKit Usage + +In SvelteKit, the canvas requires the browser environment. Disable SSR for the component: + +```svelte + + +{#if Component} + +{/if} +``` + +Or wrap the import in a client-only component. For SvelteKit 2+, you can also use the `vite-plugin-svelte` SSR excludes. + +--- + +## API Reference + +| Prop | Type | Default | Description | +| --------- | ---------------- | --------------- | ----------------------------- | +| `id` | `string` | `"tsparticles"` | Canvas element ID | +| `options` | `ISourceOptions` | `{}` | Particle configuration object | +| `url` | `string` | — | URL to a remote JSON config | + +| Event | Detail | Description | +| -------------------- | ----------- | ---------------------------------------------------------- | +| `on:init` | `Engine` | Fires when the engine is initialised (use to load plugins) | +| `on:particlesLoaded` | `Container` | Fires when the container is fully ready | + +--- + +## Troubleshooting + +- **Canvas not visible** — Ensure the parent container has explicit dimensions (`height: 100%`, `height: 100vh`, or a fixed pixel value). +- **`loadFull is not a function`** — Verify `tsparticles` is installed and that you're importing `loadFull` from `tsparticles` (not `@tsparticles/engine`). +- **Reactivity not working** — Make sure `options` is a reactive variable (`$:` or `let` bound to a reactive source). Plain `const` values will not update. +- **SvelteKit blank screen** — Import `@tsparticles/svelte` dynamically or use `browser` guard as shown in the SvelteKit section above. +- **TypeScript errors for `event.detail`** — Use `CustomEvent` and `CustomEvent` types for the event handlers. diff --git a/websites/website/docs/guides/vanilla.md b/websites/website/docs/guides/vanilla.md new file mode 100644 index 00000000000..5fe47c0c069 --- /dev/null +++ b/websites/website/docs/guides/vanilla.md @@ -0,0 +1,736 @@ +--- +title: Vanilla JS Guide +description: Complete guide for integrating tsParticles with plain JavaScript. +--- + +# Vanilla JS Guide + +## Table of Contents + +1. [Getting Started](#getting-started) +2. [Basic Particles](#basic-particles) +3. [Confetti Effect](#confetti-effect) +4. [Fireworks Effect](#fireworks-effect) +5. [Snow Effect](#snow-effect) +6. [Network / Links Effect](#network-links-effect) +7. [Stars Effect](#stars-effect) +8. [Custom Configuration](#custom-configuration) +9. [Multiple Containers](#multiple-containers) +10. [Dynamic Controls](#dynamic-controls) + +--- + +## Getting Started + +### CDN (quick start) + +Add a `
` placeholder and a script tag in your HTML: + +```html + + + + + + tsParticles – Getting Started + + + +
+ + + + + +``` + +### npm + +```bash +npm install tsparticles +``` + +Then import and use it: + +```javascript +import { tsParticles } from "tsparticles"; + +tsParticles.load({ + id: "tsparticles", + options: { + /* ... */ + }, +}); +``` + +--- + +## Basic Particles + +A minimal configuration that renders 100 particles with a circular shape, random colours, and gentle movement. + +```html + + + + + + Basic Particles + + + +
+ + + + + +``` + +--- + +## Confetti Effect + +Use the built-in confetti preset for a celebratory burst. + +```html + + + + + + Confetti + + + +
+ + + + + + +``` + +--- + +## Fireworks Effect + +A fireworks show with particles exploding across the screen. + +```html + + + + + + Fireworks + + + + + + + + +``` + +--- + +## Snow Effect + +Gentle falling snowflakes using the snow preset. + +```html + + + + + + Snow Effect + + + +
+ + + + + + +``` + +--- + +## Network Links Effect + +A classic connected-nodes visual with mouse interactivity. + +```html + + + + + + Network / Links + + + +
+ + + + + +``` + +--- + +## Stars Effect + +A starry-night sky using the stars preset. + +```html + + + + + + Stars Effect + + + +
+ + + + + + +``` + +--- + +## Custom Configuration + +Build a configuration from scratch with a gradient background, interactive hover effects, and multiple shape types. + +```html + + + + + + Custom Config + + + +

Custom Configuration

+
+ + + + + +``` + +--- + +## Multiple Containers + +Run multiple independent particle instances on the same page, each with its own configuration. + +```html + + + + + + Multiple Containers + + + +
+
+
+
+ + + + + +``` + +--- + +## Dynamic Controls + +Programmatically start, stop, pause, and switch themes at runtime. + +```html + + + + + + Dynamic Controls + + + +
+
+ + + + + + +
+ + + + + +``` + +--- + +You have now covered every major Vanilla JS integration pattern. Each example is a standalone HTML file you can open in your browser to see tsParticles in action. diff --git a/websites/website/docs/guides/vue3.md b/websites/website/docs/guides/vue3.md new file mode 100644 index 00000000000..f2493fe76e7 --- /dev/null +++ b/websites/website/docs/guides/vue3.md @@ -0,0 +1,620 @@ +--- +title: Vue 3 Integration +description: Step-by-step guide for integrating tsParticles into Vue 3 applications using @tsparticles/vue3. +--- + +# Vue 3 Integration + +The `@tsparticles/vue3` package provides a native Vue 3 component and plugin system for tsParticles. This guide covers everything from basic setup to advanced patterns like dynamic theme switching and custom presets. + +--- + +## Installation + +```bash +npm install @tsparticles/vue3 @tsparticles/engine +``` + +Optionally install a preset or the full bundle: + +```bash +# Full bundle (all features) +npm install tsparticles + +# Specific presets +npm install @tsparticles/preset-confetti +npm install @tsparticles/preset-fireworks +npm install @tsparticles/preset-snow +npm install @tsparticles/preset-stars + +# Utility configs +npm install @tsparticles/configs +``` + +--- + +## Basic Usage + +Register the plugin in your app entry point, then use the `` component anywhere. + +### App entry (`main.ts`) + +```typescript +import { createApp } from "vue"; +import App from "./App.vue"; +import { ParticlesPlugin } from "@tsparticles/vue3"; +import { loadFull } from "tsparticles"; + +const app = createApp(App); + +app.use(ParticlesPlugin, { + init: async (engine: Engine) => { + await loadFull(engine); + }, +}); + +app.mount("#app"); +``` + +### Component (`App.vue`) + +```vue + + + +``` + +--- + +## Using `particlesInit` with the Component + +If you prefer not to use the global plugin, pass an `init` callback directly: + +```vue + + + +``` + +--- + +## Events + +The component emits several lifecycle events: + +```vue + + + +``` + +--- + +## Confetti Effect + +Use the confetti preset for celebrations: + +```bash +npm install @tsparticles/preset-confetti +``` + +```vue + + + +``` + +For a one-shot burst, load the preset then call `tsParticles.load()` programmatically inside a method. + +--- + +## Fireworks Effect + +The fireworks preset creates high-impact particle explosions: + +```bash +npm install @tsparticles/preset-fireworks +``` + +```vue + + + +``` + +> **Tip:** The fireworks preset is resource-intensive. Trigger it on user interaction (e.g., button click) by toggling a `v-if` bound to the component. + +--- + +## Snow Effect + +Simulate falling snow with the snow preset: + +```bash +npm install @tsparticles/preset-snow +``` + +```vue + + + +``` + +--- + +## Interactive Particles + +Add hover and click interactivity modes: + +```vue + + + +``` + +Available interaction modes: `grab`, `repulse`, `bubble`, `connect`, `push`, `remove`, `trail`, `attract`, `light`. + +--- + +## Theme Switching + +Dynamically swap particle themes at runtime by updating the reactive options object: + +```vue + + + +``` + +Alternatively, use the built-in [themes](https://particles.js.org/docs/interfaces/Options_Interfaces_IOptions.IOptions.html#themes) option and the `theme` property on the container for zero-config switching. + +--- + +## Custom Preset from @tsparticles/configs + +The `@tsparticles/configs` package exports pre-made configuration objects: + +```bash +npm install @tsparticles/configs +``` + +```vue + + + +``` + +Browse available configs in the `@tsparticles/configs` package for ready-to-use layouts. + +--- + +## Engine Initialization Approaches + +There are two ways to initialise the engine: + +### 1. Global Plugin (recommended) + +```typescript +// main.ts +import { createApp } from "vue"; +import App from "./App.vue"; +import { ParticlesPlugin } from "@tsparticles/vue3"; +import { loadFull } from "tsparticles"; + +createApp(App) + .use(ParticlesPlugin, { + init: async (engine: Engine) => { + await loadFull(engine); + }, + }) + .mount("#app"); +``` + +The engine is then available globally and all `` instances share it. + +### 2. Component-Level Init + +Pass an `:init` callback to each `` instance. Useful when different components need different sets of plugins: + +```vue + +``` + +### 3. Particles Provider (Composition API) + +Use the provider to access the engine programmatically: + +```vue + +``` + +--- + +## Named Exports + TypeScript + +Full TypeScript example with all the pieces together: + +```vue + + + +``` + +--- + +## API Reference + +| Prop | Type | Default | Description | +| --------- | ----------------------------------- | --------------- | ------------------------------ | +| `id` | `string` | `"tsparticles"` | Canvas element ID | +| `options` | `ISourceOptions` | `{}` | Particle configuration | +| `init` | `(engine: Engine) => Promise` | — | Engine initialisation callback | +| `url` | `string` | — | URL to load JSON config from | + +| Event | Payload | Description | +| ------------------- | ----------- | --------------------------------------------- | +| `@particles-loaded` | `Container` | Fires when the container is fully initialised | +| `@particles-init` | `Engine` | Fires after the engine is initialised | + +--- + +## Troubleshooting + +- **Error: `tsparticles is not defined`** — Ensure `tsparticles` (or the presets you need) are loaded inside the `init` callback before the component renders. +- **Canvas not showing** — Verify the parent container has a non-zero height. Add a CSS rule like `#tsparticles { height: 100vh; }`. +- **Performance issues** — Lower `fpsLimit`, reduce `particles.number.value`, or disable `detectRetina` on low-end devices. +- **SSR (Nuxt)** — The `` component is client-only. Wrap it in `` or use the `client:only` directive. diff --git a/websites/website/docs/guides/webcomponents.md b/websites/website/docs/guides/webcomponents.md new file mode 100644 index 00000000000..534406f6c07 --- /dev/null +++ b/websites/website/docs/guides/webcomponents.md @@ -0,0 +1,359 @@ +# Web Components + +Use tsParticles with native Web Components via the `@tsparticles/webcomponents` package. This approach requires no framework — just vanilla JavaScript and custom elements. + +## Installation + +### Via CDN + +Include the tsParticles core and the Web Components bundle: + +```html + + +``` + +### Via npm + Build + +```bash +npm install @tsparticles/webcomponents tsparticles +``` + +Then import into your JavaScript bundle: + +```javascript +import { initParticlesEngine, defineParticlesElement } from "@tsparticles/webcomponents"; +``` + +## Engine Initialization + +Before the `` element can render, the engine must be initialized with the features you need. Call `initParticlesEngine` with a callback that loads the desired plugins: + +```javascript +import { initParticlesEngine } from "@tsparticles/webcomponents"; + +const { loadFull } = await import("tsparticles"); + +await initParticlesEngine(async (engine) => { + await loadFull(engine); +}); +``` + +> **Why `loadFull`?** It registers all built-in shapes (circle, square, polygon, image, etc.), interactions (hover, click), and updaters (opacity, size, color, etc.). For a smaller bundle, use `tsparticles-slim` or cherry-pick individual plugins. + +## Defining the Custom Element + +After engine initialization, register the `` custom element: + +```javascript +import { defineParticlesElement } from "@tsparticles/webcomponents"; + +defineParticlesElement(); +``` + +This registers the `web-particles` tag with the browser's `CustomElementRegistry`. It is safe to call multiple times — duplicate registrations are ignored. + +## Basic Usage + +Once both `initParticlesEngine` and `defineParticlesElement` have run, use the element directly in HTML: + +```html + + + + + + tsParticles Web Components + + + + + + + +``` + +## Custom Configuration + +The `` element accepts configuration via the `options` property (JavaScript object) or via JSON in the `options` attribute. + +### Via JavaScript Property + +```javascript +const el = document.querySelector("web-particles"); +el.options = { + background: { color: "#000000" }, + fpsLimit: 60, + particles: { + color: { value: ["#ff0000", "#00ff00", "#0000ff"] }, + links: { + enable: true, + distance: 150, + color: "#ffffff", + opacity: 0.4, + }, + move: { + enable: true, + speed: 3, + outModes: "bounce", + }, + number: { value: 60 }, + opacity: { value: 0.6 }, + shape: { type: ["circle", "square"] }, + size: { value: { min: 2, max: 6 } }, + }, + interactivity: { + events: { + onHover: { enable: true, mode: "repulse" }, + onClick: { enable: true, mode: "push" }, + }, + modes: { + repulse: { distance: 200 }, + push: { quantity: 4 }, + }, + }, +}; +``` + +### Via HTML Attribute (JSON) + +```html + +``` + +> When using the `options` attribute, the value must be valid JSON. Property assignment is preferred for complex configurations. + +## Dynamic Creation + +You can create `` elements entirely in JavaScript and add them to the DOM at any time: + +```javascript +import { initParticlesEngine, defineParticlesElement } from "@tsparticles/webcomponents"; + +const { loadFull } = await import("tsparticles"); + +await initParticlesEngine(async (engine) => { + await loadFull(engine); +}); + +defineParticlesElement(); + +function createParticles(container, config) { + const el = document.createElement("web-particles"); + el.id = "dynamic-particles"; + el.style.position = "absolute"; + el.style.width = "100%"; + el.style.height = "100%"; + el.style.top = "0"; + el.style.left = "0"; + el.options = config; + container.appendChild(el); + return el; +} + +// Usage +const particles = createParticles(document.body, { + background: { color: "#1a1a2e" }, + particles: { + number: { value: 100 }, + links: { enable: true, color: "#e94560" }, + move: { enable: true, speed: 1 }, + }, +}); +``` + +## Extending the Custom Element + +You can subclass `ParticlesElement` to create your own custom element with built-in configuration: + +```javascript +import { initParticlesEngine, ParticlesElement } from "@tsparticles/webcomponents"; + +const { loadFull } = await import("tsparticles"); + +await initParticlesEngine(async (engine) => { + await loadFull(engine); +}); + +class MyParticlesBackground extends ParticlesElement { + constructor() { + super(); + this.style.position = "fixed"; + this.style.top = "0"; + this.style.left = "0"; + this.style.width = "100%"; + this.style.height = "100%"; + this.style.zIndex = "-1"; + } + + connectedCallback() { + this.options = { + background: { color: "#0d47a1" }, + particles: { + number: { value: 80 }, + links: { enable: true, color: "#ffffff" }, + move: { enable: true, speed: 2 }, + }, + }; + super.connectedCallback(); + } +} + +customElements.define("my-particles-bg", MyParticlesBackground); +``` + +Usage: + +```html + +``` + +## Container Access and Control + +The custom element exposes the tsParticles `Container` instance for imperative control: + +```javascript +const el = document.querySelector("web-particles"); + +// Access the container (available after connectedCallback) +const container = el.container; +container?.pause(); +container?.play(); + +// Destroy and clean up +el.dispose(); +``` + +## Full Example + +A complete HTML page using the Web Components module with CDN scripts: + +```html + + + + + + tsParticles Web Components Demo + + + +
+

tsParticles + Web Components

+

Native custom elements, no framework required.

+
+ + + + + + +``` + +## API Reference + +| Export / Property | Type | Description | +| ------------------------------- | ------------------------ | ----------------------------------------------------- | +| `initParticlesEngine(callback)` | `function` | Initialize the tsParticles engine with plugin loaders | +| `defineParticlesElement()` | `function` | Register the `` custom element | +| `ParticlesElement` | `class` | Base class you can extend for custom elements | +| `element.options` | `ISourceOptions` | Get/set the particle configuration object | +| `element.container` | `Container \| undefined` | Read-only reference to the underlying `Container` | +| `element.dispose()` | `function` | Destroy the particle instance and clean up resources | diff --git a/websites/website/docs/guides/wordpress.md b/websites/website/docs/guides/wordpress.md new file mode 100644 index 00000000000..f9dd461f872 --- /dev/null +++ b/websites/website/docs/guides/wordpress.md @@ -0,0 +1,314 @@ +--- +title: WordPress Guide +description: Complete guide for integrating tsParticles with WordPress using the plugin, blocks, shortcodes, and theme integration. +--- + +# WordPress Guide + +## Table of Contents + +1. [Installation](#installation) +2. [Plugin Activation](#plugin-activation) +3. [Widget and Block Usage](#widget-and-block-usage) +4. [Shortcode Usage](#shortcode-usage) +5. [PHP Filter Configuration](#php-filter-configuration) +6. [Custom Configuration via Filter](#custom-configuration-via-filter) +7. [Theme Integration](#theme-integration) + +--- + +## Installation + +The tsParticles WordPress plugin is available through the WordPress Plugin Directory. Install it directly from your WordPress admin dashboard. + +### From WordPress Admin + +1. Navigate to **Plugins → Add New** +2. Search for "tsParticles" +3. Click **Install Now** on the tsParticles plugin +4. Click **Activate** + +### Manual Installation + +1. Download the plugin ZIP from the WordPress Plugin Directory or the [releases page](https://github.com/tsparticles/wordpress/releases) +2. Navigate to **Plugins → Add New → Upload Plugin** +3. Choose the ZIP file and click **Install Now** +4. Click **Activate** + +--- + +## Plugin Activation + +Once activated, the plugin registers: + +- A **Gutenberg block** named "tsParticles" available in the block inserter +- A **shortcode** `[tsparticles]` for use in the Classic Editor or custom PHP templates +- A **PHP filter** `tsparticles_options` for developers to inject configuration programmatically +- Front-end assets (JavaScript and CSS) that are enqueued only when the block or shortcode is present on the page + +After activation, you can verify the plugin is working by visiting **Settings → tsParticles** in the WordPress admin sidebar, where a basic settings page may be available depending on the plugin version. + +--- + +## Widget and Block Usage + +The tsParticles plugin adds a custom Gutenberg block for the block editor (WordPress 5.0+). + +### Adding the Block + +1. Edit any post or page with the block editor (Gutenberg) +2. Click the **+** (Add Block) button +3. Search for "tsParticles" or "Particles" +4. Click the **tsParticles** block to insert it + +### Block Settings + +Once inserted, the block inspector panel (on the right side) provides settings: + +- **Container ID** — a unique HTML ID for the particle container (default: `tsparticles`) +- **Width / Height** — set explicit dimensions or use full-screen mode +- **Z-Index** — controls layering relative to other content +- **Configuration** — paste a JSON options object to fully customize the particle appearance + +For theme-sidebar or widget areas that do not support blocks, use the [Shortcode](#shortcode-usage) approach instead. + +--- + +## Shortcode Usage + +Use the `[tsparticles]` shortcode in the Classic Editor, custom HTML blocks, or directly in PHP template files to embed particle backgrounds anywhere on your site. + +### Basic Shortcode + +``` +[tsparticles] +``` + +This renders the default particle configuration (simple floating circles on a dark background). + +### Shortcode with Options + +Pass JSON configuration directly in the shortcode using the `options` attribute: + +``` +[tsparticles options='{"particles":{"number":{"value":50},"color":{"value":"#ff0000"},"shape":{"type":"circle"},"opacity":{"value":0.5},"size":{"value":{"min":1,"max":3}},"move":{"enable":true,"speed":1,"outModes":{"default":"bounce"}}},"background":{"color":"#1a1a2e"}}'] +``` + +### Shortcode in PHP Templates + +```php +// In your theme's header.php or footer.php +echo do_shortcode('[tsparticles]'); +``` + +Or with custom options: + +```php +$options = [ + 'particles' => [ + 'number' => ['value' => 80], + 'color' => ['value' => '#00d4ff'], + 'shape' => ['type' => 'circle'], + 'links' => [ + 'enable' => true, + 'distance' => 150, + 'color' => '#00d4ff', + 'opacity' => 0.3, + ], + 'move' => [ + 'enable' => true, + 'speed' => 1.5, + 'outModes' => ['default' => 'bounce'], + ], + ], + 'background' => ['color' => '#0d1117'], +]; + +echo do_shortcode('[tsparticles options=\'' . wp_json_encode($options) . '\']'); +``` + +--- + +## PHP Filter Configuration + +The plugin exposes a `tsparticles_options` filter that lets you override or extend the particle configuration from your theme's `functions.php` file or a custom plugin. This is the recommended approach for developers because it keeps configuration in PHP and avoids inline JSON. + +### Basic Filter + +```php +// functions.php +add_filter('tsparticles_options', function (array $options): array { + $options['background'] = ['color' => '#0d1117']; + $options['particles']['number']['value'] = 100; + $options['particles']['color']['value'] = '#00d4ff'; + $options['particles']['shape']['type'] = 'circle'; + $options['particles']['opacity']['value'] = 0.6; + $options['particles']['size']['value'] = ['min' => 2, 'max' => 5]; + $options['particles']['links']['enable'] = true; + $options['particles']['links']['distance'] = 150; + $options['particles']['links']['color'] = '#00d4ff'; + $options['particles']['links']['opacity'] = 0.3; + $options['particles']['move']['enable'] = true; + $options['particles']['move']['speed'] = 1.5; + $options['particles']['move']['outModes']['default'] = 'bounce'; + return $options; +}); +``` + +This filter runs before the shortcode or block renders, so any instance of tsParticles on the page receives the customized configuration. + +--- + +## Custom Configuration via Filter + +Here is a complete custom configuration that demonstrates the full power of the filter — including interactivity, multiple shape types, and theme support. + +```php +// functions.php +add_filter('tsparticles_options', function (array $options): array { + + // Full-screen background + $options['fullScreen'] = [ + 'enable' => true, + 'zIndex' => -1, + ]; + + $options['fpsLimit'] = 60; + + // Particle settings + $options['particles'] = [ + 'number' => [ + 'value' => 60, + 'density' => ['enable' => true, 'width' => 800, 'height' => 800], + ], + 'color' => [ + 'value' => ['#ff6b6b', '#feca57', '#48dbfb', '#ff9ff3', '#54a0ff'], + ], + 'shape' => [ + 'type' => ['circle', 'triangle', 'polygon'], + 'options' => [ + 'polygon' => ['sides' => 6], + ], + ], + 'opacity' => [ + 'value' => ['min' => 0.4, 'max' => 0.8], + ], + 'size' => [ + 'value' => ['min' => 3, 'max' => 8], + ], + 'links' => [ + 'enable' => true, + 'distance' => 200, + 'color' => '#ffffff', + 'opacity' => 0.15, + 'width' => 1, + ], + 'move' => [ + 'enable' => true, + 'speed' => 2, + 'direction' => 'none', + 'random' => true, + 'straight' => false, + 'outModes' => ['default' => 'out'], + ], + ]; + + // Interactivity + $options['interactivity'] = [ + 'events' => [ + 'onHover' => ['enable' => true, 'mode' => 'attract'], + 'onClick' => ['enable' => true, 'mode' => 'repulse'], + ], + 'modes' => [ + 'attract' => ['distance' => 200, 'duration' => 0.4, 'factor' => 1], + 'repulse' => ['distance' => 200, 'duration' => 0.4], + ], + ]; + + // Background + $options['background'] = [ + 'color' => '#0f0f23', + ]; + + // Theme support — light mode toggle + $options['themes'] = [ + [ + 'name' => 'light', + 'default' => ['value' => false], + 'options' => [ + 'background' => ['color' => '#f0f0f5'], + 'particles' => [ + 'color' => ['value' => ['#e74c3c', '#2ecc71', '#3498db', '#f1c40f']], + 'links' => ['color' => '#333333', 'opacity' => 0.2], + ], + ], + ], + ]; + + return $options; +}); +``` + +--- + +## Theme Integration + +To make tsParticles a persistent background across your entire WordPress theme, add the shortcode or a direct PHP call to your theme's `header.php` or `footer.php`. + +### Header Background + +```php + + +
+ +
+ +``` + +### Full-Screen Background Styles + +Add the following CSS to your theme's `style.css` or via `wp_add_inline_style`: + +```css +#tsparticles-background { + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + z-index: -1; + pointer-events: none; +} + +/* Ensure content appears above the particles */ +.site-content { + position: relative; + z-index: 1; +} +``` + +### Conditional Loading + +To load tsParticles only on specific pages: + +```php +// In functions.php — enqueue only on the front page +add_action('wp', function () { + if (is_front_page()) { + add_filter('tsparticles_options', function (array $options): array { + $options['particles']['number']['value'] = 120; + $options['particles']['color']['value'] = '#ffffff'; + $options['particles']['move']['speed'] = 0.8; + $options['background']['color'] = '#1a1a2e'; + return $options; + }); + } +}); +``` + +Combine this with the block or shortcode placement for a performant, page-specific particle background. + +--- + +You now have everything needed to integrate tsParticles into a WordPress site. Whether you prefer the block editor, shortcodes, or full PHP control, each approach gives you a unique particle background with minimal effort. diff --git a/websites/website/docs/public/llms.txt b/websites/website/docs/public/llms.txt new file mode 100644 index 00000000000..ee7ea8d22fe --- /dev/null +++ b/websites/website/docs/public/llms.txt @@ -0,0 +1,199 @@ +# tsParticles Documentation + +> Official documentation for tsParticles — a lightweight, performant TypeScript library for creating highly customizable particle animations, confetti, fireworks, and ribbon effects. Supports React, Vue, Angular, Svelte, Next.js, Nuxt, Solid, Preact, Lit, Qwik, Ember, Riot, Inferno, jQuery, Astro, Web Components, WordPress, Stencil, and many other frameworks. Hosted at particles.js.org. + +## Getting Started + +- [Getting Started](https://particles.js.org/guide/getting-started): Quickstart guide for tsParticles +- [Installation](https://particles.js.org/guide/installation): Install tsParticles via npm, yarn, pnpm, or CDN +- [Bundle Overview](https://particles.js.org/guide/bundles): Comparison of available bundles (basic, slim, full, all, confetti, fireworks, particles) +- [Basic Bundle](https://particles.js.org/guide/bundles-basic): Lightweight bundle with core features +- [Slim Bundle](https://particles.js.org/guide/bundles-slim): Bundle without external plugins +- [Full Bundle](https://particles.js.org/guide/bundles-full): The full tsparticles bundle +- [All Bundle](https://particles.js.org/guide/bundles-all): All-inclusive bundle with every plugin +- [Confetti Bundle](https://particles.js.org/guide/bundles-confetti): Confetti-specific bundle +- [Fireworks Bundle](https://particles.js.org/guide/bundles-fireworks): Fireworks-specific bundle +- [Particles Bundle](https://particles.js.org/guide/bundles-particles): Minimal particles-only bundle + +## Playground + +- [Playground Overview](https://particles.js.org/playground/): Interactive playground to experiment with tsParticles configurations +- [Bundle Playground](https://particles.js.org/playground/bundles): Compare different tsParticles bundles +- [Configs Playground](https://particles.js.org/playground/configs): Browse built-in configuration examples +- [Shapes Playground](https://particles.js.org/playground/shapes): Explore available particle shapes +- [Presets Playground](https://particles.js.org/playground/presets): Try out preset configurations +- [Palettes Playground](https://particles.js.org/playground/palettes): Browse and test color palettes + +## Demos & Recipes + +- [Demos Overview](https://particles.js.org/demos/): Ready-to-use demonstration recipes +- [Presets Catalog](https://particles.js.org/demos/presets): Full catalog of available presets +- [Palettes Catalog](https://particles.js.org/demos/palettes): Full catalog of color palettes +- [Shapes Catalog](https://particles.js.org/demos/shapes): Full catalog of particle shapes +- [Ambient Recipe](https://particles.js.org/demos/recipes/ambient): Ambient particle effect +- [Big Circles Recipe](https://particles.js.org/demos/recipes/big-circles): Big circles particle effect +- [Bubbles Recipe](https://particles.js.org/demos/recipes/bubbles): Bubbles particle effect +- [Confetti Recipe](https://particles.js.org/demos/recipes/confetti): Confetti particle effect +- [Confetti Cannon Recipe](https://particles.js.org/demos/recipes/confetti-cannon): Confetti cannon effect +- [Confetti Explosions Recipe](https://particles.js.org/demos/recipes/confetti-explosions): Confetti explosions effect +- [Confetti Falling Recipe](https://particles.js.org/demos/recipes/confetti-falling): Falling confetti effect +- [Confetti Parade Recipe](https://particles.js.org/demos/recipes/confetti-parade): Confetti parade effect +- [Party Recipe](https://particles.js.org/demos/recipes/party): Party particle effect +- [Fire Recipe](https://particles.js.org/demos/recipes/fire): Fire particle effect +- [Firefly Recipe](https://particles.js.org/demos/recipes/firefly): Firefly particle effect +- [Fireworks Recipe](https://particles.js.org/demos/recipes/fireworks): Fireworks particle effect +- [Fountain Recipe](https://particles.js.org/demos/recipes/fountain): Fountain particle effect +- [Hyperspace Recipe](https://particles.js.org/demos/recipes/hyperspace): Hyperspace particle effect +- [Links Recipe](https://particles.js.org/demos/recipes/links): Connecting links particle effect +- [Matrix Recipe](https://particles.js.org/demos/recipes/matrix): Matrix rain particle effect +- [Ribbons Recipe](https://particles.js.org/demos/recipes/ribbons): Ribbon particle effect +- [Sea Anemone Recipe](https://particles.js.org/demos/recipes/sea-anemone): Sea anemone particle effect +- [Snow Recipe](https://particles.js.org/demos/recipes/snow): Snowfall particle effect +- [Squares Recipe](https://particles.js.org/demos/recipes/squares): Squares particle effect +- [Stars Recipe](https://particles.js.org/demos/recipes/stars): Stars particle effect +- [Triangles Recipe](https://particles.js.org/demos/recipes/triangles): Triangles particle effect + +## Configuration Options + +- [Options Reference](https://particles.js.org/options/): Complete configuration reference index +- [Background & Canvas](https://particles.js.org/options/background): Background color, image, and canvas sizing +- [Background Mask](https://particles.js.org/options/background-mask): Background masking options +- [Full Screen](https://particles.js.org/options/fullscreen): Full-screen mode configuration +- [Motion](https://particles.js.org/options/motion): Motion preferences and reduced motion support +- [Manual Particles](https://particles.js.org/options/manual-particles): Manual particle placement +- [Themes](https://particles.js.org/options/themes): Theme configuration for dark/light mode +- [Performance Guide](https://particles.js.org/options/performance): Performance optimization tips and best practices +- [Particles](https://particles.js.org/options/particles): Core particle configuration +- [Particles Number](https://particles.js.org/options/particles-number): Particle count and density +- [Particles Move](https://particles.js.org/options/particles-move): Particle movement and speed +- [Particles Links](https://particles.js.org/options/particles-links): Particle linking lines +- [Particles Shape](https://particles.js.org/options/particles-shape): Particle shape (circle, square, star, etc.) +- [Particles Color](https://particles.js.org/options/particles-color): Particle color configuration +- [Particles Size](https://particles.js.org/options/particles-size): Particle size configuration +- [Particles Opacity](https://particles.js.org/options/particles-opacity): Particle opacity +- [Particles ZIndex](https://particles.js.org/options/particles-zindex): Particle z-index layering +- [Particles Palette](https://particles.js.org/options/particles-palette): Particle color palettes +- [Particles Bounce](https://particles.js.org/options/particles-bounce): Particle bounce behavior +- [Particles Collisions](https://particles.js.org/options/particles-collisions): Particle collision detection +- [Particles Destroy](https://particles.js.org/options/particles-destroy): Particle destruction on boundaries +- [Particles Group](https://particles.js.org/options/particles-group): Particle grouping +- [Particles Life](https://particles.js.org/options/particles-life): Particle lifecycle duration +- [Particles Orbit](https://particles.js.org/options/particles-orbit): Particle orbit motion +- [Particles Repulse](https://particles.js.org/options/particles-repulse): Particle repulsion +- [Particles Roll](https://particles.js.org/options/particles-roll): Particle rolling effect +- [Particles Rotate](https://particles.js.org/options/particles-rotate): Particle rotation +- [Particles Shadow](https://particles.js.org/options/particles-shadow): Particle shadows +- [Particles Stroke](https://particles.js.org/options/particles-stroke): Particle stroke/outline +- [Particles Tilt](https://particles.js.org/options/particles-tilt): Particle tilt +- [Particles Twinkle](https://particles.js.org/options/particles-twinkle): Particle twinkle effect +- [Particles Wobble](https://particles.js.org/options/particles-wobble): Particle wobble effect +- [Particles Paint](https://particles.js.org/options/particles-paint): Particle paint effect +- [Interactivity](https://particles.js.org/options/interactivity): Mouse/touch interactivity overview +- [Interactivity Events](https://particles.js.org/options/interactivity-events): Event configuration for interactivity +- [Interactivity Modes](https://particles.js.org/options/interactivity-modes): Interaction mode configuration +- [Interactivity Click](https://particles.js.org/options/interactivity-click): Click interaction modes +- [Interactivity Hover](https://particles.js.org/options/interactivity-hover): Hover interaction modes +- [Interactivity Div](https://particles.js.org/options/interactivity-div): Div element interaction modes + +### Plugin Options + +- [Plugin: Absorbers](https://particles.js.org/options/plugin-absorbers): Absorber plugin options +- [Plugin: Background Mask](https://particles.js.org/options/plugin-background-mask): Background mask plugin options +- [Plugin: Blend](https://particles.js.org/options/plugin-blend): Blend mode plugin +- [Plugin: Canvas Mask](https://particles.js.org/options/plugin-canvas-mask): Canvas mask plugin +- [Plugin: Colors](https://particles.js.org/options/plugin-colors): Color plugin options +- [Plugin: Easings](https://particles.js.org/options/plugin-easings): Easing functions plugin +- [Plugin: Effects](https://particles.js.org/options/plugin-effects): Effects plugin options +- [Plugin: Emitter Shapes](https://particles.js.org/options/plugin-emitter-shapes): Emitter shape plugin +- [Plugin: Emitters](https://particles.js.org/options/plugin-emitters): Emitter plugin (continuous particle spawning) +- [Plugin: Exports](https://particles.js.org/options/plugin-exports): Export plugin (image/video capture) +- [Plugin: Infection](https://particles.js.org/options/plugin-infection): Infection plugin +- [Plugin: Interactions](https://particles.js.org/options/plugin-interactions): Custom interaction plugin +- [Plugin: Motion](https://particles.js.org/options/plugin-motion): Motion plugin +- [Plugin: Path Generators](https://particles.js.org/options/plugin-path-generators): Custom path generation plugin +- [Plugin: Poisson](https://particles.js.org/options/plugin-poisson): Poisson disc sampling plugin +- [Plugin: Polygon Mask](https://particles.js.org/options/plugin-polygon-mask): Polygon mask plugin (image-based masks) +- [Plugin: Responsive](https://particles.js.org/options/plugin-responsive): Responsive breakpoints plugin +- [Plugin: Shapes](https://particles.js.org/options/plugin-shapes): Custom shape plugin +- [Plugin: Sounds](https://particles.js.org/options/plugin-sounds): Sound effects plugin +- [Plugin: Themes](https://particles.js.org/options/plugin-themes): Theme management plugin +- [Plugin: Trail](https://particles.js.org/options/plugin-trail): Particle trail plugin +- [Plugin: Updaters](https://particles.js.org/options/plugin-updaters): Custom updater plugin +- [Plugin: Zoom](https://particles.js.org/options/plugin-zoom): Zoom interaction plugin + +## Framework Wrappers + +- [Wrappers Overview](https://particles.js.org/guide/wrappers): Official framework wrappers overview +- [Framework Integrations](https://particles.js.org/guide/frameworks): How to integrate tsParticles with frameworks +- [React](https://particles.js.org/guide/wrappers-react): React.js wrapper (react-tsparticles) +- [Vue 3](https://particles.js.org/guide/wrappers-vue3): Vue.js 3.x wrapper +- [Vue 2](https://particles.js.org/guide/wrappers-vue2): Vue.js 2.x wrapper +- [Angular](https://particles.js.org/guide/wrappers-angular): Angular wrapper +- [Angular Confetti](https://particles.js.org/guide/wrappers-angular-confetti): Angular confetti component +- [Angular Fireworks](https://particles.js.org/guide/wrappers-angular-fireworks): Angular fireworks component +- [Svelte](https://particles.js.org/guide/wrappers-svelte): Svelte wrapper +- [Next.js](https://particles.js.org/guide/wrappers-nextjs): Next.js wrapper +- [Nuxt 2](https://particles.js.org/guide/wrappers-nuxt2): Nuxt 2 wrapper +- [Nuxt 3](https://particles.js.org/guide/wrappers-nuxt3): Nuxt 3 wrapper +- [Nuxt 4](https://particles.js.org/guide/wrappers-nuxt4): Nuxt 4 wrapper +- [Astro](https://particles.js.org/guide/wrappers-astro): Astro integration +- [Solid](https://particles.js.org/guide/wrappers-solid): SolidJS wrapper +- [Preact](https://particles.js.org/guide/wrappers-preact): Preact wrapper +- [Lit](https://particles.js.org/guide/wrappers-lit): Lit (Web Components) wrapper +- [Qwik](https://particles.js.org/guide/wrappers-qwik): Qwik wrapper +- [Ember](https://particles.js.org/guide/wrappers-ember): Ember.js wrapper +- [Riot](https://particles.js.org/guide/wrappers-riot): Riot.js wrapper +- [Inferno](https://particles.js.org/guide/wrappers-inferno): Inferno wrapper +- [jQuery](https://particles.js.org/guide/wrappers-jquery): jQuery plugin +- [Stencil](https://particles.js.org/guide/wrappers-stencil): Stencil.js wrapper +- [Web Components](https://particles.js.org/guide/wrappers-webcomponents): Vanilla Web Components wrapper +- [WordPress](https://particles.js.org/guide/wrappers-wordpress): WordPress plugin integration + +## Plugin & Customization Development + +- [Customization Overview](https://particles.js.org/guide/plugins-customization): Guide for extending tsParticles +- [Custom Plugin](https://particles.js.org/guide/plugins-customization-plugin): Creating custom plugins +- [Custom Shape](https://particles.js.org/guide/plugins-customization-shape): Creating custom shapes +- [Custom Preset](https://particles.js.org/guide/plugins-customization-preset): Creating custom presets +- [Custom Updater](https://particles.js.org/guide/plugins-customization-updater): Creating custom updaters +- [Custom Effect](https://particles.js.org/guide/plugins-customization-effect): Creating custom effects +- [Custom Interaction](https://particles.js.org/guide/plugins-customization-interaction): Creating custom interactions +- [Custom Path](https://particles.js.org/guide/plugins-customization-path): Creating custom path generators +- [Custom Palette](https://particles.js.org/guide/plugins-customization-palette): Creating custom color palettes +- [Custom Bundle](https://particles.js.org/guide/plugins-customization-bundle): Creating custom bundles + +## Migration & Versioning + +- [Versioning Overview](https://particles.js.org/migrations/): Versioning and migration guides +- [Migrate from v3.x](https://particles.js.org/migrations/from-v3): Upgrade guide from v3.x to v4 +- [Migrate from v2.x](https://particles.js.org/migrations/from-v2): Upgrade guide from v2.x to v4 +- [Migrate from v1.x](https://particles.js.org/migrations/from-v1): Upgrade guide from v1.x to v4 +- [Option Rename Matrix](https://particles.js.org/migrations/option-rename-matrix): Cross-version option name mapping +- [particles.js Migration](https://particles.js.org/migrations/particles-js): Migrate from particles.js to tsParticles +- [Changelog](https://particles.js.org/migrations/changelog): Full release changelog +- [Releases](https://particles.js.org/migrations/releases): Release announcements and notes + +## Additional Resources + +- [Color Formats](https://particles.js.org/guide/color-formats): Supported color formats in tsParticles +- [Container Lifecycle](https://particles.js.org/guide/container-lifecycle): Understanding the container lifecycle +- [Templates & Resources](https://particles.js.org/guide/templates-resources): Starter templates and additional resources +- [Video Tutorials](https://particles.js.org/guide/video-tutorials): Video tutorials for tsParticles +- [Dependency Graph](https://particles.js.org/guide/dependency-graph): Visual dependency graph of tsParticles packages +- [Showcase](https://particles.js.org/showcase/): Community showcase of tsParticles in action + +## API Reference + +- [TypeDoc API](https://particles.js.org/docs/): Full TypeScript API reference documentation (auto-generated with TypeDoc) + +## External Sites + +- [Confetti Website](https://confetti.js.org): Interactive confetti animation playground +- [Ribbons Website](https://ribbons.js.org): Interactive ribbon animation playground +- [GitHub Repository](https://github.com/tsparticles/tsparticles): Source code, issues, and contributions +- [npm @tsparticles/engine](https://www.npmjs.com/package/@tsparticles/engine): Core engine package +- [npm tsparticles](https://www.npmjs.com/package/tsparticles): Full bundle package + +## Localized Documentation + +The website is available in 10 languages (English, Italian, French, Spanish, German, Portuguese, Russian, Chinese, Japanese, Hindi). All pages listed above are available under each language prefix: `/it/`, `/fr/`, `/es/`, `/de/`, `/pt/`, `/ru/`, `/zh/`, `/ja/`, `/hi/`. diff --git a/websites/website/docs/public/robots.txt b/websites/website/docs/public/robots.txt new file mode 100644 index 00000000000..06730f9280c --- /dev/null +++ b/websites/website/docs/public/robots.txt @@ -0,0 +1,3 @@ +User-agent: * +Allow: / +Sitemap: https://particles.js.org/sitemap.xml From 58b7ef83b48a4979519349c3cb6fd3cfe2cf6f5b Mon Sep 17 00:00:00 2001 From: Matteo Bruni <176620+matteobruni@users.noreply.github.com> Date: Thu, 4 Jun 2026 15:16:14 +0200 Subject: [PATCH 2/4] fix: various fixes after deeper review --- websites/confetti/index.html | 4 ++-- websites/ribbons/index.html | 4 ++-- websites/website/docs/.vitepress/config.ts | 24 +++++++++++++++---- websites/website/docs/guides/angular.md | 2 +- websites/website/docs/guides/jquery.md | 22 +++++++---------- websites/website/docs/guides/react.md | 5 ++-- websites/website/docs/guides/riot.md | 10 ++++---- websites/website/docs/guides/vue3.md | 2 ++ websites/website/docs/guides/webcomponents.md | 4 ++-- wrappers/stencil/src/components.d.ts | 3 +++ .../components/stencil-particles/readme.md | 11 +++++---- .../stencil-particles/stencil-particles.tsx | 7 ++++-- 12 files changed, 58 insertions(+), 40 deletions(-) diff --git a/websites/confetti/index.html b/websites/confetti/index.html index 59bb9e6c491..7407681bce1 100644 --- a/websites/confetti/index.html +++ b/websites/confetti/index.html @@ -27,7 +27,7 @@ - + - + diff --git a/websites/ribbons/index.html b/websites/ribbons/index.html index 1529459aa25..44ad868b8ae 100644 --- a/websites/ribbons/index.html +++ b/websites/ribbons/index.html @@ -27,7 +27,7 @@ - + - + diff --git a/websites/website/docs/.vitepress/config.ts b/websites/website/docs/.vitepress/config.ts index 13203f058dd..edd4da33025 100644 --- a/websites/website/docs/.vitepress/config.ts +++ b/websites/website/docs/.vitepress/config.ts @@ -367,8 +367,7 @@ export default defineConfig({ base, ignoreDeadLinks: [], transformHead: ({ pageData }) => { - const path = pageData.relativePath.replace(/\.md$/, "").replace(/index$/, ""); - const canonical = `https://particles.js.org/${path}`; + let path = pageData.relativePath.replace(/\.md$/, "").replace(/\/?index$/, ""); const localePrefixesMap: Record = { root: "x-default", it: "it", @@ -381,18 +380,35 @@ export default defineConfig({ ja: "ja", hi: "hi", }; + let detectedLocale = "root"; + for (const locale of Object.keys(localePrefixesMap)) { + if (locale === "root") continue; + if (path === locale || path.startsWith(locale + "/")) { + detectedLocale = locale; + path = path.slice(locale.length).replace(/^\//, ""); + break; + } + } const head: any[] = []; for (const [locale, hreflang] of Object.entries(localePrefixesMap)) { - const prefix = locale === "root" ? "" : `/${locale}`; + const hrefPath = locale === "root" ? path : `${locale}/${path}`; head.push([ "link", { rel: "alternate", - href: `https://particles.js.org${prefix}/${path}`, + href: `https://particles.js.org/${hrefPath}`, hreflang, }, ]); } + const canonicalPath = detectedLocale === "root" ? path : `${detectedLocale}/${path}`; + head.push([ + "link", + { + rel: "canonical", + href: `https://particles.js.org/${canonicalPath}`, + }, + ]); return head; }, locales: { diff --git a/websites/website/docs/guides/angular.md b/websites/website/docs/guides/angular.md index 26143aa454a..a2423ac4ba6 100644 --- a/websites/website/docs/guides/angular.md +++ b/websites/website/docs/guides/angular.md @@ -495,7 +495,7 @@ No `NgModule` wrapper needed — just import `NgParticlesModule` in the componen ```typescript import { Component, OnInit } from "@angular/core"; import type { Container, Engine, ISourceOptions } from "@tsparticles/engine"; -import { loadSlim } from "tsparticles"; +import { loadSlim } from "@tsparticles/slim"; import { NgParticlesService } from "@tsparticles/angular"; @Component({ diff --git a/websites/website/docs/guides/jquery.md b/websites/website/docs/guides/jquery.md index 01f457caf36..9963194d57e 100644 --- a/websites/website/docs/guides/jquery.md +++ b/websites/website/docs/guides/jquery.md @@ -8,19 +8,13 @@ Integrate tsParticles into your jQuery-based projects with the official jQuery p Include jQuery, tsParticles, and the jQuery plugin via script tags: -```html +````html - - -``` - -### Via npm + Build + + -Install the required packages: - -```bash -npm install jquery @tsparticles/jquery tsparticles -``` +--- ### Via npm + Build Install the required packages: ```bash npm install jquery @tsparticles/jquery tsparticles +```` Import into your project: @@ -213,12 +207,12 @@ Below is a complete, self-contained HTML page that loads tsParticles via CDN and
- - + + - + + ``` ### Via npm + Build diff --git a/wrappers/stencil/src/components.d.ts b/wrappers/stencil/src/components.d.ts index 247e2b5993a..d6551c2d0f8 100644 --- a/wrappers/stencil/src/components.d.ts +++ b/wrappers/stencil/src/components.d.ts @@ -11,6 +11,7 @@ export { ISourceOptions } from "@tsparticles/engine"; export { ParticlesPluginRegistrar } from "./initParticlesEngine"; export namespace Components { interface StencilParticles { + "containerId"?: string; "init"?: ParticlesPluginRegistrar; "options"?: ISourceOptions; "url"?: string; @@ -29,6 +30,7 @@ declare global { } declare namespace LocalJSX { interface StencilParticles { + "containerId"?: string; "init"?: ParticlesPluginRegistrar; "options"?: ISourceOptions; "url"?: string; @@ -36,6 +38,7 @@ declare namespace LocalJSX { interface StencilParticlesAttributes { "url": string; + "containerId": string; } interface IntrinsicElements { diff --git a/wrappers/stencil/src/components/stencil-particles/readme.md b/wrappers/stencil/src/components/stencil-particles/readme.md index 04e1b8a5e05..ef2f2bac4ba 100644 --- a/wrappers/stencil/src/components/stencil-particles/readme.md +++ b/wrappers/stencil/src/components/stencil-particles/readme.md @@ -5,11 +5,12 @@ ## Properties -| Property | Attribute | Description | Type | Default | -| --------- | --------- | ----------- | ------------------------------------------- | ----------- | -| `init` | -- | | `(engine: Engine) => void \| Promise` | `undefined` | -| `options` | -- | | `IOptions` | `undefined` | -| `url` | `url` | | `string` | `undefined` | +| Property | Attribute | Description | Type | Default | +| ------------- | -------------- | ----------- | ------------------------------------------- | ----------- | +| `containerId` | `container-id` | | `string` | `undefined` | +| `init` | -- | | `(engine: Engine) => void \| Promise` | `undefined` | +| `options` | -- | | `IOptions` | `undefined` | +| `url` | `url` | | `string` | `undefined` | ---------------------------------------------- diff --git a/wrappers/stencil/src/components/stencil-particles/stencil-particles.tsx b/wrappers/stencil/src/components/stencil-particles/stencil-particles.tsx index 6132de1d9b7..ab141ce7661 100644 --- a/wrappers/stencil/src/components/stencil-particles/stencil-particles.tsx +++ b/wrappers/stencil/src/components/stencil-particles/stencil-particles.tsx @@ -12,6 +12,7 @@ export class StencilParticles { @Prop() options?: ISourceOptions; @Prop() url?: string; @Prop() init?: ParticlesPluginRegistrar; + @Prop() containerId?: string; private container?: Container; private renderId = 0; @@ -57,9 +58,10 @@ export class StencilParticles { } // Load particles directly onto the DOM element. - // tsParticles will auto-generate a unique internal ID, preventing collisions. - const loadParams = { + // If a container-id is provided, use it so consumers can retrieve the container later. + const loadParams: Record = { element: this.containerElement, + ...(this.containerId ? { id: this.containerId } : {}), ...(this.options ? { options: this.options } : { url: this.url! }), }; @@ -81,6 +83,7 @@ export class StencilParticles { render(): JSX.Element { return (
{ this.containerElement = el as HTMLDivElement; }} From 7f398048915819a380856bdce4b6b4af4aaab9a4 Mon Sep 17 00:00:00 2001 From: Matteo Bruni <176620+matteobruni@users.noreply.github.com> Date: Thu, 4 Jun 2026 15:28:12 +0200 Subject: [PATCH 3/4] fix: various fixes after deeper review --- websites/website/docs/guides/jquery.md | 17 ++++++++++++----- websites/website/docs/guides/webcomponents.md | 2 +- .../stencil-particles/stencil-particles.tsx | 1 + 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/websites/website/docs/guides/jquery.md b/websites/website/docs/guides/jquery.md index 9963194d57e..1be880b2342 100644 --- a/websites/website/docs/guides/jquery.md +++ b/websites/website/docs/guides/jquery.md @@ -8,13 +8,21 @@ Integrate tsParticles into your jQuery-based projects with the official jQuery p Include jQuery, tsParticles, and the jQuery plugin via script tags: -````html +```html +``` + +--- + +### Via npm + Build ---- ### Via npm + Build Install the required packages: ```bash npm install jquery @tsparticles/jquery tsparticles -```` +Install the required packages: + +```bash +npm install jquery @tsparticles/jquery tsparticles +``` Import into your project: @@ -212,8 +220,7 @@ Below is a complete, self-contained HTML page that loads tsParticles via CDN and