npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

atmos-fx

v0.4.0

Published

DOM-aware atmosphere effects for creative interfaces.

Downloads

78

Readme

atmos-fx

demo-high

To view the demo and use the playground, visit https://atmosfx.carsonye.com/

InstallQuick startAPI ReferenceDesign Guidelines

Install

npm i atmos-fx

Quick start

React

React is a required peer dependency for the wrapper components.

import { AtmosFx, AtmosCard } from 'atmos-fx'

export function FunctionalDemo() {
  return (
    <AtmosFx preset="rain" density={0.7} className="functional-demo">
      <AtmosCard transMode="glass">
        <div>Rain can land on this surface and splash from the top edge.</div>
      </AtmosCard>
      
      {/* Use asChild to avoid rendering an extra wrapper element */}
      <AtmosCard asChild transMode="solid">
        <button>Opaque action</button>
      </AtmosCard>

      <AtmosCard transMode="opacity" opacity={0.64}>
        <span>Custom opacity</span>
      </AtmosCard>
    </AtmosFx>
  )
}

CDN

With a bundler such as Vite or webpack, install the package and import the core API normally:

import { createAtmosphere } from 'atmos-fx'

For plain HTML without a build step, use an ESM CDN:

<script type="module">
  import { createAtmosphere } from 'https://esm.sh/atmos-fx'

  const controller = createAtmosphere(document.querySelector('#container'), {
    preset: 'rain',
    density: 0.7,
  })

  controller.start()
</script>

Vanilla JS

<div id="container">
  <div data-atmos-collision data-atmos-glass data-atmos-liquid-dripping="true">
    <h1>Interactive Opaque Shelf</h1>
    <p>Precipitation splashes here.</p>
  </div>
</div>
import { createAtmosphere } from 'atmos-fx'

const controller = createAtmosphere(document.querySelector('#container'), {
  preset: 'rain',
  density: 0.7,
  wind: -0.15,
  alpha: 0.16,
})

controller.start()

// When removing the atmosphere root outside React, make sure to destroy it:
// controller.destroy()

Vue Example

<template>
  <div ref="containerRef" id="container">
    <!-- Use data attributes to define collision and glass surfaces -->
    <div data-atmos-collision data-atmos-glass>
      <h1>Interactive Opaque Shelf</h1>
      <p>Precipitation splashes here.</p>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { createAtmosphere } from 'atmos-fx'

const containerRef = ref(null)
let controller = null

onMounted(() => {
  if (containerRef.value) {
    controller = createAtmosphere(containerRef.value, {
      preset: 'rain',
      density: 0.7,
      wind: -0.15,
      alpha: 0.16,
    })
    controller.start()
  }
})

onUnmounted(() => {
  if (controller) {
    controller.destroy()
  }
})
</script>

API Reference

AtmosFx Props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | preset | 'rain' \| 'snow' \| 'hail' | 'rain' | Applies preset default physical and visual values. | | density | number | 0.65 | Controls particles per unit area (0 disables particles; 1 uses the full quality-tier rate). | | speed | number | 1.0 | Scalar multiplier for gravity and vertical fall speed. | | wind | number | -0.12 | Affects horizontal sway and particle drift. | | color | string | 'rgba(220, 235, 255, 0.72)' | Browser-supported CSS color for precipitation and rain liquid; its alpha channel is preserved. | | quality | 'auto' \| 'low' \| 'medium' \| 'high' | 'auto' | Manual tiers set particle rate; auto starts at medium and adapts to measured frame performance. | | alpha | number | 0.12 | Glass surface background opacity (alpha), clamped from 0 to 1. | | opacity | number | 0.1 | Fallback background opacity for elements marked with data-atmos-opacity, clamped from 0 to 1. | | bottomCollision | boolean | true | Determines whether particles collide with the bottom edge of the container. | | liquidDripping | boolean | true | Globally toggles the water condensation and dripping animation (only in Rain mode). | | pauseWhenHidden | boolean | true | Automatically pause animation when document is hidden or the root element is out of the viewport. | | respectReducedMotion| boolean | true | Honors OS prefers-reduced-motion settings. | | injectStyles | boolean | true | Injects the default rules; disable it when loading atmos-fx/styles.css yourself. | | styleNonce | string | '' | CSP nonce applied to the automatically injected style tag. |

AtmosCard Props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | transMode | 'glass' \| 'opacity' \| 'solid' | 'glass' | Specifies card integration style. | | liquidDripping | boolean | true | Toggles the water condensation and dripping animation. | | liquidGatheringPoint | number | Random | Overrides the stable-random gathering point for this card from 0.33 to 0.66. | | asChild | boolean | false | Merges properties onto the underlying child element to avoid rendering an extra wrapper element. | | opacity | number | 0.1 | Background opacity used by transMode="opacity"; ignored by glass and solid modes. | | alpha | number | 0.12 | Background opacity (alpha) used by transMode="glass"; ignored by opacity and solid modes. |

Vanilla JS createAtmosphere Options

createAtmosphere(element, options) returns a controller with start(), stop(), pause(), resume(), resize(), update(options), and destroy().

The options object accepts exactly the same parameters as the AtmosFx Props.

Define HTML with data attributes for inner cards:

  • data-atmos-solid keeps an element fully solid and removes library-applied transparency and blurs.
  • data-atmos-opacity="0.1" applies a per-element background opacity value.
  • data-atmos-alpha="0.12" applies a per-element glass background opacity (alpha) value.
  • data-atmos-glass opts nested elements into the glass surface style.
  • data-atmos-collision makes the element a top- and side-edge collision surface for foreground precipitation.
  • data-atmos-liquid-dripping="true" toggles the water condensation and dripping animation (only in Rain mode).
  • data-atmos-liquid-gathering-point="0.5" is an optional override example. Omit it to keep the stable-random per-card default; provided values are clamped from 0.33 to 0.66.

Design & UI Guidelines

To ensure visually realistic atmosphere effects, here are some guidelines to follow when designing with AtmosCard:

  • Particle Layering & Dripping: Particles are rendered in foreground and background layers. Foreground particles are blocked by collidable AtmosCard elements. If liquidDripping is enabled on a card, the accumulated rainwater will drip down and correctly collide with any collidable AtmosCards positioned below it.
  • Width-aware Gathering: Wider cards spend longer in Gathering (1250ms + 2.8ms per CSS pixel, capped at 5500ms; 300px takes 2090ms). Later drip phases keep fixed durations.
  • Container-level Glass: For the best glass mode results, put glass mode on block-level HTML containers such as div, section, article, or form. Wrap inputs, images, SVGs, and inline text instead of marking them directly.
  • Avoid Wide Blocking Cards: A very wide collidable AtmosCard will act like an umbrella, blocking most of the foreground rain. This prevents rain from reaching the elements below it, significantly reducing their rain splash animations. Unless this "umbrella" effect is specifically intended, avoid overly wide collision surfaces.
  • Avoid Nesting Cards: Unless you have a highly specific visual effect in mind, avoid nesting an AtmosCard directly inside another AtmosCard. This can cause conflicting collision bounds and visual behaviors that defy natural physics.
  • Card Modes (transMode):
    • glass: The default frosted glass effect, triggering high-fidelity backdrop blurs.
    • opacity: A translucent mode where the card relies on standard CSS opacity to blend with the weather background.
    • solid: Leaves the element with its default opaque style, allowing you to fully customize its appearance without library-applied transparency.

Performance Notes

  • Prefer quality: 'auto' for adaptive performance scaling. Container area changes particle count, but does not select the quality tier.
  • Rendering defaults to WebGL, automatically falling back to a silent dummy Canvas 2D context if WebGL initialization fails.
  • Transparent surfaces can reveal background-layer precipitation while foreground precipitation still collides with selected DOM surfaces.
  • Keep collision surfaces intentional; target rects refresh outside the animation frame loop.
  • Collision and dripping physics use the axis-aligned bounding box (AABB) of targeted elements. Rotated elements (e.g. using transform: rotate()) will have collisions calculated against their outer bounding rectangle rather than the rotated visual boundary.
  • Snow and hail accumulation use bounded pools whose capacity scales with quality and density.
  • Leave respectReducedMotion enabled in production.

Development

npm install
npm run typecheck
npm run build
npm test

The current implementation includes the core lifecycle, WebGL rain, snow, and hail renderers, adaptive quality scaling, a silent dummy Canvas 2D fallback, glass orchestration, rounded top- and side-edge collision responses, rainwater gathering and dripping physics, two-dimensional snow and hail accumulation, and a static docs playground.

Local Smoke Test

After building, open the interactive docs playground:

npm run build
npx vite --host 127.0.0.1 --port 4173

Then visit http://127.0.0.1:4173/docs/ to play with the switcher and compare rain, snow, and hail.

Contributing

See CONTRIBUTING.md for details on building and testing.

License

MIT