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

signal-layers

v0.1.5

Published

A minimalist, framework-agnostic component library where components respond to signals of intention, not rigid variants or configuration APIs

Readme

Signal Layers

A minimalist, intent-driven UI system where components are laws, not presets. You copy the code. You own it. You change it. The system guides you instead of trapping you.

Signal Layers exists because modern frontend UI has become over-configured, over-abstracted, and under-owned. This library fixes that through a revolutionary signal-based architecture where props are signals of intention, not configuration.

🚀 Quick Start

Prerequisites

Required Dependencies:

react@>=16.8.0 
react-dom@>=16.8.0
tailwindcss@v4

Installation & Setup

Option 1: Copy All Components (Recommended)

npx signal-layers copy

This copies all components to src/components/signals/ in your project.

Option 2: Add Specific Components

npx signal-layers add button
npx signal-layers add card
npx signal-layers add dropdown

Option 3: List Available Components

npx signal-layers list

🧠 Architecture

Signal Layers introduces a revolutionary four-signal architecture:

Signal Types

  1. Input Signals (inputSignal)

    • Raw props passed to components
    • User intention for styling
    • Example: primary, lg, onClick, disabled
  2. Layer Signals (layerSignal)

    • Mapped CSS classes and styling layers
    • Visual presentation logic
    • Example: Maps primary"bg-blue-500 text-white"
  3. Data Signals (dataSignal)

    • Processed and validated data
    • Component state and computed values
    • Example: Validated form values, computed dimensions
  4. State Signals (stateSignal)

    • React hooks for interactivity
    • Hover, focus, ripple states
    • Example: stateSignal.hover.get, stateSignal.ripples.set

Signal Resolution Rules

  • One signal per layer: If multiple signals from the same layer are passed, the last one is applied
  • Deterministic: No magic, no warnings, predictable behavior
  • Composable: Signals can be combined freely
  • Optional: All signals are opt-in

📦 Available Components

| Component | Description | |-----------|-------------| | Button | Interactive button with ripple effects | | Card | Content container with layered styling | | CheckBox | Custom checkbox with animations | | Dropdown | Select dropdown with keyboard navigation | | FabMenu | Floating action button menu | | ProgressBar | Animated progress indicator | | Slider | Range slider with drag interaction | | Spinner | Loading spinner animations | | Switch | Toggle switch with smooth transitions | | TextField | Input field with validation states |

🎯 Usage Examples

Basic Button

import { Button } from './components/signals/Button.jsx';

// Simple usage
<Button onClick={() => console.log('clicked')}>Click me</Button>

// With signals
<Button primary lg hoverEnlarge>Primary Action</Button>

// Multiple signals
<Button ghost red sm hoverLift activeShrink>Ghost Button</Button>

Interactive Components

import { FabMenu } from './components/signals/FabMenu.jsx';

<FabMenu 
  icon="+"
  actions={[
    { icon: "📝", label: "New Document", onClick: () => {} },
    { icon: "📁", label: "Open File", onClick: () => {} },
    { icon: "💾", label: "Save", onClick: () => {} }
  ]}
/>

Form Components

import { TextField, CheckBox, Switch } from './components/signals';

<TextField placeholder="Enter your name" lg />
<CheckBox checked={isChecked} onChange={setIsChecked} />
<Switch on={isEnabled} onChange={setIsEnabled} />

🎨 Signal System

Structural Signals (Identity)

Define what the component is:

Tone/Style: primary, secondary, cta, ghost, neumorphism Color: red, green, blue, yellow, purple Size: xs, sm, md, lg, xl Shape: square, rounded, pill, circle

Behavioral Signals (Interaction)

Define how it behaves:

Hover: hoverEnlarge, hoverShrink, hoverLift, hoverFade Active: activeShrink, activeRipple, activeExplode Effects: ripple, innerShadow, noShadow

Layout Signals

Display: block, inline, center Border: border, noBorder, roundedBorder

🔧 Advanced Usage

Custom Signal Mapping

Each component contains a signal mapping section where you can customize how signals translate to CSS:

// Inside Button.jsx
const layer = (name, scope = "btn") => (className) =>
  (layerSignal[scope] ||= {},
  layerSignal[scope][name] ||= [],
  (layerSignal[scope][name][0] = className));

// Composite Signal
  inputSignal.ghost && (
btn.shape("rounded-full"),
btn.shadow("shadow-none"),
btn.color("bg-transparent text-gray-800"),
btn.hover("hover:scale-110 hover:bg-gray-100/50 hover:text-gray-900"),
btn.active("active:scale-95 active:bg-gray-100/75 active:text-gray-900"),
btn.animation("transition-all duration-500 cursor-pointer")
)

// Individual Signals
inputSignal.xs      && btn.size("px-2 py-1 text-xs"),
inputSignal.sm      && btn.size("px-3 py-1.5 text-sm"),
inputSignal.md      && btn.size("px-4 py-2 text-base"),
inputSignal.lg      && btn.size("px-6 py-3 text-lg"),
inputSignal.xl      && btn.size("px-8 py-4 text-xl")

State Management

Interactive components use state signals for React hooks:

const state = (name, priority = 0, initial = false) => (
  (stateSignal._hooks ||= {})[name] ||= (() => {
    const [get, set] = useState(initial);
    return { get, set };
  })(),
  priority && (!stateSignal._priority || priority > stateSignal._priority) &&
    (stateSignal[name] = stateSignal._hooks[name], stateSignal._priority = priority)
);

🛠️ Development

Component Structure

Each component follows this structure:

export function ComponentName(contract = {}) {
  /* ────────────────────────────────────────────────────────────────────────────
   * CONTRACT
   * ──────────────────────────────────────────────────────────────────────────── */
  const [inputSignal, layerSignal, dataSignal, stateSignal] = [{ ...contract }, {}, {}, {}];
  
  /* ────────────────────────────────────────────────────────────────────────────
   * CONTRACT TOOLS
   * ──────────────────────────────────────────────────────────────────────────── */
  const layer = (name, scope = "root") => (className) => { /* ... */ };
  const data = (name, key = name) => { /* ... */ };
  const state = (name, priority = 0, initial = false) => { /* ... */ };
  
  /* ────────────────────────────────────────────────────────────────────────────
   * LAYERS
   * ──────────────────────────────────────────────────────────────────────────── */
  // Signal mappings here
  
  /* ────────────────────────────────────────────────────────────────────────────
   * RENDER
   * ──────────────────────────────────────────────────────────────────────────── */
  return (
    // JSX with className={classes(layerSignal.root)}
  );
}

📚 Philosophy

Ownership Over Abstraction

  • Copy, don't import: Components are copied into your project
  • No vendor lock-in: You own the code completely
  • No hidden logic: Everything is visible and editable
  • The file is the product: Components are self-contained documentation

Intention Over Configuration

  • No variant enums: Use primary, not variant="primary"
  • No size schemas: Use lg, not size="large"
  • Signals express intent: Props describe what you want, not how to configure it
  • Composable API: Mix and match signals freely

HTML Already Has State

  • Respect browser behavior: Use :hover, :focus, :active
  • Semantic HTML: Proper elements and accessibility
  • Keyboard navigation: Built-in browser support
  • No re-modeling: Don't fight the platform

🤝 Contributing

Signal Layers follows the "copy and edit" philosophy. To contribute:

  1. Copy components to your project
  2. Make changes as needed
  3. Share improvements with the community
  4. No PRs required - this is a copy-first system

📄 License

MIT License - feel free to use, modify, and distribute.

🔗 Links

  • GitHub: https://github.com/aryanbatras/minimalist-ui
  • Issues: https://github.com/aryanbatras/minimalist-ui/issues
  • NPM: https://www.npmjs.com/package/signal-layers