Introduction
bwo-ui is a GSAP-powered motion and UI library for React, Vue, and Svelte. One core, three framework wrappers, beautifully designed accessible components — themed with a few CSS variables and shipped as a real npm install.
This is not just an animation library. It is also a real UI kit.
Most motion libraries leave you to glue together your own buttons, inputs, and cards. Most UI libraries treat motion as an afterthought — a fade here, a hover there. The result is a frontend made of mismatched parts, where the animation system and the component system never quite agree on tokens, ergonomics, or accessibility.
bwo-ui is built so that the motion primitives (SplitReveal, Magnetic, Tilt, Marquee…) and the UI primitives (Button, Input, Select, Dialog…) come from the same design language — same theme tokens, same radius scale, same framework wrappers. It is built around the following principles:
- One Core, Three Frameworks: every animation lives once as a vanilla TS factory in
@bwo-ui/core, with thin React, Vue, and Svelte wrappers. - Motion as Primitives: scroll reveals, magnetic buttons, tilts, and marquees are first-class components — not hooks you have to wire up yourself.
- Themable by CSS Variables: override
--bwo-accent,--bwo-radius-current, and friends. No Tailwind plugin or theming context required. - Light by Default: ~7 KB gzipped for the entire library.
sideEffects: falsemeans you only ship what you import. GSAP is a peer dependency, so you do not double-bundle it. - Composable & Predictable: every interactive primitive is built from scratch with accessibility, focus management, and keyboard handling baked in — no external UI library underneath.
One Core, Three Frameworks
Every effect — SplitReveal, Magnetic, Tilt, Marquee, FlipList — is implemented exactly once, as a framework-agnostic GSAP factory in @bwo-ui/core. The React, Vue, and Svelte packages are thin wrappers that mount the factory against a ref, action, or template ref. This means:
- No framework drift: the React tilt and the Svelte tilt are the exact same animation; the wrapper is the only thing that changes.
- One bug fix, three frameworks: a change in the GSAP factory ships to every package on the next build.
- SSR-safe: every factory short-circuits when
windowis undefined.
Motion as Primitives
Animation is not bolted on. The motion components are part of the same import surface as Button and Input:
import { SplitReveal, Magnetic, Button } from '@bwo-ui/react';
<SplitReveal as="h1" type="words" stagger={0.04}>
The shortcut to beautiful UI.
</SplitReveal>
<Magnetic strength={0.4}>
<Button>Get started</Button>
</Magnetic>Effects share the same options shape (durations, easings, scroll triggers) so the cognitive surface across the library stays small.
Themable by CSS Variables
Every visual decision is exposed as a CSS variable on :root — colors, radii, shadows, fonts, transitions. Override them in your own stylesheet to rebrand the whole library:
:root {
--bwo-accent: #6c5ce7; /* swap the accent color */
--bwo-radius-current: 12px; /* round everything more */
--bwo-font-sans: 'JetBrains Mono', monospace;
}Per-instance overrides also exist where they matter most. For example, the radius prop on Button, Input, Card, and friends switches between none / sm / md / lg / pill on the fly.
Light by Default
The whole library — every motion effect plus every UI primitive — is about 7 KB gzipped at the published level. Because sideEffects: false is set on the packages, a bundler ships only the components you actually import. A page that uses one SplitReveal pays for one SplitReveal, not for the rest of the catalog.
GSAP itself stays a peer dependency. Projects that already use GSAP do not double-bundle it; projects that do not use GSAP still install it once and stay in control of the version.
Composable & Predictable
Every interactive primitive is written from scratch on a shared in-house stack (Portal, Presence, useDismiss, useFocusTrap, useScrollLock, floating positioning). You get accessibility (focus traps, escape handlers, ARIA wiring, keyboard navigation, SR-friendly markup) plus a visual layer that is entirely ours, themed with --bwo-* variables. Select, Dialog, Tooltip, Popover, and Toast behave consistently across every framework wrapper.
Ready to install?
Head over to Installation to add bwo-ui to your project, or jump straight to Button and SplitReveal to see the components in action.