Changelog
All notable changes to skeletal-ui are documented here.
Format follows Keep a Changelog (opens in a new tab). Versioning follows Semantic Versioning (opens in a new tab).
0.8.0 (opens in a new tab) — 2026-04-13
Added
- User-configurable sizes and constants — three new optional config namespaces in
skeletal.config.ts:tailwind,classifier, andprimitives. All keys are optional and deep-merged with built-in defaults; existing configs parse without changes. tailwindconfig namespace — overrides the Tailwind font-size/line-height tables used during AST analysis. Keys:fontSizePx,leading,pairedLineHeightPx,spacingUnit,textLengthThreshold. Useful for Tailwind v4 configs, custom theme extensions, or non-standard spacing scales.classifierconfig namespace — overrides geometry thresholds used to classify Playwright-measured DOM elements:lineHeightEstimate,avatarSmallMax,iconMax,avatarMediumMax,badgeMaxHeight,badgeMaxWidth,textSingleLineMaxHeight,textMultiLineMinWidthRatio,imageMinDimension,imageAspectRatioMin,imageAspectRatioMax.primitivesconfig namespace — overrides default prop values for allSk.*components. Affects both codegen (generated files omit props that match the new default) and runtime rendering. Per-component keys:avatar,icon,button,badge,text,heading,image,card,list,defaultPulseSkeleton.SkeletonProvider—primitivesprop — runtime equivalent of theprimitivesconfig namespace. Wraps children with a React context so allSk.*in the subtree pick up overridden defaults without prop drilling.primitives/context.ts— new internal module exportingSkeletalContextanduseSkeletalContext.resolveAstConstants(tailwind?)factory — merges userTailwindConfigwith built-in defaults; returned object threaded through all AST analysis helpers.resolveClassifierThresholds(cfg?)factory — merges userClassifierConfigwith built-in defaults; passed tobuildClassificationRules.buildClassificationRules(thresholds)factory — replaces the staticCLASSIFICATION_RULESarray; rules are now closures reading from thethresholdsparameter.- New exported types:
AstConstants,TailwindConfig,ClassifierConfig,PrimitivesConfig. - Codegen default-elision —
printSkeletonTree/printElementaccept optionalprimitivesConfigand omit props whose value equals the effective default. - 3 new codegen tests — cover default-elision for
Text width="100%",Avatar size={40}/shape="circle", andprimitivesConfig-overridden defaults.
Changed
- All
Sk.*primitives — removed hardcoded default parameter values; props now resolved via three-layer lookup: explicit prop →SkeletonProvidercontext → hardcoded default. classify(geometry, thresholds?)— second parameter added.generateSkeletonBodyFromSource/generateSkeletonBodyWithGeometry— optionalconstants?: AstConstantslast parameter added.generateSkeleton— optionalprimitivesConfig?: PrimitivesConfiglast parameter added.analyzecommand — resolvesastConstantsandclassifierThresholdsfrom config once at startup and threads them to all generation call sites.
0.7.0 (opens in a new tab) — 2026-04-12
Changed
initcommand — full interactive wizard overhaul: replaced minimal 3-question prompt with a fully guided wizard supporting Quick and Advanced modes. Quick mode asks only devServer URL, routes, and animation. Advanced mode additionally prompts for border radius, framework, and Playwright concurrency.init— auto-detects framework and dev server port: readspackage.jsondeps to detectnextjsorvite, and parsesscripts.dev/scripts.startfor--port/-pflags.init— route discovery from disk: scanssrc/app/,app/,src/pages/, orpages/and presents discovered routes as a pre-selected multiselect checklist. App Router strips route groups ((group)segments), preserves dynamic segments ([slug]).init— config preview before write: displays the full generated config and requires explicit confirmation before writingskeletal.config.ts.init—include,exclude,outputalways written: both Quick and Advanced configs now include these fields with their defaults.init— CSR/lazy/dynamic always enabled: removed the multiselect that allowed toggling these patterns off.
Added
detect-project.ts— new pure utility (detectProject(projectRoot): DetectedProject) encapsulating framework detection, dev server URL synthesis, and route discovery.- 21 unit tests for
detectProject: cover framework detection, port extraction, app router discovery, pages router discovery, and no-router fallback.
0.6.0 (opens in a new tab) — 2026-04-10
Changed
- Animation — shimmer → pulse: replaced horizontal gradient sweep with opacity-based pulse (
opacity 1 → 0.4 → 1). Easing:cubic-bezier(0.4, 0, 0.6, 1). Duration increased from1.5sto2s. The--sk-highlightCSS variable has been removed. SkeletonProvider— removedhighlightprop: no longer needed after animation change.color,radius, anddurationremain.- AST generator —
tailwindLeadingMultiplieruses Tailwind paired line-heights: uses built-in font-size/line-height pairs (text-xs→ 16px,text-sm→ 20px, etc.) instead of a hardcoded1.5multiplier. - AST generator —
tailwindLeadingMultiplierreceivesinheritedTextClass: child elements inheriting a parent'stext-*class now also inherit the correct paired line-height.
Fixed
- Layout jump on skeleton ↔ loaded toggle for
<span>elements (AST-only path): caused bylineHeightbeing 18px fortext-xsspans instead of the correct 16px. <p>with short static text emittinglines={2}: AST-only path now resolves paragraph text at analysis time — including property accesses on localas constobjects (e.g.{POST.excerpt}) — and emitslines={1}for text under 80 characters.
0.5.0 (opens in a new tab) — 2026-04-08
Fixed
Sk.Textinvisible inalign-items: centerflex containers:lineHeightpath now placeswidthon the outer<span>instead of the inner bar.<img>withrounded-fullgenerated asSk.Imageinstead ofSk.Avatar:classifyLeafWithGeonow checksisCircularGeoforimgtags.- Gradient hero/banner divs generated as empty or wrong element:
bg-gradient-*divs taller than 40px now emitSk.Imagewith the measured height. - Purely visual child containers silently dropped: containers whose children produce no skeleton output now emit
Sk.Cardinstead of being omitted. dynamicWithSkeleton—require is not definedin browser bundles: replaced dynamicrequire('next/dynamic')with a static ESMimport.
Changed
- AST generator — single-line text width uses pixels: emits absolute pixel widths (e.g.
width="68px") for single-lineSk.Textinstead of percentages.
Added
package.json—homepage,repository,bugs: npm package page now links to the live demo and GitHub repository.
0.2.0 (opens in a new tab) — 2026-04-08
Added
Sk.Text—lineHeightprop: outer container height for single-line text. Eliminates height jump on skeleton ↔ loaded toggle.Sk.Text—gapprop: controls gap between bars in multi-line mode. Analyzer computes this so total skeleton height matches real element exactly.Sk.Heading—heightprop: overrides the fixed1.4emdefault. Analyzer sets this to the element's actual bounding-box height.Sk.Number—outerHeightprop: outer container height for layout stability.- Playwright geometry —
fontSize+lineHeight:extractChildGeometryScriptnow captures computedfontSizeandlineHeightalongsideborderRadiusandaspectRatio. - AST generator — geo-based avatar detection (
isCircularGeo): detects avatars from computedborder-radius(≥ 45% of min dimension or exactly50%). - AST generator — geo-based image detection (
isImageShapedGeo): detects image-shaped containers from computedaspect-ratio. - AST generator —
aspect-*→Sk.Imagerule (AST-only path): mapsaspect-video→aspectRatio="16/9",aspect-square→aspectRatio="1/1". - AST generator — template literal
classNamesupport: extracts static class tokens fromclassName={`...${expr}...`}. - AST generator —
hasOnlyInlineChildren: replaceshasOnlyLeafChildrenwith a broader inline element list. - AST generator — spacing class preservation:
extractSpacingClassesextractsmt-*,mb-*,mx-*, etc. and passes them asclassNameonSk.Text.
Changed
Sk.Textmulti-lineclassName: moved from each inner bar to the outer flex wrapper.- AST generator —
Sk.Textbar height: changed fromlineHeighttofontSize(Playwright-extracted). - AST generator —
Sk.Numberheight: changed from bounding-box height tofontSize.outerHeightpreserves layout. - AST generator —
classifyNodeWithGeoheading: uses bounding-boxhforSk.Heading height.
Fixed
- Height jump when toggling skeleton ↔ loaded for single-line text elements (
lineHeightwrapper). - Height jump for numeric stat blocks (
outerHeightwrapper onSk.Number). - Skeleton overall height taller than real content for multi-line text (gap overflow fixed by explicit
gapprop computation). - Avatar missing from components using template-literal
className. aspect-videoareas generatingSk.Textbars instead ofSk.Image.<p><span>inline patterns generating separateSk.Textper span instead of one bar per paragraph.
0.1.0 (opens in a new tab) — 2026-03-01
Initial release.
Added
- CLI:
init,analyze,check,watch,preview,ejectcommands. - Playwright crawler: bounding-box and
border-radius/aspect-ratiogeometry extraction. - AST scanner: RSC / CSR / lazy / dynamic pattern detection via ts-morph.
- Code generator: co-located
.skeleton.tsxoutput withSk.*primitives. - Codemod: auto-wires
fallbackprop andlazyWithSkeleton/dynamicWithSkeletonreplacements. - Primitives:
Sk.Text,Sk.Heading,Sk.Avatar,Sk.Image,Sk.Button,Sk.Badge,Sk.Number,Sk.Icon,Sk.List,Sk.Card. SkeletonWrapper,SkeletonProvider,DefaultPulseSkeleton.lazyWithSkeleton(runtime),dynamicWithSkeleton(Next.js), Vite plugin.- CSS-only pulse animation with
prefers-reduced-motionsupport. - AST hash staleness detection (
skeletal:hashheader comment). skeletal.config.tswithdefineConfig()and Zod schema validation.