UI Components Easy
Cool Mode
Fun particle burst of emojis and shapes that explode from every click point with physics-based motion and fadeout.
Open in Lab
MCP
css javascript vue svelte
Targets: TS JS HTML React Vue Svelte
Code
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: system-ui, -apple-system, sans-serif;
min-height: 100vh;
background: #0a0a0a;
color: #f1f5f9;
overflow: hidden;
}
.cool-page {
width: 100vw;
height: 100vh;
display: grid;
place-items: center;
position: relative;
}
.cool-content {
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
gap: 1.5rem;
position: relative;
z-index: 2;
}
.cool-title {
font-size: clamp(2rem, 5vw, 3.5rem);
font-weight: 800;
letter-spacing: -0.03em;
background: linear-gradient(135deg, #fbbf24 0%, #f97316 40%, #ef4444 70%, #ec4899 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.cool-subtitle {
font-size: clamp(0.875rem, 2vw, 1.125rem);
color: rgba(148, 163, 184, 0.7);
}
.cool-buttons {
display: flex;
gap: 1rem;
flex-wrap: wrap;
justify-content: center;
}
.cool-btn {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.75rem 1.5rem;
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 12px;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
font-family: inherit;
color: white;
}
.cool-btn:hover {
transform: translateY(-1px);
}
.cool-btn--primary {
background: rgba(239, 68, 68, 0.15);
border-color: rgba(239, 68, 68, 0.3);
}
.cool-btn--primary:hover {
background: rgba(239, 68, 68, 0.25);
box-shadow: 0 0 20px rgba(239, 68, 68, 0.2);
}
.cool-btn--secondary {
background: rgba(250, 204, 21, 0.12);
border-color: rgba(250, 204, 21, 0.3);
}
.cool-btn--secondary:hover {
background: rgba(250, 204, 21, 0.22);
box-shadow: 0 0 20px rgba(250, 204, 21, 0.2);
}
.cool-btn--accent {
background: rgba(168, 85, 247, 0.12);
border-color: rgba(168, 85, 247, 0.3);
}
.cool-btn--accent:hover {
background: rgba(168, 85, 247, 0.22);
box-shadow: 0 0 20px rgba(168, 85, 247, 0.2);
}
/* Particle element */
.cool-particle {
position: fixed;
pointer-events: none;
z-index: 9999;
font-size: 20px;
line-height: 1;
user-select: none;
will-change: transform, opacity;
}// Cool Mode — emoji particle burst on every click
(function () {
"use strict";
var EMOJIS = [
"\u2728",
"\u2B50",
"\u2764\uFE0F",
"\u{1F525}",
"\u{1F389}",
"\u{1F31F}",
"\u{1F4AB}",
"\u{1F308}",
"\u{1F680}",
"\u{1F388}",
"\u{1F381}",
"\u{1F382}",
"\u{1F386}",
"\u{1F387}",
"\u2604\uFE0F",
];
var PARTICLE_COUNT = 15;
var GRAVITY = 0.12;
var FRICTION = 0.98;
var FADE_SPEED = 0.015;
var activeParticles = [];
var animRunning = false;
function spawnParticles(x, y) {
for (var i = 0; i < PARTICLE_COUNT; i++) {
var el = document.createElement("span");
el.className = "cool-particle";
el.textContent = EMOJIS[Math.floor(Math.random() * EMOJIS.length)];
el.style.left = x + "px";
el.style.top = y + "px";
el.style.fontSize = 14 + Math.random() * 16 + "px";
document.body.appendChild(el);
var angle = Math.random() * Math.PI * 2;
var speed = 2 + Math.random() * 6;
activeParticles.push({
el: el,
x: x,
y: y,
vx: Math.cos(angle) * speed,
vy: Math.sin(angle) * speed - 2,
opacity: 1,
rotation: Math.random() * 360,
rotationSpeed: (Math.random() - 0.5) * 10,
scale: 0.5 + Math.random() * 0.8,
});
}
if (!animRunning) {
animRunning = true;
requestAnimationFrame(animate);
}
}
function animate() {
for (var i = activeParticles.length - 1; i >= 0; i--) {
var p = activeParticles[i];
p.vy += GRAVITY;
p.vx *= FRICTION;
p.vy *= FRICTION;
p.x += p.vx;
p.y += p.vy;
p.opacity -= FADE_SPEED;
p.rotation += p.rotationSpeed;
if (p.opacity <= 0) {
if (p.el.parentNode) p.el.parentNode.removeChild(p.el);
activeParticles.splice(i, 1);
continue;
}
p.el.style.transform =
"translate(-50%, -50%) rotate(" + p.rotation + "deg) scale(" + p.scale + ")";
p.el.style.left = p.x + "px";
p.el.style.top = p.y + "px";
p.el.style.opacity = p.opacity;
}
if (activeParticles.length > 0) {
requestAnimationFrame(animate);
} else {
animRunning = false;
}
}
document.addEventListener("click", function (e) {
spawnParticles(e.clientX, e.clientY);
});
})();<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Cool Mode</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="cool-page">
<div class="cool-content">
<h1 class="cool-title">Cool Mode</h1>
<p class="cool-subtitle">Click anywhere for emoji explosions!</p>
<div class="cool-buttons">
<button class="cool-btn cool-btn--primary">
<span>❤️</span> Like
</button>
<button class="cool-btn cool-btn--secondary">
<span>⭐</span> Star
</button>
<button class="cool-btn cool-btn--accent">
<span>🎉</span> Party
</button>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>import { useEffect, useRef, useCallback } from "react";
interface CoolModeProps {
emojis?: string[];
particleCount?: number;
gravity?: number;
fadeSpeed?: number;
children: React.ReactNode;
}
interface Particle {
el: HTMLSpanElement;
x: number;
y: number;
vx: number;
vy: number;
opacity: number;
rotation: number;
rotationSpeed: number;
scale: number;
}
const DEFAULT_EMOJIS = [
"\u2728",
"\u2B50",
"\u2764\uFE0F",
"\uD83D\uDD25",
"\uD83C\uDF89",
"\uD83C\uDF1F",
"\uD83D\uDCAB",
"\uD83C\uDF08",
"\uD83D\uDE80",
"\uD83C\uDF88",
"\uD83C\uDF81",
"\uD83C\uDF82",
"\uD83C\uDF86",
"\uD83C\uDF87",
"\u2604\uFE0F",
];
export function CoolMode({
emojis = DEFAULT_EMOJIS,
particleCount = 15,
gravity = 0.12,
fadeSpeed = 0.015,
children,
}: CoolModeProps) {
const containerRef = useRef<HTMLDivElement>(null);
const particlesRef = useRef<Particle[]>([]);
const animRunningRef = useRef(false);
const animFrameRef = useRef<number>(0);
const animate = useCallback(() => {
const particles = particlesRef.current;
for (let i = particles.length - 1; i >= 0; i--) {
const p = particles[i];
p.vy += gravity;
p.vx *= 0.98;
p.vy *= 0.98;
p.x += p.vx;
p.y += p.vy;
p.opacity -= fadeSpeed;
p.rotation += p.rotationSpeed;
if (p.opacity <= 0) {
p.el.parentNode?.removeChild(p.el);
particles.splice(i, 1);
continue;
}
p.el.style.transform = `translate(-50%, -50%) rotate(${p.rotation}deg) scale(${p.scale})`;
p.el.style.left = `${p.x}px`;
p.el.style.top = `${p.y}px`;
p.el.style.opacity = String(p.opacity);
}
if (particles.length > 0) {
animFrameRef.current = requestAnimationFrame(animate);
} else {
animRunningRef.current = false;
}
}, [gravity, fadeSpeed]);
const spawnParticles = useCallback(
(x: number, y: number) => {
for (let i = 0; i < particleCount; i++) {
const el = document.createElement("span");
el.style.position = "fixed";
el.style.pointerEvents = "none";
el.style.zIndex = "9999";
el.style.lineHeight = "1";
el.style.userSelect = "none";
el.style.willChange = "transform, opacity";
el.style.fontSize = `${14 + Math.random() * 16}px`;
el.style.left = `${x}px`;
el.style.top = `${y}px`;
el.textContent = emojis[Math.floor(Math.random() * emojis.length)];
document.body.appendChild(el);
const angle = Math.random() * Math.PI * 2;
const speed = 2 + Math.random() * 6;
particlesRef.current.push({
el,
x,
y,
vx: Math.cos(angle) * speed,
vy: Math.sin(angle) * speed - 2,
opacity: 1,
rotation: Math.random() * 360,
rotationSpeed: (Math.random() - 0.5) * 10,
scale: 0.5 + Math.random() * 0.8,
});
}
if (!animRunningRef.current) {
animRunningRef.current = true;
animFrameRef.current = requestAnimationFrame(animate);
}
},
[emojis, particleCount, animate]
);
useEffect(() => {
const container = containerRef.current;
if (!container) return;
const handleClick = (e: MouseEvent) => {
spawnParticles(e.clientX, e.clientY);
};
container.addEventListener("click", handleClick);
return () => {
container.removeEventListener("click", handleClick);
cancelAnimationFrame(animFrameRef.current);
// Clean up remaining particles
for (const p of particlesRef.current) {
p.el.parentNode?.removeChild(p.el);
}
particlesRef.current = [];
};
}, [spawnParticles]);
return <div ref={containerRef}>{children}</div>;
}
// Demo usage
export default function CoolModeDemo() {
const btnBase: React.CSSProperties = {
display: "inline-flex",
alignItems: "center",
gap: "0.5rem",
padding: "0.75rem 1.5rem",
border: "1px solid rgba(255,255,255,0.12)",
borderRadius: 12,
fontSize: "1rem",
fontWeight: 600,
cursor: "pointer",
fontFamily: "inherit",
color: "white",
transition: "all 0.2s",
};
return (
<CoolMode>
<div
style={{
width: "100vw",
height: "100vh",
background: "#0a0a0a",
display: "grid",
placeItems: "center",
fontFamily: "system-ui, -apple-system, sans-serif",
color: "#f1f5f9",
}}
>
<div
style={{
textAlign: "center",
display: "flex",
flexDirection: "column",
alignItems: "center",
gap: "1.5rem",
}}
>
<h1
style={{
fontSize: "clamp(2rem, 5vw, 3.5rem)",
fontWeight: 800,
letterSpacing: "-0.03em",
background:
"linear-gradient(135deg, #fbbf24 0%, #f97316 40%, #ef4444 70%, #ec4899 100%)",
WebkitBackgroundClip: "text",
WebkitTextFillColor: "transparent",
backgroundClip: "text",
}}
>
Cool Mode
</h1>
<p style={{ fontSize: "1rem", color: "rgba(148,163,184,0.7)" }}>
Click anywhere for emoji explosions!
</p>
<div style={{ display: "flex", gap: "1rem", flexWrap: "wrap", justifyContent: "center" }}>
<button
style={{
...btnBase,
background: "rgba(239,68,68,0.15)",
borderColor: "rgba(239,68,68,0.3)",
}}
>
<span>{"\u2764\uFE0F"}</span> Like
</button>
<button
style={{
...btnBase,
background: "rgba(250,204,21,0.12)",
borderColor: "rgba(250,204,21,0.3)",
}}
>
<span>{"\u2B50"}</span> Star
</button>
<button
style={{
...btnBase,
background: "rgba(168,85,247,0.12)",
borderColor: "rgba(168,85,247,0.3)",
}}
>
<span>{"\uD83C\uDF89"}</span> Party
</button>
</div>
</div>
</div>
</CoolMode>
);
}<script setup>
import { ref, onMounted, onUnmounted } from "vue";
const DEFAULT_EMOJIS = [
"\u2728",
"\u2B50",
"\u2764\uFE0F",
"\uD83D\uDD25",
"\uD83C\uDF89",
"\uD83C\uDF1F",
"\uD83D\uDCAB",
"\uD83C\uDF08",
"\uD83D\uDE80",
"\uD83C\uDF88",
"\uD83C\uDF81",
"\uD83C\uDF82",
"\uD83C\uDF86",
"\uD83C\uDF87",
"\u2604\uFE0F",
];
const particleCount = 15;
const gravity = 0.12;
const fadeSpeed = 0.015;
const containerEl = ref(null);
let particles = [];
let animRunning = false;
let animFrame = 0;
function animate() {
for (let i = particles.length - 1; i >= 0; i--) {
const p = particles[i];
p.vy += gravity;
p.vx *= 0.98;
p.vy *= 0.98;
p.x += p.vx;
p.y += p.vy;
p.opacity -= fadeSpeed;
p.rotation += p.rotationSpeed;
if (p.opacity <= 0) {
p.el.parentNode?.removeChild(p.el);
particles.splice(i, 1);
continue;
}
p.el.style.transform = `translate(-50%, -50%) rotate(${p.rotation}deg) scale(${p.scale})`;
p.el.style.left = `${p.x}px`;
p.el.style.top = `${p.y}px`;
p.el.style.opacity = String(p.opacity);
}
if (particles.length > 0) {
animFrame = requestAnimationFrame(animate);
} else {
animRunning = false;
}
}
function spawnParticles(x, y) {
for (let i = 0; i < particleCount; i++) {
const el = document.createElement("span");
el.style.position = "fixed";
el.style.pointerEvents = "none";
el.style.zIndex = "9999";
el.style.lineHeight = "1";
el.style.userSelect = "none";
el.style.willChange = "transform, opacity";
el.style.fontSize = `${14 + Math.random() * 16}px`;
el.style.left = `${x}px`;
el.style.top = `${y}px`;
el.textContent = DEFAULT_EMOJIS[Math.floor(Math.random() * DEFAULT_EMOJIS.length)];
document.body.appendChild(el);
const angle = Math.random() * Math.PI * 2;
const speed = 2 + Math.random() * 6;
particles.push({
el,
x,
y,
vx: Math.cos(angle) * speed,
vy: Math.sin(angle) * speed - 2,
opacity: 1,
rotation: Math.random() * 360,
rotationSpeed: (Math.random() - 0.5) * 10,
scale: 0.5 + Math.random() * 0.8,
});
}
if (!animRunning) {
animRunning = true;
animFrame = requestAnimationFrame(animate);
}
}
function handleClick(e) {
spawnParticles(e.clientX, e.clientY);
}
onMounted(() => {
containerEl.value?.addEventListener("click", handleClick);
});
onUnmounted(() => {
containerEl.value?.removeEventListener("click", handleClick);
cancelAnimationFrame(animFrame);
for (const p of particles) {
p.el.parentNode?.removeChild(p.el);
}
particles = [];
});
</script>
<template>
<div ref="containerEl">
<div style="width: 100vw; height: 100vh; background: #0a0a0a; display: grid; place-items: center; font-family: system-ui, -apple-system, sans-serif; color: #f1f5f9;">
<div style="text-align: center; display: flex; flex-direction: column; align-items: center; gap: 1.5rem;">
<h1 style="font-size: clamp(2rem, 5vw, 3.5rem); font-weight: 800; letter-spacing: -0.03em; background: linear-gradient(135deg, #fbbf24 0%, #f97316 40%, #ef4444 70%, #ec4899 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;">
Cool Mode
</h1>
<p style="font-size: 1rem; color: rgba(148,163,184,0.7);">Click anywhere for emoji explosions!</p>
<div style="display: flex; gap: 1rem; flex-wrap: wrap; justify-content: center;">
<button style="display: inline-flex; align-items: center; gap: 0.5rem; padding: 0.75rem 1.5rem; border: 1px solid rgba(239,68,68,0.3); border-radius: 12px; font-size: 1rem; font-weight: 600; cursor: pointer; font-family: inherit; color: white; transition: all 0.2s; background: rgba(239,68,68,0.15);">
<span>❤️</span> Like
</button>
<button style="display: inline-flex; align-items: center; gap: 0.5rem; padding: 0.75rem 1.5rem; border: 1px solid rgba(250,204,21,0.3); border-radius: 12px; font-size: 1rem; font-weight: 600; cursor: pointer; font-family: inherit; color: white; transition: all 0.2s; background: rgba(250,204,21,0.12);">
<span>⭐</span> Star
</button>
<button style="display: inline-flex; align-items: center; gap: 0.5rem; padding: 0.75rem 1.5rem; border: 1px solid rgba(168,85,247,0.3); border-radius: 12px; font-size: 1rem; font-weight: 600; cursor: pointer; font-family: inherit; color: white; transition: all 0.2s; background: rgba(168,85,247,0.12);">
<span>🎉</span> Party
</button>
</div>
</div>
</div>
</div>
</template><script>
import { onMount, onDestroy } from "svelte";
const DEFAULT_EMOJIS = [
"\u2728",
"\u2B50",
"\u2764\uFE0F",
"\uD83D\uDD25",
"\uD83C\uDF89",
"\uD83C\uDF1F",
"\uD83D\uDCAB",
"\uD83C\uDF08",
"\uD83D\uDE80",
"\uD83C\uDF88",
"\uD83C\uDF81",
"\uD83C\uDF82",
"\uD83C\uDF86",
"\uD83C\uDF87",
"\u2604\uFE0F",
];
const particleCount = 15;
const gravity = 0.12;
const fadeSpeed = 0.015;
let containerEl;
let particles = [];
let animRunning = false;
let animFrame = 0;
function animate() {
for (let i = particles.length - 1; i >= 0; i--) {
const p = particles[i];
p.vy += gravity;
p.vx *= 0.98;
p.vy *= 0.98;
p.x += p.vx;
p.y += p.vy;
p.opacity -= fadeSpeed;
p.rotation += p.rotationSpeed;
if (p.opacity <= 0) {
p.el.parentNode?.removeChild(p.el);
particles.splice(i, 1);
continue;
}
p.el.style.transform = `translate(-50%, -50%) rotate(${p.rotation}deg) scale(${p.scale})`;
p.el.style.left = `${p.x}px`;
p.el.style.top = `${p.y}px`;
p.el.style.opacity = String(p.opacity);
}
if (particles.length > 0) {
animFrame = requestAnimationFrame(animate);
} else {
animRunning = false;
}
}
function spawnParticles(x, y) {
for (let i = 0; i < particleCount; i++) {
const el = document.createElement("span");
el.style.position = "fixed";
el.style.pointerEvents = "none";
el.style.zIndex = "9999";
el.style.lineHeight = "1";
el.style.userSelect = "none";
el.style.willChange = "transform, opacity";
el.style.fontSize = `${14 + Math.random() * 16}px`;
el.style.left = `${x}px`;
el.style.top = `${y}px`;
el.textContent = DEFAULT_EMOJIS[Math.floor(Math.random() * DEFAULT_EMOJIS.length)];
document.body.appendChild(el);
const angle = Math.random() * Math.PI * 2;
const speed = 2 + Math.random() * 6;
particles.push({
el,
x,
y,
vx: Math.cos(angle) * speed,
vy: Math.sin(angle) * speed - 2,
opacity: 1,
rotation: Math.random() * 360,
rotationSpeed: (Math.random() - 0.5) * 10,
scale: 0.5 + Math.random() * 0.8,
});
}
if (!animRunning) {
animRunning = true;
animFrame = requestAnimationFrame(animate);
}
}
function handleClick(e) {
spawnParticles(e.clientX, e.clientY);
}
onMount(() => {
if (containerEl) {
containerEl.addEventListener("click", handleClick);
}
});
onDestroy(() => {
if (containerEl) containerEl.removeEventListener("click", handleClick);
cancelAnimationFrame(animFrame);
for (const p of particles) {
p.el.parentNode?.removeChild(p.el);
}
particles = [];
});
const btnBase =
"display: inline-flex; align-items: center; gap: 0.5rem; padding: 0.75rem 1.5rem; border-radius: 12px; font-size: 1rem; font-weight: 600; cursor: pointer; font-family: inherit; color: white; transition: all 0.2s;";
</script>
<div bind:this={containerEl}>
<div style="width: 100vw; height: 100vh; background: #0a0a0a; display: grid; place-items: center; font-family: system-ui, -apple-system, sans-serif; color: #f1f5f9;">
<div style="text-align: center; display: flex; flex-direction: column; align-items: center; gap: 1.5rem;">
<h1 style="font-size: clamp(2rem, 5vw, 3.5rem); font-weight: 800; letter-spacing: -0.03em; background: linear-gradient(135deg, #fbbf24 0%, #f97316 40%, #ef4444 70%, #ec4899 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;">
Cool Mode
</h1>
<p style="font-size: 1rem; color: rgba(148,163,184,0.7);">Click anywhere for emoji explosions!</p>
<div style="display: flex; gap: 1rem; flex-wrap: wrap; justify-content: center;">
<button style="{btnBase} background: rgba(239,68,68,0.15); border: 1px solid rgba(239,68,68,0.3);">
<span>{'\u2764\uFE0F'}</span> Like
</button>
<button style="{btnBase} background: rgba(250,204,21,0.12); border: 1px solid rgba(250,204,21,0.3);">
<span>{'\u2B50'}</span> Star
</button>
<button style="{btnBase} background: rgba(168,85,247,0.12); border: 1px solid rgba(168,85,247,0.3);">
<span>{'\uD83C\uDF89'}</span> Party
</button>
</div>
</div>
</div>
</div>Cool Mode
A delightful particle burst effect that spawns emojis and shapes from every click point. Particles fly outward with realistic physics (gravity, velocity, rotation) and fade away gracefully.
How it works
- A global click handler captures click position
- Multiple particle elements are spawned at the click point with random velocities
- Each particle has gravity, rotation, and opacity decay applied via
requestAnimationFrame - Particles are removed from the DOM once fully faded
Customization
emojis— array of emoji/text to randomly pick fromparticleCount— number of particles per clickspread— initial velocity rangegravity— downward accelerationfadeSpeed— how quickly particles disappear
When to use it
- Like/favorite button celebrations
- Game feedback effects
- Fun interactive landing pages
- Celebratory confetti alternatives