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

styled-atom

v3.0.3

Published

Runtime for loading and mounting CSS atoms in React

Readme

logo

Table of contents

About

styled-atom is a tiny TypeScript runtime for mounting CSS atoms only when a React preview, component or tool surface needs them.

It is designed for React demo shells, component workbenches, visual editors and render-heavy UI sandboxes: places where many small previews mount, unmount and re-render while sharing CSS files or small inline style atoms.

It is not a CSS framework. It does not create cascade layers or replace your bundler. It owns the runtime part: loading CSS by name, compiling small React-like style objects, injecting stable style tags, tracking loading state and releasing styles when nobody uses them anymore.

The idea is simple - imported CSS goes through a React-bound runtime store, while inline CSS can use StyledAtom directly.

Installation

npm install styled-atom
import StyledAtom, { createStyledAtomStore } from "styled-atom";

✦ Note:

  • Supports both ESM (import) and CommonJS (require) builds.
  • Written in TypeScript and ships declaration files.
  • React is a peer dependency.
  • The package does not ship runtime CSS. Your project keeps ownership of CSS files and the loader function.

API

There are two StyledAtom entry points:

  • import StyledAtom from "styled-atom" - a standalone inline style atom. It does not need a store or loader and accepts name + styles.
  • styleAtomsStore.StyledAtom - a store-bound style atom returned by createStyledAtomStore. It accepts files and loads CSS through the store loader.

Description: Mounts one inline CSS atom without creating a store. The component compiles a React-like style object into an owned <style> tag and releases it on unmount. It does not render a wrapper by default. Add encap when the atom should wrap children and compile styles through that wrapper selector.

Props:

  • name: string - inline atom name used for the style tag, default root selector and dev sourceURL.
  • styles: StyledAtomStyles - React-like CSS object.
  • encap?: boolean | string | StyleEncap - optional wrapper scope. Omitted means no wrapper. encap={true} uses the name class. String, className, id and attribute use the selector you provide and the inline CSS is compiled under that selector.
  • fallback?: React.ReactNode - content rendered before the style atom is mounted.
  • onLoad?: () => void - called once when this atom changes from loading to loaded.
  • children?: React.ReactNode - content shown after the atom is mounted.

Example:

import StyledAtom from "styled-atom";

export function LoadingScreen() {
  return (
    <StyledAtom
      name="loading-screen"
      encap
      styles={{
        backgroundColor: "#fff",
        minHeight: "100vh",

        ".title": {
          color: "#111",
          fontWeight: 600,
        },

        "@media (max-width: 640px)": {
          padding: 16,
        },
      }}
    >
      <section>
        <h1 className="title">Loading</h1>
      </section>
    </StyledAtom>
  );
}

Style object:

In the styles prop nested selectors are resolved from the root selector. Without encap the root selector is .${name}, so add that class yourself when root declarations should apply to your markup. With encap, the root selector is the generated wrapper selector. Selector lists are scoped per item, so a nested selector list such as .card, .panel inside .dark compiles both selectors under .dark. At-rules such as @media and @keyframes are supported. Numeric values receive px unless the CSS property is unitless. For pseudo-element content, pass the literal text directly (content: "", content: "×"); existing CSS values such as content: '""', attr(...), counter(...) and none are preserved.

Description: The store-bound component registers requested files in the shared runtime, renders fallback while the loader resolves them and reuses already mounted style tags with other atoms from the same store.

Example:

import StyledAtomImport from "your-styled-atom-store";

<StyledAtomImport
  files={["reset", "preview-card"]}
  fallback={<span>Loading...</span>}
>
  <PreviewCard />
</StyledAtomImport>;

Props:

  • files?: string | readonly string[] - CSS atom names passed to the configured loader.
  • encap?: boolean | string | StyleEncap - optional wrapper props only. Omitted means no wrapper. encap={true} adds classes from files; string, className, id and attribute use the selector you provide. Imported CSS is not rewritten, so files should target that wrapper themselves.
  • fallback?: React.ReactNode - content rendered while requested files are loading.
  • onLoad?: () => void - called once when this atom changes from loading to loaded.
  • children?: React.ReactNode - content shown after the requested files are loaded.

Description: Creates one React-bound style runtime and a StyledAtom component bound to that runtime. Use one runtime for a shell, workspace or isolated UI surface. Every mounted atom shares the same CSS cache and loader.

Return: Returns the bound component and a small runtime control surface:

const { StyledAtom, configure, reload, replace, dispose } =
  createStyledAtomStore();
  • StyledAtom - React component that loads requested CSS files before rendering children.
  • configure(path) - set or replace the CSS loader.
  • reload(files?) - reload all or selected mounted CSS atoms through the configured loader.
  • replace(styles) - replace mounted CSS text directly without calling the loader.
  • dispose() - remove all style tags owned by this runtime.

Example:

import { createStyledAtomStore } from "styled-atom";

export const styleAtomsStore = createStyledAtomStore(
  (name) => import(`./styles/${name}.css`),
);

export const StyledAtomImport = styleAtomsStore.StyledAtom;

Patterns

import StyledAtom, { type StyledAtomStyles } from "styled-atom";

const splashStyles: StyledAtomStyles = {
  display: "grid",
  placeItems: "center",
  minHeight: "100vh",
  backgroundColor: "#fff",

  ".logo": {
    width: 96,
  },
};

export function SplashScreen() {
  return (
    <StyledAtom name="splash-screen" encap styles={splashStyles}>
      <img className="logo" src="/logo.svg" alt="" />
    </StyledAtom>
  );
}
export function HostStyledShell({ children }) {
  return (
    <>
      <StyledAtomImport files={["reset", "theme"]} />
      {children}
    </>
  );
}

The style tags are released automatically when the StyledAtom unmounts and no other mounted atom uses the same files.

// Any dev server, watcher or bundler integration
styleAtomsStore.replace([
  {
    file: changedFileName,
    css: nextCssText,
  },
]);

changedFileName and nextCssText usually come from a dev server, bundler plugin, file watcher or custom preview infrastructure.

Only the provided CSS atoms are replaced. Mounted React previews stay in place, and unrelated style entries are left untouched.

If CSS text is not available, ask the configured loader to fetch fresh CSS instead:

// Reload selected mounted atoms through the configured loader.
styleAtomsStore.reload(["main", "card"]);

// Reload every currently mounted atom.
styleAtomsStore.reload();

License