Skip to content

ubay1/react-auto-shimmer

Repository files navigation

✨ React Auto Shimmer

npm version License React Next.js

πŸš€ Auto-adapting shimmer loader untuk React yang otomatis menyesuaikan bentuk, ukuran, dan posisi dengan UI asli Anda. Tidak ada lagi skeleton manual yang tidak presisi!

Demo

✨ Fitur

  • 🎯 Auto-Measurement: Shimmer otomatis mengukur dimensi elemen asli (teks, gambar, button, dll)
  • 🧠 Smart Caching: Dimensi disimpan per cacheKey, shimmer presisi di load berikutnya
  • 🎨 Blueprint Skeleton: Berikan template JSX di prop skeleton untuk first-load yang akurat
  • πŸ“ Padding & Border Aware: Mendukung padding, border, border-radius, dan box-shadow via props
  • πŸ”„ Resize Observer: Auto-update saat konten berubah ukuran (responsive, flex-wrap, dll)
  • πŸŒ— Framework Agnostic: Tidak tergantung Tailwind, Bootstrap, atau CSS framework apapun
  • 🟒 Next.js Ready: SSR-safe, bekerja sempurna di Next.js (App Router / Pages Router) dengan "use client"
  • πŸ“¦ Zero CSS Import: Komponen sepenuhnya self-contained, CSS di-inject otomatis
  • πŸ› οΈ TypeScript Ready: Full type definitions included

πŸ“¦ Instalasi

# npm
npm install @ubay182/react-auto-shimmer

# yarn
yarn add @ubay182/react-auto-shimmer

# pnpm
pnpm add @ubay182/react-auto-shimmer


Basic Usage

import React, { useState, useEffect } from "react";
import { AutoShimmer } from "@ubay182/react-auto-shimmer";

const ProfileCard = () => {
  const [loading, setLoading] = useState(true);
  const [data, setData] = useState(null);

  useEffect(() => {
    // Simulasi fetch data
    setTimeout(() => {
      setData({ title: "Hello World", description: "This is a description." });
      setLoading(false);
    }, 2000);
  }, []);

  return (
    <AutoShimmer
      loading={loading}
      cacheKey="my-card"
      skeleton={
        <div className="card">
          <h2>Loading title...</h2>
          <p>Loading description...</p>
        </div>
      }
    >
      {/* Konten Asli */}
      <div className="card">
        <h2>{data?.title}</h2>
        <p>{data?.description}</p>
      </div>
    </AutoShimmer>
  );
};

export default ProfileCard;

Usage with Next.js (App Router) & Tailwind CSS

Pastikan menambahkan "use client" di paling atas file komponen Anda karena AutoShimmer memerlukan akses ke DOM (seperti ResizeObserver dan getBoundingClientRect).

"use client";

import React, { useState, useEffect } from "react";
import { AutoShimmer } from "@ubay182/react-auto-shimmer";
import Link from "next/link";

export default function UserProfile() {
  const [loading, setLoading] = useState(true);
  const [user, setUser] = useState<any>(null);

  const fetchData = () => {
    setLoading(true);
    const names = ["Ubaidillah Rahman", "Budi Santoso", "Siti Aminah"];
    const randomName = names[Math.floor(Math.random() * names.length)];

    setTimeout(() => {
      setUser({
        name: randomName,
        bio: "Fullstack Developer & React Enthusiast.",
        avatar: "https://placehold.co/100x100/e2e8f0/475569?text=UR",
        tags: ["React", "TypeScript", "UI/UX", "Next.js", "Tailwind"],
      });
      setLoading(false);
    }, 3000);
  };

  useEffect(() => {
    fetchData();
  }, []);

  return (
    <AutoShimmer
      loading={loading}
      cacheKey="user-profile-nextjs"
      border="1px solid #e5e7eb"
      borderRadius="12px"
      boxShadow="0 4px 12px rgba(0,0,0,0.05)"
      bgColor="#ffffff"
      padding="1.5rem"
      skeleton={
        <div className="flex flex-col items-center text-center w-full">
          <div className="w-16 h-16 rounded-full bg-gray-200 mb-4"></div>
          <h2 className="w-3/5 h-6 bg-gray-200 rounded mb-2"></h2>
          <p className="w-full h-4 bg-gray-200 rounded mb-4"></p>
          <div className="flex flex-wrap gap-2 mb-4 justify-center w-full">
            {[...Array(5)].map((_, i) => (
              <span
                key={i}
                className="inline-block w-16 h-6 bg-gray-200 rounded-full"
              ></span>
            ))}
          </div>
          <button className="px-5 py-2.5 border-none rounded-lg font-medium text-sm bg-indigo-600 text-white mt-2">
            View Profile
          </button>
        </div>
      }
    >
      {/* KONTEN ASLI */}
      <div className="flex flex-col items-center text-center w-full">
        {user?.avatar && (
          <img
            src={user.avatar}
            alt={user.name}
            className="w-16 h-16 rounded-full mb-4 object-cover"
          />
        )}
        <h2 className="text-2xl font-bold text-gray-900 mb-2 w-full">
          {user?.name || "Loading Name..."}
        </h2>
        <p className="text-gray-600 leading-relaxed mb-4 w-full">
          {user?.bio || "Loading bio..."}
        </p>

        <div className="flex flex-wrap gap-2 mb-4 justify-center w-full">
          {user?.tags?.map((tag: string) => (
            <span
              key={tag}
              className="bg-indigo-50 text-indigo-800 px-3 py-1 rounded-full text-sm font-medium whitespace-nowrap"
            >
              {tag}
            </span>
          ))}
        </div>

        <button className="px-5 py-2.5 border-none rounded-lg cursor-pointer font-medium text-sm bg-indigo-600 text-white mt-2">
          <Link href="/profile" className="text-white decoration-none">
            View Profile
          </Link>
        </button>
      </div>
    </AutoShimmer>
  );
}

πŸ“š API Reference

Prop Tipe Default Deskripsi
loading boolean false Kontrol state loading (true = tampilkan shimmer)
cacheKey string - Unique key untuk caching dimensi. Wajib agar shimmer presisi di refresh berikutnya
border string '1px solid #e5e7eb' CSS border untuk wrapper container
borderRadius string '8px' CSS border-radius untuk wrapper
boxShadow string '0 2px 8px rgba(0,0,0,0.05)' CSS box-shadow untuk wrapper
bgColor string '#ffffff' Background color wrapper
padding string '1.5rem' Padding internal wrapper (shimmer blocks diukur relatif terhadap area ini)
skeleton ReactNode - Blueprint JSX untuk first-load shimmer. Strukturnya sebaiknya mirip konten asli
children ReactNode - Konten asli yang akan ditampilkan saat loading=false dan diukur posisinya

Skip Elements

Gunakan atribut data-shimmer-ignore untuk mengecualikan elemen tertentu agar tidak diubah menjadi shimmer block:

<div>
  <h2>Title</h2>
  <p data-shimmer-ignore>Ini tidak akan ditimpa shimmer block</p>
  <button>Action</button>
</div>

Skip Entire Section

Gunakan data-shimmer-skip jika ada section besar yang ingin diabaikan sepenuhnya oleh scanner ukuran:

<div data-shimmer-skip>
  {/* Konten ini tidak akan di-scan untuk shimmer */}
  <StaticBanner />
</div>

πŸ› οΈ Development

# Clone repo
git clone https://github.com/ubay1/react-auto-shimmer.git
cd react-auto-shimmer

# Install dependencies
npm install

# Run playground (dev mode)
npm run dev

# Build library
npm run build

🀝 Contributing

Contributions welcome!

Silakan:

  1. Fork repo
  2. Buat branch fitur (git checkout -b feat/amazing-feature)
  3. Commit perubahan (git commit -m 'Add amazing feature')
  4. Push ke branch (git push origin feat/amazing-feature)
  5. Buka Pull Request

Pastikan:

  1. βœ… Code mengikuti style yang ada
  2. βœ… Tidak ada error TypeScript
  3. βœ… Playground masih berjalan normal
  4. βœ… Update README jika menambah fitur baru

πŸ“„ License

MIT License - see LICENSE file for details.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors