Kosmesis
Components

Skeleton

A pulsing placeholder for loading content. Purely presentational.

Installation

npx kosmesis add skeleton
pnpm dlx kosmesis add skeleton
yarn dlx kosmesis add skeleton
bunx kosmesis add skeleton

Copy and paste the following code into your project.

skeleton.tsx
import { StatelessComponent } from "@praxisjs/core";import { Component } from "@praxisjs/decorators";import { cn } from "@/lib/utils";export interface SkeletonProps {  class?: string;  id?: string;}/** Purely presentational — no Morphos equivalent, same as upstream shadcn/ui. */@Component()export class Skeleton extends StatelessComponent<SkeletonProps> {  render() {    const { class: cls, id } = this.props;    return <div id={id} data-slot="skeleton" class={cn("animate-pulse rounded-md bg-accent", cls)} />;  }}

Install the following dependencies:

npm install @praxisjs/css
pnpm add @praxisjs/css
yarn add @praxisjs/css
bun add @praxisjs/css

Copy and paste the following code into your project.

skeleton.tsx
import { StatelessComponent } from "@praxisjs/core";import { cx, keyframes, Stylesheet, Styled, tokenVars } from "@praxisjs/css";import { Component } from "@praxisjs/decorators";import { KosmesisTokens } from "@/lib/kosmesis-theme";const t = tokenVars(KosmesisTokens);/** `keyframes()` is content-hash-deduplicated, so calling this with the same definition in more than one file (see `spinner.tsx`) still injects a single shared `@keyframes` rule. */const pulse = keyframes("kosmesis-pulse", { "0%, 100%": { opacity: "1" }, "50%": { opacity: "0.5" } });class SkeletonStyles extends Stylesheet {  $root = this.css({    borderRadius: `calc(${t.radius} - 2px)`,    backgroundColor: t.accent,    animation: `${pulse} 2s cubic-bezier(0.4, 0, 0.6, 1) infinite`,  });}export interface SkeletonProps {  class?: string;  id?: string;}/** Purely presentational — no Morphos equivalent, same as upstream shadcn/ui. */@Component()export class Skeleton extends StatelessComponent<SkeletonProps> {  @Styled(SkeletonStyles) $s!: SkeletonStyles;  render() {    const { class: cls, id } = this.props;    return <div id={id} data-slot="skeleton" class={cx(this.$s.$root, cls)} />;  }}

Examples

Usage

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

<div class="flex items-center gap-4">
  <Skeleton class="size-12 rounded-full" />
  <div class="flex flex-col gap-2">
    <Skeleton class="h-4 w-48" />
    <Skeleton class="h-4 w-32" />
  </div>
</div>

On this page