Skip to content

GoBoldlyForward/joycelights

Repository files navigation

joycelights

A Christmas-lights alphabet wall as a drop-in CSS + JS plugin. Type a message, the wall spells it out one bulb at a time — inspired by Joyce Byers' wall in Stranger Things S1. Ships with built-in Christmas and Fourth of July themes as counter-examples so the API doesn't end up shrink-wrapped to one aesthetic.

Demo

goboldlyforward.github.io/joycelights — toggle the Stranger Things / Christmas / Fourth of July tabs to see the same plugin themed three different ways.

What it does

Renders a hand-painted alphabet wall (wallpaper backdrop, paint-drip letters, multicolor Christmas bulbs on a sagging wire) into any container, then animates messages onto it. Each letter's bulb flashes in sequence then goes dark before the next one fires.

Install

For now, download joycelights.css and joycelights.js from this repo. (npm publication pending.)

<link rel="stylesheet" href="path/to/joycelights.css">
<script src="path/to/joycelights.js"></script>

Usage

<div id="wall"></div>

<script>
  const wall = new JoyceLights('#wall');
  wall.spell('RIGHT HERE');
</script>

new JoyceLights(target, options?) mounts the wall into target (selector or element). spell(message) returns a Promise that resolves when the message has finished playing.

Themes

// Built-in: Stranger Things (default)
new JoyceLights('#wall');

// Built-in: Christmas
wall.setOptions({
  theme: 'christmas',
  palette: ['red', 'green'],
  drips: false,
  letterTilt: 0, letterShift: 0, letterScale: false,
});

// Built-in: Fourth of July
wall.setOptions({
  theme: 'july4',
  palette: ['red', 'white', 'blue'],
  drips: false,
  randomColors: true,
  letterTilt: 0, letterShift: 0, letterScale: false,
});

Roll your own theme by adding a modifier class (.joycelights--mygame) and overriding the CSS custom properties — see Theming.

Bulb palette

red · green · blue · yellow · orange · white

Pass any subset (or all) via palette to control which colors letters cycle through. Combine with colorMap to pin specific letters to specific colors, or randomColors: true to re-roll on each spell.

Full-bleed wallpaper

To make the wallpaper extend behind an entire region (header, hero), put the theme modifier on a wrapper and pass flat: true to the wall so it drops its own chrome:

<header class="stage joycelights--july4">
  <h1>Independence Day</h1>
  <div id="wall"></div>
</header>

<style>
  .stage {
    background-color: var(--joycelights-wallpaper-base);
    background-image:  var(--joycelights-wallpaper-image);
    background-repeat: repeat;
    background-size: 160px 160px;
  }
</style>

<script>
  new JoyceLights('#wall', { flat: true });
</script>

CSS custom properties cascade from the wrapper into the wall, so one class swap reskins everything.

Options

new JoyceLights('#wall', {
  rows: ['ABCDEFGH', 'IJKLMNOPQ', 'RSTUVWXYZ'],
  palette: ['red', 'green', 'blue', 'yellow', 'orange'],
  colorMap: { H: 'red', E: 'red', L: 'red', O: 'red' },
  randomColors: false,
  flicker: true,
  speed: 600,            // ms per letter cycle
  onTimeRatio: 0.7,
  drips: true,
  wallpaper: true,
  flat: false,           // drop ALL wall chrome (parent provides bg)
  theme: null,           // 'christmas' | 'july4' | null
  letterTilt: 14,        // ± degrees of random rotation per letter
  letterShift: 6,        // ± pixels of random vertical shift
  letterScale: true,     // random 0.9–1.12 scale per letter
  wireSag: 10,           // 0–14 viewBox units; depth of wire dip between bulbs
  onLetter: (letter, color, index) => { /* sfx, etc. */ },
});

Methods

wall.spell('HELLO');
wall.spell('RUN', { speed: 900 });
wall.light('A', 'red');
wall.unlight('A');
wall.clear();
wall.cancel();
wall.setOptions({ theme: 'july4' });
wall.destroy();

Modifier classes

Class What it does
.joycelights--christmas Built-in festive theme (cream + holly + red letters)
.joycelights--july4 Built-in Americana theme (cream + stars + navy letters)
.joycelights--no-wallpaper Drops wallpaper bg + shadow (keeps padding + radius)
.joycelights--flat Drops all chrome — use when a parent provides the bg
.joycelights--no-drips Hides letter paint drips

Theming

.joycelights {
  --joycelights-paint: #1a1612;
  --joycelights-wallpaper-base: #dec59b;
  --joycelights-wallpaper-image: url("…SVG data URI…");
  --joycelights-wire: #1a2a14;
  --joycelights-letter-font: 'Permanent Marker', cursive;
  --joycelights-letter-shadow: 0 1px 0 rgba(0,0,0,0.5), 1px 0 0 rgba(0,0,0,0.3);
  --joycelights-vignette: radial-gradient(/* … */);
  --joycelights-shadow: inset 0 0 60px rgba(60,30,10,0.35), 0 6px 30px rgba(0,0,0,0.6);
  --joycelights-radius: 4px;
}

/* Your own theme */
.joycelights--retro {
  --joycelights-paint: #ff00ff;
  --joycelights-wallpaper-base: #150030;
  --joycelights-letter-font: 'Press Start 2P', monospace;
}

Activate with wall.setOptions({ theme: 'retro' }).

How the curved wire works

Each row's wire is an inline SVG with a single <path> of stitched-together quadratic Bezier curves. The path anchors at every bulb's x-position and dips down to wireSag viewBox units between each pair. preserveAspectRatio="none" lets the SVG stretch responsively across whatever pixel width the row ends up at, and vector-effect="non-scaling-stroke" keeps the stroke a consistent pixel thickness. The wire SVG sits at z-index 1, below the bulbs' z-index 3 screw caps — so the wire visually threads through each cap.

Requirements

HTML, CSS, and a smidge of JavaScript. No framework, no build step.

Roadmap

  • Working prototype
  • LICENSE (MIT)
  • .gitignore
  • README
  • package.json
  • CSS + JS split, public API
  • Themeable (CSS vars + theme option)
  • Built-in Christmas theme
  • Built-in Fourth of July theme
  • White bulb in core palette
  • Curved/sagging wire (SVG path per row)
  • Full-bleed-friendly via flat option
  • Publish to npm (as @goboldlyforward/joycelights)
  • Optional joycelights-rails gem wrapper
  • GitHub Actions CI (stylelint + eslint)
  • Deploy demo to gh-pages
  • Multi-strand chaotic wire (multiple overlapping paths)
  • Click-to-light interaction on individual letters
  • Ambient twinkle() mode (multiple bulbs gently fading independently)
  • Optional bulb "ping" SFX hook

License

MIT — see LICENSE.

About

A Christmas-lights alphabet wall as a drop-in CSS + JS plugin. Type a message, the wall spells it out one bulb at a time — inspired by Joyce Byers' wall in Stranger Things S1.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors