Part 1 of the Motion System shipped in v3.4.2. This closes the gaps: the stepped, hard-edged motion language now covers waiting states, shapes, and page transitions — React and Vue.
Every new variant defaults to the pre-v3.5 behaviour, so this release is non-breaking. Existing code looks exactly the same until you opt in.
🩻 Brutalist loading states
Loading is the most-seen state in any app and the easiest to leave generic. Now it's on-brand.
<Skeleton variant="stamp" /> {/* hard on/off, no interpolated fade */}
<Skeleton variant="blocks" /> {/* marching cells on a stepped loop */}
<Skeleton variant="scan" /> {/* a hard bar sweeping the block */}
<Progress value={60} variant="stepped" /> {/* ten discrete notches */}
<Progress variant="marquee" aria-label="Loading" /> {/* indeterminate */}
<ChartContainer config={config} loading>{/* chart-shaped placeholder */}</ChartContainer>pulse and smooth remain the defaults.
⬡ Stepped shape presets
Three new presets join the six smooth ones, each at three speeds — genuinely stepped, not eased:
<GearShape animation="spin-step" /> {/* rotates in 8 visible clicks */}
<BurstShape animation="pulse-hard" /> {/* no interpolation at all */}
<FlagShape animation="marquee-stamp" />🎬 Page transition recipes
Three named View Transition recipes. Set the attribute, call the helper, the CSS does the rest:
document.documentElement.dataset.bkTransition = 'hard-wipe' // | 'color-block' | 'stamp'
startViewTransition(() => navigate('/next'))Browsers without View Transitions fall back to an instant swap.
🐛 Fixes uncovered while building this
Several of these were shipping broken well before v3.5:
- The React
shapesregistry shipped no animation CSS at all — none of the 18.shape-animate-*rules orshape-*keyframes. Theanimationprop was inert for every React consumer. - The React registry and Vue
globals.csscarried 2 of the 15--bk-*tokens. Progressnever exposedaria-valuenow—valuewas destructured out and never reached Radix. Now clamped and forwarded; an omitted value stays indeterminate.- Installed charts had no accessible name — the registry
ChartContaineraccepted neitheraria-labelnoraria-labelledbyand set no role. skeleton/progress/shapes/chartnow declare the motion stylesheet as a registry dependency, so the CSS actually arrives with the component.
♿ Accessibility
Every new animation has a prefers-reduced-motion fallback, verified against the live CSSOM in both the React and Vue apps rather than by eye.
✅ Verification
- React 590 tests, Vue 59 tests
- 36 axe fixtures (12 new for v3.5), 0 violations
- Full build incl. prerender: 131/131 routes
registry:audit: React 0 / Vue 0
📦 Install
npx shadcn@latest add "https://boldkit.dev/r/skeleton.json"
npx shadcn-vue@latest add "https://boldkit.dev/r/vue/skeleton.json"Versions: boldkit-site 3.5.0 · @boldkit/vue 3.3.0
Full changelog: v3.4.9...v3.5.0