Skip to content

Skeleton

A pulsing placeholder block for cards, avatars, and tables while data loads — with the neobrutalist thick-border treatment.

import { Skeleton } from "@/components/ui/skeleton"

export function SkeletonDemo() {

The skeleton is a pulsing placeholder that holds a piece of UI's shape while its data loads. It's a single div — no primitive underneath — with animate-pulse, a muted background, and the neobrutalist recipe's thick border.

Reach for it when:

  • Cards and lists — mirror the final layout so content pops in without a shift.
  • Avatars and media — reserve the circle or thumbnail box before the image arrives.
  • Tables and forms — keep rows and fields in place during a slow fetch.

Installation

pnpm dlx shadcn@latest add https://neobrutalism.com/r/base/skeleton.json
npx shadcn@latest add https://neobrutalism.com/r/base/skeleton.json
yarn dlx shadcn@latest add https://neobrutalism.com/r/base/skeleton.json
bunx --bun shadcn@latest add https://neobrutalism.com/r/base/skeleton.json

Copy and paste the following code into your project.

components/ui/skeleton.tsx
import { cn } from "@/lib/utils"

function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
  return (
    <div
      data-slot="skeleton"
      className={cn("animate-pulse rounded border-2 bg-muted", className)}
      {...props}
    />
  )
}

export { Skeleton }

Update the import paths to match your project setup.

Usage

import { Skeleton } from "@/components/ui/skeleton"
<Skeleton className="h-[20px] w-[100px] rounded-full" />

Examples

Avatar

import { Skeleton } from "@/components/ui/skeleton"

export function SkeletonAvatar() {

Card

import { Card, CardContent, CardHeader } from "@/components/ui/card"
import { Skeleton } from "@/components/ui/skeleton"

Text

import { Skeleton } from "@/components/ui/skeleton"

export function SkeletonText() {

Form

import { Skeleton } from "@/components/ui/skeleton"

export function SkeletonForm() {

Table

import { Skeleton } from "@/components/ui/skeleton"

export function SkeletonTable() {

RTL

To enable RTL support in Neobrutalism.com, see the RTL configuration guide.

"use client"

import * as React from "react"

Accessibility

Skeletons are decorative — hide them from assistive tech with aria-hidden="true" so screen readers don't announce empty pulsing boxes. Convey the loading state itself separately: set aria-busy="true" on the region being loaded, or update a visually hidden live region ("Loading results…") that clears when content lands. Once the real content renders, remove the skeletons from the DOM entirely.