Skip to content

v3.5.0 — Motion System, Part 2

Latest

Choose a tag to compare

@ANIBIT14 ANIBIT14 released this 04 Aug 14:28

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 shapes registry shipped no animation CSS at all — none of the 18 .shape-animate-* rules or shape-* keyframes. The animation prop was inert for every React consumer.
  • The React registry and Vue globals.css carried 2 of the 15 --bk-* tokens.
  • Progress never exposed aria-valuenowvalue was destructured out and never reached Radix. Now clamped and forwarded; an omitted value stays indeterminate.
  • Installed charts had no accessible name — the registry ChartContainer accepted neither aria-label nor aria-labelledby and set no role.
  • skeleton / progress / shapes / chart now 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