Skip to content

arnonsang/skelayzr

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

1 Commit
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Skelayzr 🦴

npm version npm downloads GitHub license GitHub issues GitHub stars TypeScript

⚠️ Warning: Under Development - This repository is currently under active development. Use at your own risk for production applications.

Skelayzr your UI – load beautifully, by default.

Skelayzr dynamically wraps any component or DOM element in responsive skeleton loaders. It auto-generates loaders based on the element's structure and layout, providing a smooth and consistent loading experience with elegant, soft colors that blend seamlessly with modern UI designs.

✨ Features

  • 🎯 Auto-detect dimensions from live DOM elements with intelligent caching
  • 🧠 Content-aware placeholders (text, image, avatar, button, etc.)
  • 🎨 Beautiful themes: shimmer, solid, pulse with soft, modern colors
  • πŸ“¦ Lightweight & modular TypeScript-first architecture
  • β™Ώ Accessible by design (aria-busy, reduced motion, screen reader support)
  • ⚑ Performance optimized with IntersectionObserver and smart caching
  • πŸŽ›οΈ Layout intelligence (CSS Grid, Flexbox, aspect ratio preservation)
  • πŸ›‘οΈ Graceful degradation and comprehensive error handling
  • πŸ”§ Full TypeScript support with complete type safety
  • πŸš€ Framework integrations (React hook included, Vue/Angular ready)

πŸš€ Quick Start

Installation

npm install skelayzr
# or
yarn add skelayzr
# or
pnpm add skelayzr
# or
bun add skelayzr

Basic Usage

Vanilla JavaScript/TypeScript

<div id="profile">
  <img src="avatar.jpg" alt="Avatar" />
  <h2>Jane Doe</h2>
  <p>Senior Frontend Developer</p>
</div>
import { skelayzr } from 'skelayzr';
import 'skelayzr/styles';

// Wrap element with skeleton (uses soft, modern colors)
skelayzr('#profile', {
  theme: 'shimmer',
  loading: true
});

// Toggle loading state with options
skelayzr.setLoading('#profile', false);

// Or with custom delay
skelayzr.setLoading('#profile', true, { delay: 0 });

React Hook

import { useSkelayzr } from 'skelayzr/react';

function Profile({ loading, user }) {
  const { ref } = useSkelayzr({ loading, theme: 'shimmer' });
  
  return (
    <div ref={ref}>
      <img src={user.avatar} alt="Avatar" />
      <h2>{user.name}</h2>
      <p>{user.bio}</p>
    </div>
  );
}

πŸ“– API Reference

Core Functions

skelayzr(element, options)

Main function to wrap an element with a skeleton loader.

import { skelayzr, type SkelayzrOptions } from 'skelayzr';

const options: SkelayzrOptions = {
  theme: 'shimmer',
  loading: true,
  delay: 150
};

const instance = skelayzr('#my-element', options);

Options

Option Type Default Description
theme 'shimmer' | 'solid' | 'pulse' | 'custom' 'shimmer' Skeleton animation theme
loading boolean false Whether to show skeleton immediately
delay number 150 Delay before showing skeleton (ms)
cacheStrategy 'lazy' | 'eager' | 'manual' 'lazy' Skeleton caching strategy
resizeDebounce number 300 Resize event debounce time (ms)
intersectionThreshold number 0.1 Intersection observer threshold
exclude string[] [] CSS selectors to exclude
gracefulDegradation boolean true Handle errors gracefully
debug boolean false Enable debug mode
onError function - Error callback function

Utility Functions

// Set loading state
skelayzr.setLoading(element, true);

// Remove skeleton
skelayzr.unwrap(element);

// Auto-scan elements
skelayzr.scan('.skelayzr-auto');

// Cache management
skelayzr.cache.clear();
skelayzr.cache.getSize();

// Get statistics
const stats = skelayzr.getStats();

// Clean up everything
skelayzr.destroy();

Presets

Pre-configured options for common UI patterns:

// Card layout preset
skelayzr('#card', skelayzr.presets.card());

// List/feed preset
skelayzr('#list', skelayzr.presets.list());

// Form preset
skelayzr('#form', skelayzr.presets.form());

🎨 Themes & Colors

Built-in Themes

Skelayzr comes with beautiful, soft themes that blend seamlessly with modern UI:

  • shimmer – Elegant gradient shimmer animation with soft highlights
  • solid – Clean static blocks with gentle colors (#f1f3f4)
  • pulse – Smooth breathing animation
  • custom – Use your own CSS classes

Modern Color Palette

/* Light mode - soft, modern colors */
--skeleton-bg: #f1f3f4;
--skeleton-highlight: rgba(255, 255, 255, 0.6);

/* Dark mode - elegant dark theme */
--skeleton-bg: #e5e7ea;
--skeleton-highlight: rgba(240, 240, 240, 0.15);

Custom Themes

.skelayzr.my-custom-theme {
  --skeleton-bg: #f8fafc;
  --skeleton-highlight: rgba(255, 255, 255, 0.8);
  background: var(--skeleton-bg);
}
skelayzr('#element', { theme: 'my-custom-theme' });

βš›οΈ React Integration

useSkelayzr Hook

import { useSkelayzr } from 'skelayzr/react';

function MyComponent({ isLoading, data }) {
  const { ref, setLoading } = useSkelayzr({
    loading: isLoading,
    theme: 'shimmer',
    delay: 200
  });

  // Programmatically control loading
  const handleRefresh = () => {
    setLoading(true);
    fetchData().finally(() => setLoading(false));
  };

  return (
    <div ref={ref}>
      <h1>{data?.title}</h1>
      <p>{data?.description}</p>
      <button onClick={handleRefresh}>Refresh</button>
    </div>
  );
}

πŸŽ›οΈ Advanced Configuration

Layout Intelligence

skelayzr('#complex-layout', {
  layoutHints: {
    preserveGrid: true,
    respectFlexGrow: true,
    maintainAspectRatio: true,
    adaptToContainer: true
  }
});

Content Type Detection

skelayzr('#content', {
  contentTypes: {
    avatar: { 
      selectors: ['.avatar', '[data-avatar]'], 
      aspectRatio: 1 
    },
    cardTitle: { 
      selectors: ['h1', 'h2', '.title'], 
      lineClamp: 1 
    },
    paragraph: { 
      selectors: ['p', '.description'], 
      lineClamp: 3 
    }
  }
});

πŸ”§ Performance Optimization

Intersection Observer

Skelayzr automatically uses IntersectionObserver to only create skeletons for visible elements:

skelayzr('#list-container', {
  intersectionThreshold: 0.1, // Trigger when 10% visible
  cacheStrategy: 'lazy' // Cache skeletons for better performance
});

Smart Caching

Skelayzr intelligently caches skeleton DOM elements to boost performance:

// Cache similar skeletons automatically
skelayzr('.card', { loading: true }); // Creates and caches
skelayzr('.card2', { loading: true }); // Reuses cached skeleton!

// Manual cache management
skelayzr.cache.clear(); // Clear all cached skeletons
console.log(`Cache size: ${skelayzr.cache.getSize()}`); // Check cache stats

// Cache strategies
const engine = skelayzr.createEngine({
  cacheStrategy: 'eager' // 'lazy' | 'eager' | 'manual'
});

Cache Benefits:

  • ⚑ Faster rendering for similar elements
  • 🧠 Smart reuse based on dimensions + content type + theme
  • πŸ’Ύ Memory efficient with automatic cleanup (max 100 items)
  • πŸ“Š Performance tracking via skelayzr.getStats()

β™Ώ Accessibility

Skelayzr follows accessibility best practices:

  • Adds aria-busy="true" to skeleton elements
  • Provides aria-label="Loading content"
  • Respects prefers-reduced-motion
  • Maintains focus management
  • Supports high contrast mode

πŸ§ͺ Testing

Skelayzr has a comprehensive test suite with 37 passing tests:

# Run all tests
npm test

# Run tests with UI
npm run test:ui

# Run tests with coverage
npm run test:coverage

# Start demo server
npm run demo

Testing with Skelayzr

import { skelayzr } from 'skelayzr';
import { render, screen } from '@testing-library/react';

test('should show skeleton while loading', () => {
  const { container } = render(<MyComponent loading={true} />);
  
  expect(container.querySelector('.skelayzr')).toBeInTheDocument();
  expect(screen.getByLabelText('Loading content')).toBeInTheDocument();
});

test('should cache skeleton for performance', () => {
  const element = document.createElement('div');
  skelayzr(element, { loading: true });
  
  const stats = skelayzr.getStats();
  expect(stats.cacheSize).toBeGreaterThan(0);
});

πŸ“Š Browser Support

  • Chrome/Edge 88+
  • Firefox 87+
  • Safari 14+
  • React 16.8+ (for React integration)

🀝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

πŸ“„ License

MIT Β© arnonsang

πŸ™ Acknowledgments

  • Inspired by modern loading patterns in React, Vue, and Angular ecosystems
  • Built with TypeScript for better developer experience
  • Designed with accessibility and performance in mind

πŸš€ Quick Demo

Try Skelayzr locally:

git clone <repo-url>
cd skelayzr
npm install
npm run build
npm run demo

Visit:

  • http://localhost:8080 - Full ES module demo
  • http://localhost:8080/demo-standalone.html - Standalone demo

Made with ❀️ using TypeScript β€’ πŸ› Issues β€’ 🀝 Contributing

About

Dynamically wraps any component or DOM element in responsive skeleton loaders.

Resources

License

Stars

Watchers

Forks

Contributors