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

@zakiibnu723/react-auto-skeleton

v0.1.7

Published

Zero-config automatic skeleton loader for React components preserving layout and spacing.

Downloads

674

Readme

react-auto-skeleton

Automatic, layout-accurate skeleton loaders for React

Zero manual skeleton components. Automatically generates visually identical skeleton versions of your React components by analyzing the rendered DOM and preserving exact layout, spacing, and structure.


🎯 Problem

Current skeleton loading approaches require:

  • Manually creating separate skeleton components
  • Maintaining skeletons alongside UI components
  • Updating skeletons every time UI changes
  • Writing duplicate layout code

This causes code duplication, inconsistency, and maintenance overhead.


💡 Solution

react-auto-skeleton solves this by:

  1. Rendering your component invisibly
  2. Letting the browser compute the final layout (including Tailwind CSS, inline styles, etc.)
  3. Automatically generating a skeleton that preserves:
    • Layout structure (flex, grid, block)
    • Spacing (padding, margin, gap)
    • Dimensions (width, height)
    • Element hierarchy

No manual skeleton components needed.


📦 Installation

npm install @zakiibnu723/react-auto-skeleton

or

yarn add @zakiibnu723/react-auto-skeleton

or

pnpm add @zakiibnu723/react-auto-skeleton

🚀 Quick Start

import { AutoSkeleton } from '@zakiibnu723/react-auto-skeleton';
// or use alias: import { SkeletonMorph } from '@zakiibnu723/react-auto-skeleton';
import { useState } from 'react';

function App() {
  const [loading, setLoading] = useState(true);

  return (
    <AutoSkeleton loading={loading}>
      <YourComponent />
    </AutoSkeleton>
  );
}

That's it! When loading is true, AutoSkeleton shows a skeleton. When false, it shows the actual component. No manual CSS imports required (zero-config).


📖 API Reference

<AutoSkeleton>

Wrapper component that automatically generates skeleton loaders.

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | loading | boolean | true | When true, shows skeleton. When false, shows actual component. | | animate | 'shimmer' | 'pulse' | 'none' | 'shimmer' | Animation style for skeleton elements. | | ignore | string[] | undefined | CSS selectors to skip during skeleton generation (e.g., ['svg', '.icon']). | | className | string | undefined | CSS class applied to the wrapper container. | | children | ReactNode | required | The component(s) to wrap with skeleton functionality. |


🎨 Animation Modes

Shimmer (Default)

Animated gradient sweep effect that moves across skeleton elements.

<AutoSkeleton loading={loading} animate="shimmer">
  <ProductCard />
</AutoSkeleton>

Pulse

Gentle fade in/out animation.

<AutoSkeleton loading={loading} animate="pulse">
  <UserProfile />
</AutoSkeleton>

None

Static skeleton without animation.

<AutoSkeleton loading={loading} animate="none">
  <CommentList />
</AutoSkeleton>

🔧 Advanced Usage

Ignoring Elements

Use the ignore prop to skip certain elements (like decorative icons) during skeleton generation:

<AutoSkeleton 
  loading={loading} 
  ignore={['svg', 'path', '.icon']}
>
  <Dashboard />
</AutoSkeleton>

This is useful for:

  • SVG icons that don't need skeleton versions
  • Decorative elements
  • Elements with complex rendering logic

Custom Styling & Theming

Apply custom styles to the skeleton wrapper:

<AutoSkeleton 
  loading={loading} 
  className="my-skeleton-wrapper"
>
  <Card />
</AutoSkeleton>

Custom Colors (CSS Variables)

react-auto-skeleton works out of the box with zero configuration, but you can easily customize skeleton colors and animations for your theme (light/dark mode) using standard CSS variables:

:root {
  /* Tier 1: Card container surface (default: #1e293b) */
  --ras-card-bg: #1e293b;

  /* Tier 2: Skeleton leaf elements and shimmer sweep (default: #334155 & #475569) */
  --ras-base: #334155;
  --ras-highlight: #475569;

  /* Optional: Custom corner radius for leaf elements (default: 8px) */
  --ras-radius: 8px;
}

/* Light Mode Example */
[data-theme="light"], .light {
  --ras-card-bg: #ffffff;
  --ras-base: #cbd5e1;
  --ras-highlight: #f1f5f9;
}

Conditional Loading

function DataView() {
  const { data, isLoading } = useQuery();

  return (
    <AutoSkeleton loading={isLoading}>
      {data && <DataTable data={data} />}
    </AutoSkeleton>
  );
}

🏗️ How It Works

  1. Invisible Render: Component is rendered with visibility: hidden
  2. DOM Analysis: Browser computes final layout including all CSS (Tailwind, styled-components, etc.)
  3. Skeleton Generation: Walks the DOM tree and creates skeleton elements preserving:
    • Display types (flex, grid, block)
    • Layout properties (padding, margin, gap)
    • Dimensions (width, height)
    • Parent-child relationships
  4. Display: Shows generated skeleton with chosen animation

Element Handling

  • Text nodes → Converted to skeleton bars with computed line height
  • Images → Rectangular skeletons preserving dimensions
  • Buttons/Inputs → Converted to non-interactive skeleton blocks
  • Containers → Preserve layout (flex/grid) and spacing

✅ Features

  • ✅ Zero manual skeleton components
  • ✅ Preserves exact layout and spacing
  • ✅ Works with any CSS framework (Tailwind, styled-components, CSS Modules, etc.)
  • ✅ Handles text, images, buttons, forms, and complex layouts
  • ✅ Multiple animation modes (shimmer, pulse, none)
  • ✅ Customizable via ignore selectors
  • ✅ Full TypeScript support
  • ✅ Responsive by default
  • ✅ Lightweight (~9KB gzipped)

⚠️ Limitations

  • Requires first render: Skeleton appears after initial paint (not SSR compatible)
  • Client-side only: Best for client-rendered components
  • ResizeObserver dependency: Uses ResizeObserver for responsive updates (widely supported)

These are acceptable trade-offs for the convenience of automatic skeleton generation.


📚 Examples

Product Card

<AutoSkeleton loading={loading} animate="shimmer">
  <div className="product-card">
    <img src="product.jpg" alt="Product" />
    <h3>Premium Headphones</h3>
    <p>High-quality audio with noise cancellation</p>
    <div className="price">$199</div>
    <button>Add to Cart</button>
  </div>
</AutoSkeleton>

User Profile

<AutoSkeleton loading={loading} animate="pulse">
  <div className="profile">
    <img src="avatar.jpg" alt="User" className="avatar" />
    <h2>John Doe</h2>
    <p>Software Engineer</p>
    <div className="stats">
      <div>1,234 Followers</div>
      <div>567 Following</div>
    </div>
  </div>
</AutoSkeleton>

Comment List

<AutoSkeleton loading={loading} animate="none">
  <div className="comments">
    {comments.map(comment => (
      <div key={comment.id} className="comment">
        <img src={comment.avatar} className="avatar" />
        <div>
          <strong>{comment.author}</strong>
          <p>{comment.text}</p>
        </div>
      </div>
    ))}
  </div>
</AutoSkeleton>

Form

<AutoSkeleton loading={loading}>
  <form>
    <label>
      Name
      <input type="text" placeholder="Your name" />
    </label>
    <label>
      Email
      <input type="email" placeholder="[email protected]" />
    </label>
    <label>
      Message
      <textarea rows={4} />
    </label>
    <button type="submit">Send</button>
  </form>
</AutoSkeleton>

🎓 Use Cases

Data Fetching

function UserList() {
  const { data, isLoading } = useUsers();

  return (
    <AutoSkeleton loading={isLoading}>
      <div className="user-grid">
        {data?.map(user => <UserCard key={user.id} user={user} />)}
      </div>
    </AutoSkeleton>
  );
}

Lazy Loading

const HeavyComponent = lazy(() => import('./HeavyComponent'));

function App() {
  return (
    <Suspense fallback={
      <AutoSkeleton loading>
        <HeavyComponentPlaceholder />
      </AutoSkeleton>
    }>
      <HeavyComponent />
    </Suspense>
  );
}

Progressive Enhancement

function Dashboard() {
  const [loaded, setLoaded] = useState(false);

  useEffect(() => {
    // Simulate data loading
    setTimeout(() => setLoaded(true), 2000);
  }, []);

  return (
    <AutoSkeleton loading={!loaded} animate="shimmer">
      <div className="dashboard">
        <StatCards />
        <Charts />
        <RecentActivity />
      </div>
    </AutoSkeleton>
  );
}

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.


📄 License

MIT © 2025


🙏 Acknowledgments

Built for Final Thesis (Tugas Akhir) - Demonstrating automatic UI skeleton generation through DOM analysis and layout preservation.


🔗 Links

  • Demo: Run npm run dev to see interactive examples
  • Issues: Report bugs or request features
  • TypeScript: Full type definitions included

💻 Development

# Install dependencies
npm install

# Run demo
npm run dev

# Build library
npm run build

# Run tests
npm test

# Lint
npm run lint

🎯 Design Philosophy

Skeletons are NOT designed. Skeletons are GENERATED.

The library doesn't redesign your UI—it converts it. Every DOM element maps to a skeleton element, preserving the exact layout structure your users expect.

Key Principles

  1. One Element, One Skeleton: Never merge multiple elements
  2. Layout Preservation: Keep display types, spacing, and hierarchy
  3. Automatic Conversion: Text → bars, Images → blocks, Containers → wrappers
  4. Zero Configuration: Works out of the box with sensible defaults

❓ FAQ

Q: Does this work with Tailwind CSS?
A: Yes! AutoSkeleton works with any CSS approach because it reads computed styles from the browser.

Q: Can I customize skeleton colors?
A: Yes, override the CSS variables --ras-base and --ras-highlight.

Q: Does this support Server-Side Rendering (SSR)?
A: No. The library requires a browser to compute layout. Use traditional skeleton components for SSR.

Q: How does performance compare to manual skeletons?
A: Slightly slower initial render (requires DOM analysis), but negligible in practice. The trade-off is worth it for zero maintenance.

Q: Can I use this with React Native?
A: No. This library depends on browser DOM APIs.


Built with ❤️ for developers who value their time.