skeleton-ui

ui

src-1
item-1
item-1
item-1
item-1
item-1
src-2
item-2
item-2
item-2
item-2
item-2
src-3
item-3
item-3
item-3
item-3
item-3
src-4
item-4
item-4
item-4
item-4
item-4
src-5
item-5
item-5
item-5
item-5
item-5
src-6
item-6
item-6
item-6
item-6
item-6
src-7
item-7
item-7
item-7
item-7
item-7
src-8
item-8
item-8
item-8
item-8
item-8

src

http.ts

TS
export async function getItems(value: number, delay: number): Promise<number> {
    return new Promise((resolve) => {
        setTimeout(() => resolve(value), delay);
    });
}

data.tsx

TSX
"use client"

import { use } from "react";

interface DataProps {
    data: Promise<number>;
}

export function Data({ data }: DataProps) {

    const len = use(data);

    return (
        <>
            {
                [ ...Array(len) ].map((_, idx) => (
                    <div className="w-full p-5 border border-slate-700 space-y-5 text-white"
                         key={ idx + 1 }>
                        <div className="bg-slate-800 h-24 w-full mb-10">
                            src-{ idx + 1 }
                        </div>
                        <div className="bg-slate-800 h-5 w-3/4">
                            item-{ idx + 1 }
                        </div>
                        <div className="bg-slate-800 h-5 w-1/2">
                            item-{ idx + 1 }
                        </div>
                        <div className="bg-slate-800 h-5 w-1/4">
                            item-{ idx + 1 }
                        </div>
                        <div className="bg-slate-800 h-5 w-3/4">
                            item-{ idx + 1 }
                        </div>
                        <div className="bg-slate-800 h-5 w-1/4 mb-10">
                            item-{ idx + 1 }
                        </div>
                        <div className="flex gap-x-5">
                            <button className="bg-slate-800 px-8 py-3">some</button>
                            <button className="bg-slate-800 px-8 py-3">option</button>
                        </div>
                    </div>
                ))
            }
        </>
    )
}

loading.tsx

TSX
"use client"

interface LoadingProps {
    count: number;
}

export function Loading({ count }: LoadingProps) {
    return (
        <>
            {
                [ ...Array(count) ].map((_, idx) => (
                    <div className="w-full p-5 border border-slate-300 space-y-5"
                         key={ idx }>
                        <div className="bg-gray-400 animate-pulse h-24 w-full mb-10"/>
                        <div className="bg-gray-400 animate-pulse h-5 w-3/4"/>
                        <div className="bg-gray-400 animate-pulse h-5 w-1/2"/>
                        <div className="bg-gray-400 animate-pulse h-5 w-1/4"/>
                        <div className="bg-gray-400 animate-pulse h-5 w-3/4"/>
                        <div className="bg-gray-400 animate-pulse h-5 w-1/4 mb-10"/>
                        <div className="flex gap-x-5">
                            <button className="bg-gray-400 px-10 py-5 animate-pulse"/>
                            <button className="bg-gray-400 px-10 py-5 animate-pulse"/>
                        </div>
                    </div>
                ))
            }
        </>
    )
}

page.tsx

TSX
"use client"

import { Suspense } from "react";
import { Data } from "@/examples/skeleton-ui/data";
import { Loading } from "@/examples/skeleton-ui/loading";
import { getItems } from "@/examples/skeleton-ui/http";

export default function Page() {

    const data = getItems(8, 1000);

    return (
        <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-5">
            <Suspense fallback={ (<Loading count={ 8 }/>) }>
                <Data data={ data }/>
            </Suspense>
        </div>
    )
}

video