Skeleton
Animated placeholder for content that's loading. Pulse or shimmer animation, multiple shapes.
Overview
The Skeleton component is a core building block of the Byteion design system, providing a robust, accessibility-compliant interface for its specific UI capabilities.
Why this exists
Skeletons are perceived as faster than spinners because they show the layout structure before content arrives. They reduce perceived wait time.
Mental model
A skeleton is a loading placeholder that matches the shape of the final content. Use it for cards, tables, and text blocks.
When to use
When not to use
Basic example
The following example demonstrates standard usage, fully compliant with Byteion's token-first approach.
Text lines
Shimmer
Avatar + name
Card
List rows
Table rows
| Name | Role | Status |
|---|---|---|
Shapes
import { Skeleton } from '@byteion/react';
export default function SkeletonDemo() {
return (
<div className="max-w-sm space-y-3 p-6">
<Skeleton className="h-32 w-full rounded-xl" />
<Skeleton className="h-4 w-3/4" />
<Skeleton className="h-4 w-1/2" />
<div className="flex items-center gap-3 pt-2">
<Skeleton className="h-10 w-10 rounded-full" />
<Skeleton className="h-4 w-32" />
</div>
</div>
);
}
<script setup lang="ts">
import { Skeleton } from '@byteion/vue';
</script>
<template>
<div class="max-w-sm space-y-3 p-6">
<Skeleton class="h-32 w-full rounded-xl" />
<Skeleton class="h-4 w-3/4" />
<Skeleton class="h-4 w-1/2" />
<div class="flex items-center gap-3 pt-2">
<Skeleton class="h-10 w-10 rounded-full" />
<Skeleton class="h-4 w-32" />
</div>
</div>
</template>
Variants
Each variant communicates a different meaning. Choose based on priority, not aesthetics.
Single default variant.
Sizes
Size should match the importance and context of the component.
- md — md size.
States
This component reacts seamlessly to the following interaction and data states:
- loading — Action in progress — spinner replaces icon, button is disabled.
- default — Resting appearance before interaction.
- hover — Pointer is over the element — visual feedback via color or shadow.
- focus — Keyboard or tab focus — shows ring indicator for accessibility.
- active — Currently selected or in use.
- disabled — Non-interactive — grayed out, cursor not-allowed.
Anatomy
Usage guidelines
- Match the shape of the loaded content.
- Use shimmer animation.
- Keep dimensions identical to final content.
Do and Don't
Do
- Match loaded layout shape.
- Use shimmer animation.
- Keep identical dimensions.
Don't
- Do not use random shapes.
- Do not animate excessively.
- Do not use for instant loads.
Accessibility
Wrap with aria-busy="true" and aria-label="Loading". Hide from screen readers when loaded.
Role:status
Customization
Color uses muted background with shimmer animation.
Compose with React cva()
Use the exportedcva() +cn() utilities to compose your own variant on top of the Byteion tokens.
import { cva, cn, type VariantProps } from '@byteion/react';
const mySkeleton = cva('base classes…', {
variants: {
accent: { soft:'border-primary-200', loud:'border-primary-500' },
},
defaultVariants: { accent:'soft' },
});
type Props = React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof mySkeleton>;
Compose with Vue cva()
Use the exportedcva() +cn() utilities inside standard Vue setup blocks.
<script setup lang="ts">
import { computed, useAttrs } from 'vue';
import { cva, type VariantProps } from '@byteion/vue';
interface Props { accent?:'soft' |'loud' }
const props = withDefaults(defineProps<Props>(), { accent:'soft' });
const attrs = useAttrs();
const mySkeleton = cva('base classes…', {
variants: { accent: { soft:'border-primary-200', loud:'border-primary-500' } },
});
const cls = computed(() => mySkeleton({ accent: props.accent, class: attrs.class as string | undefined }));
</script>
Runtime events
Byteion keeps framework APIs idiomatic: HTML uses DOM custom events, React uses callback props, and Vue uses emitted events / v-model updates.
HTML / JS events
No HTML runtime events are declared by this adapter.
React callbacks
No React callback events are declared by this adapter.
Vue emits
No Vue emitted events are declared by this adapter.
Remote / AJAX
This component does not implement Byteion JS remote loading. Use normal HTML form submission, framework state, or your application data layer around it.
API Reference
Static HTML. Remove when content is loaded.
HTML Data Attributes
No custom data attributes required.
React Props · SkeletonProps
Extracted directly fromreact/src/components/Skeleton.tsx.
export interface SkeletonProps
extends Omit<HTMLAttributes<HTMLDivElement>, 'children'>,
VariantProps<typeof skeleton> {
/** Tailwind width utility (or CSS width via style). Default `w-full`. */
width?: string;
/** Tailwind height utility (or CSS height via style). Default `h-3`. */
height?: string;
}
React Variant Schema
Internal variant composition defined viacva().
cva('bg-muted', {
variants: {
rounded: {
none: 'rounded-none',
sm: 'rounded',
md: 'rounded-md',
lg: 'rounded-lg',
xl: 'rounded-xl',
full: 'rounded-full',
},
animation: {
pulse: 'motion-safe:animate-pulse-soft',
shimmer: 'bg-shimmer motion-safe:animate-shimmer dark:bg-shimmer-dark',
none: '',
},
},
defaultVariants: { rounded: 'sm', animation: 'pulse' },
})
Vue Props · SkeletonProps
Extracted directly fromvue/src/components/Skeleton.vue.
export interface SkeletonProps {
rounded?: 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
animation?: 'pulse' | 'shimmer' | 'none';
/** Tailwind width utility (or CSS width via style). Default `w-full`. */
width?: string;
/** Tailwind height utility (or CSS height via style). Default `h-3`. */
height?: string;
}
Developer tips
Common mistakes
Production usage tips
data-bi-* attributes instead of styling hooks.
Premium examples
Advanced patterns available in Byteion Pro:
Related components
Unlock Premium Patterns
Get access to copy-paste ready Pro blocks, SaaS templates, and advanced data-tables built with this component.
Explore Pro Components