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

@atomazing-org/design-system

v2.0.1

Published

A library providing a set of useful utils, MUI style extensions, and components to build your application.

Readme

@atomazing-org/design-system

Modern MUI v7 + Emotion design system with strongly differentiated visual presets, scheme-based light/dark tokens, SSR-safe theming, and persistence.

Preview

Design system preview

Why use it

  • True light/dark themes: each preset ships two curated schemes (light + dark), so backgrounds, cards, and text actually change (not just palette.mode).
  • Works out of the box: includes ready-made presets you can use immediately.
  • Easy to extend: bring your own presets, or combine defaults + custom.
  • Consistent UI: global styles + MUI component overrides for predictable visuals.
  • Safe persistence: remembers selected theme + dark mode with SSR-safe guards.

Installation

Install the library:

npm install @atomazing-org/design-system

Install required peer dependencies (React 18/19 + MUI v7 + Emotion core):

npm install react react-dom @mui/material @emotion/react @emotion/styled

Optional peers:

  • @mui/icons-material (only if your app imports MUI icons)
  • @emotion/css (only if your project uses Emotion css helpers)
npm install @mui/icons-material @emotion/css

Package format (v2)

@atomazing-org/design-system v2 is ESM-only. Use ESM imports (import ... from ...). CommonJS require() is not supported.


Quick start

Use built-in presets (recommended starting point):

import { ThemeProviderWrapper } from "@atomazing-org/design-system";
import { defaultThemes } from "@atomazing-org/design-system/presets";

export function App() {
  return (
    <ThemeProviderWrapper themes={defaultThemes}>
      {/* your app */}
    </ThemeProviderWrapper>
  );
}

Notes:

  • themes can be default presets, your presets, or both.
  • Theme choice + dark mode are persisted (storage key: appSettings).

Built-in presets

Built-in presets are ready-made theme packs shipped with the library.
You can use them as-is, or add your own presets alongside them.

| Preset | Stable id | Best for | |---|---|---| | Warm Earth | warm-earth | Warm and friendly apps | | Editorial Classic | editorial-classic | Content-heavy UIs | | Modern Minimal | modern-minimal | Dashboards and tooling | | Neo Glass | neo-glass | Modern “glass” style UIs | | Retro Terminal | retro-terminal | Terminal-inspired branding |

Import them from:

import { defaultThemes } from "@atomazing-org/design-system/presets";

Switching theme (UI)

Build a simple theme switcher using the library’s theme settings hook.

import { ToggleButton, ToggleButtonGroup } from "@mui/material";
import { useThemeSettings } from "@atomazing-org/design-system";
import { defaultThemes } from "@atomazing-org/design-system/presets";

export function ThemeSwitcher() {
  const { theme, setTheme } = useThemeSettings();

  return (
    <ToggleButtonGroup
      size="small"
      exclusive
      value={theme}
      onChange={(_, next) => next && setTheme(next)}
    >
      {defaultThemes.map((t) => (
        <ToggleButton key={t.id} value={t.id}>
          {t.label}
        </ToggleButton>
      ))}
    </ToggleButtonGroup>
  );
}

Dark mode

Dark mode switches the active scheme inside the current preset.

Supported values

  • light — always use the preset’s light scheme
  • dark — always use the preset’s dark scheme
  • system — follow OS/browser preference (prefers-color-scheme)

Why system exists

It’s the most common UX: the app automatically follows the user’s OS preference without custom code in every project.

Example selector:

import { RadioGroup, FormControlLabel, Radio } from "@mui/material";
import { useThemeSettings } from "@atomazing-org/design-system";

export function DarkModeSelector() {
  const { darkMode, setDarkMode } = useThemeSettings();

  return (
    <RadioGroup row value={darkMode} onChange={(e) => setDarkMode(e.target.value as any)}>
      <FormControlLabel value="system" control={<Radio />} label="System" />
      <FormControlLabel value="light" control={<Radio />} label="Light" />
      <FormControlLabel value="dark" control={<Radio />} label="Dark" />
    </RadioGroup>
  );
}

Forcing mode (optional)

If your app does not support dark mode, you can force the effective palette mode:

import { ThemeProviderWrapper } from "@atomazing-org/design-system";
import { defaultThemes } from "@atomazing-org/design-system/presets";

export function App() {
  return (
    <ThemeProviderWrapper themes={defaultThemes} darkMode="light">
      {/* your app */}
    </ThemeProviderWrapper>
  );
}

Note: when darkMode is set, darkMode is locked and setDarkMode is ignored.


Persistence (appSettings)

Theme selection is persisted in localStorage under the key appSettings.

v2 JSON shape:

{ "themeId": "editorial-classic", "darkMode": "system" }

Notes:

  • v2 stores only themeId and darkMode.
  • v2 does not migrate legacy stored formats (theme, version, auto); invalid/legacy payloads reset to defaults.

App migration routes (repo docs)

If you are migrating an app to v2, use the route runbooks under:

  • migrations/docs/migrations/design-system/README.md
  • migrations/docs/migrations/design-system/routes/*

examples/react-app is the canonical Vite consumer smoke app for local v2 validation (npm run smoke:react-app). examples/next-app-router is the canonical Next.js App Router SSR reference consumer (npm run smoke:next).


Custom themes

Provide your own preset(s) to the provider. A preset is one identifiable theme with two schemes: light and dark.

API reference — ThemePreset

| Field | Type | What it means | |---|---|---| | id | string | Stable identifier used for persistence and deduplication. Must be unique. | | label | string | Name shown in UI selectors. | | colorSchemes.light | ThemeOptions | MUI ThemeOptions for light mode. | | colorSchemes.dark | ThemeOptions | MUI ThemeOptions for dark mode. |

Minimum required tokens per scheme

Each scheme must define:

  • palette.background.default — page background
  • palette.background.paper — Card/Paper background
  • palette.text.primary
  • palette.text.secondary
  • palette.divider

Example:

import type { ThemePreset } from "@atomazing-org/design-system";

export const myPreset: ThemePreset = {
  id: "my-brand",
  label: "My Brand",
  colorSchemes: {
    light: {
      palette: {
        background: { default: "#ffffff", paper: "#ffffff" },
        text: { primary: "#111111", secondary: "#444444" },
        divider: "rgba(0,0,0,0.12)",
      },
    },
    dark: {
      palette: {
        background: { default: "#0f1115", paper: "#151922" },
        text: { primary: "#f1f3f5", secondary: "#c6cbd1" },
        divider: "rgba(241,243,245,0.16)",
      },
    },
  },
};

Using defaults + custom presets

import { defaultThemes } from "@atomazing-org/design-system/presets";

const themes = [...defaultThemes, myPreset];

Then pass themes into ThemeProviderWrapper.


Typography variants

The library adds extra typography variants (beyond MUI defaults) so your text styles are consistent across the app.

import { Typography } from "@mui/material";

export function TypographyDemo() {
  return (
    <>
      <Typography variant="header_lg_bold">Page title</Typography>
      <Typography variant="text_md_regular">Body text</Typography>
      <Typography variant="text_sm_bold">Caption / label</Typography>
    </>
  );
}

Notes:

  • Typography sizing is expected to be rem-based (scales with the user’s browser font size settings).
  • Variants are defined in the design system theme (no local “one-off” styles needed).

Global styles

ThemeProviderWrapper applies global styles (via Emotion) and MUI component defaults, so the app looks consistent immediately.

Set a custom font stack:

import { ThemeProviderWrapper } from "@atomazing-org/design-system";

export function App() {
  return (
    <ThemeProviderWrapper fontFamily="Inter, system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif">
      {/* your app */}
    </ThemeProviderWrapper>
  );
}

Animations

The library exports reusable keyframes so you can keep motion consistent.

import styled from "@emotion/styled";
import { fadeIn } from "@atomazing-org/design-system";

const Panel = styled.div`
  animation: ${fadeIn} 240ms ease-in both;
`;

export function AnimatedPanel() {
  return <Panel>Content</Panel>;
}

SSR notes

  • The library is written to be SSR-safe: no window/document/localStorage access at module scope.
  • If you use system dark mode, the effective mode is derived from prefers-color-scheme on the client.
  • In Next.js, place the provider inside a client boundary (e.g., a component with "use client"), then wrap your app with ThemeProviderWrapper.

Consumer alias guidance (optional)

Aliases are optional. They help you avoid long relative imports inside your app.


Local development (repo)

From the repository root:

pnpm lint
pnpm build
pnpm test
pnpm -C examples/react-app dev
pnpm -C examples/next-app-router dev

Peer dependencies

Make sure your app installs these (MUI v7 + Emotion):

  • react
  • react-dom
  • @mui/material
  • @mui/icons-material (optional, only if you use icons from MUI)
  • @emotion/react
  • @emotion/styled
  • @emotion/css (optional)

Troubleshooting

Dark mode switches, but background/cards do not change

  • Ensure your preset provides both schemes:
    • colorSchemes.light.palette.background.default/paper
    • colorSchemes.dark.palette.background.default/paper
  • Avoid hardcoded colors in overrides. Use theme.palette.* tokens.

Text is hard to read in dark mode

  • Do not reuse light “ink” constants in dark mode.
  • Check:
    • palette.text.primary vs palette.background.default
    • palette.text.secondary vs palette.background.paper

I want to add my own presets

  • Create a ThemePreset with colorSchemes.light and colorSchemes.dark.
  • Combine with defaults: const themes = [...defaultThemes, myPreset];

Examples (examples/react-app, examples/next-app-router)

The repo includes runnable example apps that demonstrate:

  • preset switching
  • dark mode switching
  • background + card surfaces changing correctly
  • token/debug view (if enabled in the example)
  • Next.js App Router SSR integration with a client provider boundary

Run it from the repository root:

pnpm -C examples/react-app dev
pnpm -C examples/next-app-router dev

What to check in the UI:

  • switching to dark changes the page background and Card/Paper background
  • text stays readable on both backgrounds
  • inputs, buttons, menus, and dialogs remain usable
  • Next.js example keeps SSR stable while theme state finalizes on the client

API reference — ThemeProviderWrapper

ThemeProviderWrapper wires MUI ThemeProvider, global styles, and persisted settings.

| Prop | Type | Default | What it does | |---|---|---|---| | themes | ThemePreset[] (or built-in defaultThemes) | defaultThemes | List of presets available to the user. | | fontFamily | string | (theme default) | Optional global font stack for the whole app. | | darkMode | DarkModeOptions | - | Forces mode regardless of persisted settings and system preference. | | children | ReactNode | — | Your application tree. |

Minimal usage:

import { ThemeProviderWrapper } from "@atomazing-org/design-system";
import { defaultThemes } from "@atomazing-org/design-system/presets";

export function App() {
  return (
    <ThemeProviderWrapper themes={defaultThemes}>
      {/* your app */}
    </ThemeProviderWrapper>
  );
}

Public exports (recommended imports)

Use only these stable entry points:

Core API

import { ThemeProviderWrapper, useThemeSettings } from "@atomazing-org/design-system";

Built-in presets

import { defaultThemes } from "@atomazing-org/design-system/presets";

Tip:

  • Avoid deep imports from internal folders. They may change during refactors.

Migration notes (if upgrading)

If you previously passed a single theme object or a legacy “theme list”:

  1. Move your theme into a preset shape with two schemes:
    • colorSchemes.light
    • colorSchemes.dark
  2. Ensure each scheme defines the required tokens:
    • background.default, background.paper
    • text.primary, text.secondary
    • divider
  3. Pass presets into the provider:
    • themes={[...defaultThemes, myPreset]} or only [myPreset]

Goal:

  • dark mode changes real palette tokens, so backgrounds/cards/text update together.

License

MIT