Skeleton
AtomAnimated placeholder shown before content loads. Uses animate-pulse bg-surface-sunken. aria-busy="true" ensures accessibility.
<%- include('modules/ui/Skeleton', { variant: 'line', width: 'w-full' }) %>
<%- include('modules/ui/Skeleton', { variant: 'line', width: 'w-3/4' }) %>
<%- include('modules/ui/Skeleton', { variant: 'line', width: 'w-1/2' }) %>
<%- include('modules/ui/Skeleton', { variant: 'text', lines: 4 }) %>
<%- include('modules/ui/Skeleton', { variant: 'card' }) %>
<%- include('modules/ui/Skeleton', { variant: 'tableRow', cols: 4 }) %>
<%- include('modules/ui/Skeleton', { variant: 'tableRow', cols: 4 }) %>
<%- include('modules/ui/Skeleton', { variant: 'tableRow', cols: 4 }) %>
<%# Stat cards + table skeleton %>
<% for (var i = 0; i < 3; i++) { %>
<%- include('modules/ui/Skeleton', { variant: 'line', width: 'w-1/2' }) %>
<%- include('modules/ui/Skeleton', { variant: 'line', width: 'w-3/4' }) %>
<%- include('modules/ui/Skeleton', { variant: 'line', width: 'w-1/3' }) %>
<% } %>
<%- include('modules/ui/Skeleton', { variant: 'tableRow', cols: 4 }) %>
<%# Blog post / article skeleton %>
<%- include('modules/ui/Skeleton', { variant: 'line', width: 'w-1/4' }) %>
<%- include('modules/ui/Skeleton', { variant: 'line', width: 'w-full' }) %>
<%- include('modules/ui/Skeleton', { variant: 'line', width: 'w-3/4' }) %>
<%- include('modules/ui/Skeleton', { variant: 'avatar', size: 'sm' }) %>
<%- include('modules/ui/Skeleton', { variant: 'line', width: 'w-24' }) %>
<%- include('modules/ui/Skeleton', { variant: 'text', lines: 4 }) %>
<%
var _variant = locals.variant || 'line';
var _className = locals.className || '';
var _width = locals.width || 'w-full';
var _size = locals.size || 'md';
var _lines = (typeof locals.lines === 'number') ? locals.lines : 3;
var _cols = (typeof locals.cols === 'number') ? locals.cols : 4;
var base = 'animate-pulse bg-surface-sunken';
var avatarSize = {
sm: 'h-8 w-8',
md: 'h-10 w-10',
lg: 'h-12 w-12',
}[_size] || 'h-10 w-10';
var colWidths = ['w-28', 'w-40', 'w-20', 'w-16'];
%>
<% if (_variant === 'line') { %>
<% } else if (_variant === 'avatar') { %>
<% } else if (_variant === 'text') { %>
<% for (var i = 0; i < _lines; i++) { %>
<% } %>
<% } else if (_variant === 'card') { %>
<% } else if (_variant === 'tableRow') { %>
<% for (var j = 0; j < _cols; j++) { %>
<% } %>
<% } %>