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

@morphuiapp/morphui

v0.4.1

Published

Intelligent UI SDK for React

Readme

morph

Intelligent UI SDK for React

Your app has one interface. Your users are not one person.

npm license React Next.js

Website · Documentation · Dashboard · Pricing


What is Morph?

Morph is an intelligent UI SDK that makes your React app personal for every user — automatically.

No theme files to write. No dark mode to build. No accessibility backlog. One line of code. That's it.

<MorphProvider licenseKey="morph-free-demo">
  <App />
</MorphProvider>

Works without a license key — native detection is always free. Add a key for AI-powered adaptation. Get your key →


Three layers of intelligence

V1 — Context Intelligence

Morph reads the room the moment your app loads.

  • 🌙 Dark at night. Light in the morning.
  • ♿ High contrast when the system asks.
  • 🎨 Color-blind safe palette when needed.
  • ⚡ Reduced motion. Bold text. Language. All detected.

System preference always wins. Time-based logic is a smart fallback — never an override.

V1 — Design Intelligence

Claude reads your actual design — not just your colors.

Not a color inverter. Morph reads your Tailwind classes, computed styles, inline styles, Ant Design tokens — and reasons about your design like a senior designer would. What's a background? What's a card? What's a brand color that should never change?

The result: 4 surface depth levels generated from your palette, WCAG AA verified on every element, gradients adapted, portals and modals covered. It looks hand-crafted. Because the reasoning behind it was.

V2 — Behavioral Intelligence (Pro)

Your interface learns this person — and 11 papercuts disappear.

Morph V2 fixes the small frustrations every web app has: the white flash between routes, the form that resets on back-button, the scroll position that vanishes after a refresh, the dialog that doesn't trap focus, the autofill that breaks your validation, the rage-tap on a 24px button. All local, all private, all in IndexedDB. Nothing leaves the browser.

  • 6 auto-engines that just work — opt-out per feature
  • 5 drop-in components for the parts where a component is the right answer
  • 3 hooks for storage, cross-tab sync, and autofill

Always with their permission. Always reversible. Each engine is a lazy chunk — zero overhead if unused.


Install

npm install @morphuiapp/morphui

Quick start

import { MorphProvider } from '@morphuiapp/morphui'

export default function App() {
  return (
    <MorphProvider licenseKey="morph-free-demo">
      <YourApp />
    </MorphProvider>
  )
}

How adaptation works

| App theme | Time of day | System preference | Action | |-----------|-------------|-------------------|--------| | Light | Day | None | ✅ Stay light | | Light | Night | None | 🌙 Switch to dark | | Dark | Day | None | ☀️ Switch to light | | Dark | Night | None | ✅ Stay dark | | Any | Any | Dark (manual) | 🌙 Always dark | | Any | Any | Light (manual) | ☀️ Always light |


Read the state anywhere

import { useMorph } from '@morphuiapp/morphui'

function MyComponent() {
  const {
    theme,                // 'dark' | 'light'
    adaptation,           // 'darken' | 'lighten' | 'none'
    highContrast,         // 'normal' | 'high'
    colorBlindMode,       // null | 'deuteranopia' | 'protanopia' | 'tritanopia'
    prefersReducedMotion, // true | false
    language,             // 'en' | 'fr' | ...
    appBrightness,        // original theme of your app
    // V2 — Pro
    morphingMode,         // 'digest' | 'article' | 'gallery'
    zoneOrder,            // { search: 1, feed: 2 }
  } = useMorph()
}

Hooks

useTheme()

import { useTheme } from '@morphuiapp/morphui'

const { theme, prefersReducedMotion } = useTheme()
// theme → 'light' | 'dark'

useAccessibility()

import { useAccessibility } from '@morphuiapp/morphui'

const { highContrast, forcedColors, colorBlindMode } = useAccessibility()

You always stay in control

data-morph-skip — protect a subtree

Put this on any element and Morph stops at that boundary — styles, ordering, and tracking. All untouched.

<div data-morph-skip>
  {/* Morph never touches this */}
  <BrandLogo />
  <PDFViewer />
</div>

data-morph-force — re-enable inside a skipped zone

<div data-morph-skip>
  <LegacyWidget />
  <section data-morph-force>
    {/* Morph applies again here */}
    <ModernCard />
  </section>
</div>

safeMode — detect without touching anything

<MorphProvider safeMode>
  <App />
</MorphProvider>

Morph detects everything, applies nothing. useMorph() still returns all values with safeMode: true.


Setup by framework

Tailwind CSS

// tailwind.config.js
module.exports = {
  darkMode: 'class', // Required
  content: ['./src/**/*.{js,ts,jsx,tsx}'],
}

Morph automatically toggles .dark on <html> — all your dark: classes work instantly.

CSS Variables

body {
  background: var(--morph-bg, var(--background));
  color: var(--morph-text-primary, var(--foreground));
}

.card {
  background: var(--morph-card-bg, var(--card));
  border: 1px solid var(--morph-border, var(--border));
}

Next.js App Router

// app/providers.tsx
'use client'
import { MorphProvider } from '@morphuiapp/morphui'

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <MorphProvider licenseKey="morph-free-demo">
      {children}
    </MorphProvider>
  )
}
// app/layout.tsx
import { Providers } from './providers'

export default function RootLayout({ children }) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body>
        <Providers>{children}</Providers>
      </body>
    </html>
  )
}

Ant Design / MUI / Chakra

No special config needed. Wrap your app — Morph handles the rest.

<MorphProvider licenseKey="morph-free-demo">
  <ConfigProvider> {/* antd */}
    <App />
  </ConfigProvider>
</MorphProvider>

V2 — Things that just work

Six auto-engines run inside MorphProvider. No code to write. Each one ships as its own lazy chunk and is opt-out via a single prop.

PreNavSkeleton — kill the white flash

The frustration: every router transition repaints the page white before the new route renders. Users think the app froze.

The fix: Morph snapshots the layout structure of every page you visit, intercepts navigation, and paints a same-shape skeleton in the gap between unmount and mount. The skeleton matches your actual surface colors (it reads --morph-bg / --morph-card-bg).

Auto-on. Disable with <MorphProvider preNav={false}>.

WhiteIslandFixer — no more white blocks in dark mode

Third-party iframes (Stripe, Calendly, YouTube) and PNG logos with white backgrounds scream in dark mode. Morph detects them, dims iframes via the cover trick, and applies mix-blend-mode: multiply to white-pixel logos.

Auto-on. Disable with <MorphProvider whiteIslandFix={false}>.

ScrollRestoration — every page remembers

Browsers restore scroll on back-navigation, sometimes. Refreshes wipe it. Anchored elements (sticky headers) shift on restore. Morph snapshots scroll position per route, restores after first paint, and adjusts for layout shift.

Auto-on. Disable with <MorphProvider scrollRestore={false}>.

ImproperTapDetector — catches double-taps that mean rage

Users double-tap a button when they think nothing happened. Morph detects the pattern (same target, <300ms apart, no visible change) and shows a non-blocking "Action confirmed" undo banner so the second tap doesn't fire a duplicate.

Auto-on. Disable with <MorphProvider improperTap={false}>.

LostTapDetector — flags missed touch targets

When a user taps near but not on a button, that's friction worth knowing about. Morph reports near-miss taps to the dashboard so you see which targets are too small. Nothing visible to the end-user.

Auto-on. Disable with <MorphProvider lostTap={false}>.


V2 — Drop-in components

Five components for cases where a component is the cleaner answer than an engine.

MorphForm — no more lost form data

The frustration: user fills a 12-field form, hits the back button, comes back. Empty.

Wrap any form. Morph snapshots field values to IndexedDB on every change, restores on mount, clears on submit.

import { MorphForm } from '@morphuiapp/morphui'

<MorphForm id="contact-form" onSubmit={handleSubmit}>
  <input name="email" />
  <textarea name="message" />
  <button type="submit">Send</button>
</MorphForm>

MorphLoader — adaptive loading state

A loader that respects prefers-reduced-motion, matches your theme, and uses a real skeleton (not a spinner) when given a shape prop.

import { MorphLoader } from '@morphuiapp/morphui'

<MorphLoader shape="card" count={3} />

MorphDialog — accessible modal that traps focus

Replaces the homemade <div className="modal">. Backdrop click to close, ESC to close, focus trap, restores focus to the trigger on close, applies inert to the rest of the page so screen readers ignore it.

import { MorphDialog } from '@morphuiapp/morphui'

<MorphDialog open={open} onClose={() => setOpen(false)} title="Confirm">
  Delete this license?
</MorphDialog>

MorphPhoneInput — international phone field that adapts

Auto-detects the user's country from navigator.language, formats as they type, validates on blur. Theme-aware, RTL-aware.

import { MorphPhoneInput } from '@morphuiapp/morphui'

<MorphPhoneInput value={phone} onChange={setPhone} />

MorphZone — the original V2 primitive

After enough sessions, Morph reorders zones based on what this user actually uses. Always with their permission. Always with an Undo button.

import { MorphZone } from '@morphuiapp/morphui'

<MorphZone id="search" priority={1}>
  <SearchSection />
</MorphZone>
<MorphZone id="feed" priority={2}>
  <FeedSection />
</MorphZone>

V2 — Utility hooks

useStorage() — persistence with automatic fallback

IndexedDB → localStorage → in-memory. Same API everywhere. Returns [value, setValue, { ready }].

import { useStorage } from '@morphuiapp/morphui'

const [draft, setDraft, { ready }] = useStorage('post-draft', '')

useTabSync() — keep state in sync across tabs

BroadcastChannel under the hood. When the user has your app in two tabs, both stay coherent.

import { useTabSync } from '@morphuiapp/morphui'

const [count, setCount] = useTabSync('cart-items', 0)

useAutoFillGuard() — detect browser autofill

Browser autofill doesn't fire onChange consistently. This hook uses the :-webkit-autofill CSS animation trick to fire a callback the moment a field is autofilled, so your validation runs.

import { useAutoFillGuard } from '@morphuiapp/morphui'

const ref = useAutoFillGuard((field) => trigger(field.name))
return <input ref={ref} name="email" />

Full documentation →


CSS Variables reference

| Variable | Description | |----------|-------------| | --morph-bg | Main background | | --morph-card-bg | Card / surface background | | --morph-text-primary | Primary text | | --morph-text-secondary | Secondary / muted text | | --morph-primary | Brand / accent color | | --morph-primary-text | Text on primary color | | --morph-border | Border color | | --morph-surface | Alternative surface | | --morph-font-scale | Font boost in high contrast | | --morph-motion | Motion multiplier |


Framework support

| Framework | Status | |-----------|--------| | React 18+ | ✅ | | Next.js 13+ App Router | ✅ | | Next.js 12 Pages Router | ✅ | | Vite + React | ✅ | | Tailwind CSS v3 / v4 | ✅ | | shadcn/ui | ✅ | | Ant Design v5+ | ✅ | | Material UI v5+ | ✅ | | Chakra UI v3 | ✅ | | CSS / SCSS | ✅ | | Vue.js | 🔜 V3 |


Troubleshooting

Dark mode not activating on Tailwind Add darkMode: 'class' in tailwind.config.js.

Colors not adapting

  • MorphProvider must wrap your app at root level
  • Avoid !important on color properties
  • Prefer CSS classes over inline styles

Next.js flash of wrong theme

<script>
  if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
    document.documentElement.classList.add('dark')
  }
</script>

Text unreadable after adaptation Make sure elements have explicit backgrounds — not transparent. Update to the latest version: npm update @morphuiapp/morphui


Pricing

| Feature | Free | Professional | Business | Enterprise | | ------- | ---- | ------------ | -------- | ---------- | | Price | $0 | $29/mo | $99/mo | Custom | | API calls/day | 100 | 5,000 | 50,000 | Unlimited | | License keys | 1 | 5 | 25 | Unlimited | | Dark mode + Accessibility | ✅ | ✅ | ✅ | ✅ | | AI theme generation | ✅ | ✅ | ✅ | ✅ | | V2 auto-engines (PreNav, ScrollRestore, …) | — | ✅ | ✅ | ✅ | | V2 components (Form, Dialog, Zone, …) | — | ✅ | ✅ | ✅ | | Analytics dashboard | — | — | ✅ | ✅ | | AI recommendations | — | — | ✅ | ✅ | | SLA + private support | — | — | — | ✅ |

Get your license key →


Roadmap

✅ Live now

  • Automatic dark / light theme
  • WCAG AA — guaranteed, not hoped for
  • System preferences — all of them
  • AI-powered theme generation (Claude)
  • Tailwind, shadcn, Ant Design, MUI, Chakra, CSS / SCSS

✅ V2 — Behavioral Intelligence

  • Zone tracking and reordering
  • Interface morphing (digest / article / gallery)
  • Personal heatmap — cross-session
  • Navigation pattern detection
  • Analytics dashboard
  • AI-powered recommendations (opt-in)

🔜 V3

  • Vue.js support
  • React Native support

morphui.dev · Docs · Dashboard · npm

Every user deserves an interface made for them.

MIT License