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

@waukeshamakerspace/react-components

v2.0.0

Published

Shared Waukesha Makerspace React components (theme toggle, avatar, branded spinner), styled with design-tokens semantic CSS variables so they work in any WMI UI stack

Readme

@waukeshamakerspace/react-components

Shared Waukesha Makerspace React components: the brand-specific widgets every WMI UI needs but no framework provides. Published on the public npm registry.

All styling comes from the semantic CSS variables in @waukeshamakerspace/design-tokens (var(--primary), var(--surface), ...), so the components render correctly in light and dark mode and drop into any WMI stack: Next.js + Tailwind, MUI, or plain CSS. They carry no styling framework of their own.

Scope

This package is deliberately small. It holds brand-specific, cross-app widgets only. Generic primitives (buttons, inputs, cards) stay out: Tailwind and MUI apps already have strong opinions there, and duplicating them here would fight every consumer's styling system.

Install

npm install @waukeshamakerspace/react-components @waukeshamakerspace/design-tokens

Peer dependencies: React 18 or 19, @waukeshamakerspace/design-tokens >= 1.3.

Load the token variables and the component styles once, at app root:

import '@waukeshamakerspace/design-tokens/css/tokens.css'; // or the Tailwind layer
import '@waukeshamakerspace/react-components/styles.css';

Apps already consuming the tokens package (per waukesha-makers-architecture/shared/ui-guidelines.md) only add the second line.

Theme state

Theme state has one source of truth, owned by the tokens package's theme-init: the override attribute on <html> plus the persisted choice in localStorage (wm-theme). Explicit light/dark choices persist across visits; "system" (follow the device) is the default and choosing it clears the stored choice. This package never keeps its own copy, so every theme control on a page, and in other open tabs, stays in sync.

useThemeMode

import { useThemeMode } from '@waukeshamakerspace/react-components';

const { mode, resolvedTheme, setMode } = useThemeMode();
// mode:          'light' | 'dark' | 'system'  (the user's choice)
// resolvedTheme: 'light' | 'dark'             (what's applied right now)
// setMode:       change + persist the choice

Built on useSyncExternalStore; SSR renders as system/light and corrects itself after hydration. Use it wherever app code needs theme state (chart palettes, embedded maps, ...) instead of reading the DOM or duplicating state.

Components

ThemeToggle

The compact theme control that ui-guidelines requires in every WMI UI, as one import. An icon button that cycles system → light → dark through the shared theme state.

import { ThemeToggle } from '@waukeshamakerspace/react-components';

<ThemeToggle />

| Prop | Type | Default | Notes | |------|------|---------|-------| | onModeChange | (mode) => void | | Called after each switch | | className | string | | Merged onto the button |

The component assumes the app follows ui-guidelines: the theme-init script is inlined (or initTheme() runs at startup) so the stored choice applies pre-paint and OS-change syncing coordinates.

ThemeModeSwitch

The settings-page sibling of ThemeToggle: a segmented control showing light / auto / dark at once. A WAI-ARIA radio group (arrow keys move and select, roving tabindex), sharing the same theme state as everything else.

import { ThemeModeSwitch } from '@waukeshamakerspace/react-components';

<ThemeModeSwitch />

| Prop | Type | Default | Notes | |------|------|---------|-------| | onModeChange | (mode) => void | | Called after each selection | | label | string | 'Theme' | Accessible name for the group | | className | string | | Merged onto the group |

Avatar

User avatar with an initials fallback, clipped to the brand gear silhouette by default (a scalable SVG clip, so any size works). The fallback tone (primary, secondary, or accent token pair) is hashed from the name, so the same person gets the same color in every app.

import { Avatar } from '@waukeshamakerspace/react-components';

<Avatar name="Casey Kerr" src={member.photoUrl} />
<Avatar name="Casey Kerr" shape="circle" />

| Prop | Type | Default | Notes | |------|------|---------|-------| | name | string | required | Accessible label + initials source | | src | string | | Falls back to initials on load error | | size | 'sm' \| 'md' \| 'lg' \| number | 'md' | 28 / 40 / 64 px, or exact px | | shape | 'gear' \| 'circle' | 'gear' | | | className | string | | |

BrandSpinner

Branded loading indicator built from meshed gears in the token colors. Announces itself as role="status" with a visually hidden label, and swaps rotation for a gentle opacity pulse under prefers-reduced-motion.

import { BrandSpinner } from '@waukeshamakerspace/react-components';

<BrandSpinner size="lg" label="Fetching inventory" />
<BrandSpinner variant="train" />

| Prop | Type | Default | Notes | |------|------|---------|-------| | size | 'sm' \| 'md' \| 'lg' \| number | 'md' | 24 / 48 / 96 px, or exact px | | variant | 'gears' \| 'train' \| 'solo' | 'gears' | Two meshed gears / three-gear chain / single gear | | label | string | 'Loading…' | | | className | string | | |

RandomSpinner

BrandSpinner that picks a random variant each time it mounts, for variety on repeat loads. Takes every BrandSpinner prop except variant, plus an optional variants array to restrict the pool. The pick happens after mount, so SSR markup stays deterministic (no hydration mismatch).

import { RandomSpinner } from '@waukeshamakerspace/react-components';

<RandomSpinner size="lg" />
<RandomSpinner variants={['gears', 'train']} />

Development

npm install
npm run dev    # Ladle playground on http://localhost:3801 (reserved port)
npm test       # vitest + testing-library under jsdom
npm run build  # tsc to dist/

Use the ThemeToggle story to preview every component in both themes before shipping a change.

Releases

Same automation as design-tokens: conventional commits accumulate into a release-please PR; merging it publishes to npm via trusted publishing (OIDC, no tokens). Consumer repos must run Renovate or Dependabot so releases arrive as bump PRs.