typescriptbeginner

Loading UI with Skeleton Screens

Create loading.tsx skeleton screens for instant navigation feedback with Next.js App Router.

typescript
// app/dashboard/loading.tsx
export default function DashboardLoading() {
  return (
    <div className="p-6 space-y-6 animate-pulse">
      {/* Header skeleton */}
      <div className="flex items-center justify-between">
        <div className="h-8 w-48 bg-gray-800 rounded" />
        <div className="h-10 w-32 bg-gray-800 rounded-lg" />
      </div>

      {/* Stats grid skeleton */}
      <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
        {Array.from({ length: 3 }).map((_, i) => (
          <div
            key={i}
            className="bg-[#111] border border-white/10 rounded-xl p-6"
          >
            <div className="h-4 w-20 bg-gray-800 rounded mb-3" />
            <div className="h-8 w-24 bg-gray-800 rounded" />
          </div>
        ))}
      </div>

      {/* Table skeleton */}
      <div className="bg-[#111] border border-white/10 rounded-xl overflow-hidden">
        <div className="p-4 border-b border-white/10">
          <div className="h-5 w-32 bg-gray-800 rounded" />
        </div>
        {Array.from({ length: 5 }).map((_, i) => (
          <div
            key={i}
            className="flex items-center gap-4 p-4 border-b border-white/5"
          >
            <div className="h-10 w-10 bg-gray-800 rounded-full" />
            <div className="flex-1 space-y-2">
              <div className="h-4 w-48 bg-gray-800 rounded" />
              <div className="h-3 w-32 bg-gray-800 rounded" />
            </div>
            <div className="h-6 w-16 bg-gray-800 rounded-full" />
          </div>
        ))}
      </div>
    </div>
  );
}

// Reusable skeleton components
function Skeleton({ className = '' }: { className?: string }) {
  return <div className={`bg-gray-800 rounded animate-pulse ${className}`} />;
}

function SkeletonCard() {
  return (
    <div className="bg-[#111] border border-white/10 rounded-xl p-4 space-y-3">
      <Skeleton className="h-5 w-3/4" />
      <Skeleton className="h-4 w-full" />
      <Skeleton className="h-4 w-2/3" />
    </div>
  );
}

export { Skeleton, SkeletonCard };

Use Cases

  • Route transition loading states
  • Dashboard skeleton screens
  • Content placeholder layouts

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.