JSPM

@dg-ui-react/react

0.5.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 26
  • Score
    100M100P100Q66911F
  • License MIT

Damn Good UI — production-ready React component library

Package Exports

  • @dg-ui-react/react
  • @dg-ui-react/react/aurora
  • @dg-ui-react/react/bio-organic
  • @dg-ui-react/react/cinder
  • @dg-ui-react/react/corporate
  • @dg-ui-react/react/dusk
  • @dg-ui-react/react/fluid
  • @dg-ui-react/react/forge
  • @dg-ui-react/react/glass
  • @dg-ui-react/react/memphis
  • @dg-ui-react/react/mobile
  • @dg-ui-react/react/motion
  • @dg-ui-react/react/neon
  • @dg-ui-react/react/obsidian
  • @dg-ui-react/react/retro
  • @dg-ui-react/react/scholar
  • @dg-ui-react/react/styles.css
  • @dg-ui-react/react/vapor

Readme

@dg-ui-react/react

April 2026 — Hey everyone — the package is fully usable right now, the components work great and the DG Motion engine is solid, but I want to be upfront: things are moving fast. I'm pushing dozens of commits every single day — new themes, a completely custom animation engine that replaces framer-motion and GSAP, physics, text animation, SVG morphing, and a lot more. If something looks different between versions that's why. Stick around — what's coming is worth the wait. Thanks for checking it out. — AahPlexX

Damn Good UI — A production-ready React component library with 15 design themes, 1,478+ component exports, and a built-in zero-dependency motion system.

npm version license TypeScript React Tailwind CSS

Built with TypeScript 6 and Tailwind CSS v4. No external animation dependencies — all motion is powered by the built-in DG Motion engine.


Preview

DG-UI Showcase — 15 design themes, 1,478+ components

Live showcase and documentation: dg-ui.com


Quick Start

npm install @dg-ui-react/react
// 1. Import the stylesheet once at your app root
import '@dg-ui-react/react/styles.css';

// 2. Import components from any theme
import { Button, Card, Input } from '@dg-ui-react/react/obsidian';

// 3. Use them
export default function App() {
  return (
    <Card>
      <Input placeholder="Enter your name" />
      <Button variant="primary">Submit</Button>
    </Card>
  );
}

No Tailwind configuration required — the library ships a single pre-compiled CSS file.


Installation

# npm
npm install @dg-ui-react/react

# pnpm
pnpm add @dg-ui-react/react

# yarn
yarn add @dg-ui-react/react

# bun
bun add @dg-ui-react/react

Peer Dependencies

Package Required Version
react >= 19.0.0
react-dom >= 19.0.0

No animation peer dependency required. DG Motion ships bundled and zero-dependency.

Setup

Import the stylesheet once at the root of your application:

// app root (e.g. main.tsx, _app.tsx, layout.tsx)
import '@dg-ui-react/react/styles.css';

No Tailwind config, no PostCSS plugins, no build-step changes.


Themes

DG-UI ships 15 distinct design themes, each published as its own tree-shakeable subpath entry point. Every theme provides a complete, internally-consistent component set with full TypeScript declarations.

Theme Import Path Components Design Language
Obsidian @dg-ui-react/react/obsidian 127 Dark developer-tools aesthetic — command palettes, data tables, code blocks, and full dashboard primitives
Aurora @dg-ui-react/react/aurora 133 Light SaaS-clean — pricing cards, avatar stacks, notification bells, and product-marketing surfaces
Forge @dg-ui-react/react/forge 130 Dark industrial warmth — gradient buttons, metric cards, and data-heavy analytics admin surfaces
Mobile @dg-ui-react/react/mobile 129 Touch-first native feel — bottom sheets, swipe actions, and mobile interaction patterns
Neon @dg-ui-react/react/neon 106 Cyberpunk glow — vivid green accents on dark backgrounds with glowing borders
Vapor @dg-ui-react/react/vapor 119 Glassmorphic ethereal — translucent frosted-glass surfaces with layered purple depth
Fluid @dg-ui-react/react/fluid 149 Motion-first declarative — 149 interactive components built on a unified animation primitive
Retro 70s @dg-ui-react/react/retro 147 Disco-era warmth — amber and earth-tone palette, sunset and earth modes, organic card surfaces
Cinder @dg-ui-react/react/cinder 126 Warm ember-toned dark — amber and rust accent palette for atmospheric dashboards
Dusk @dg-ui-react/react/dusk 126 Twilight enterprise — muted teal and blue-grey for professional presentation surfaces
Scholar @dg-ui-react/react/scholar 135 Education-focused — quiz cards, flashcard decks, lesson planners, grade displays, and 101 standard UI components
Corporate @dg-ui-react/react/corporate 21 Enterprise professional — clean, precise components for business applications
Glass @dg-ui-react/react/glass 10 Frosted glass surfaces — backdrop blur, translucent panels, and glassy depth
Memphis @dg-ui-react/react/memphis 10 80s geometric pop — bold black shadows, pastel fills, and playful asymmetry
Bio-Organic @dg-ui-react/react/bio-organic 50 Bioluminescent living UI — organic shapes, pulsing glows, and flowing forms

Motion System is also published at @dg-ui-react/react/motion — see the Motion System section below.


Import Patterns

DG-UI supports three import patterns.

Best tree-shaking, unambiguous component origin. The recommended approach for production applications.

import { Button, Input, Card } from '@dg-ui-react/react/obsidian';
import { PricingCard, Badge } from '@dg-ui-react/react/aurora';
import { MetricCard } from '@dg-ui-react/react/forge';
import { QuizCard, FlashcardDeck } from '@dg-ui-react/react/scholar';
import { Button } from '@dg-ui-react/react/retro';

// TypeScript types
import type { ButtonProps, InputProps } from '@dg-ui-react/react/obsidian';

Pattern 2: Namespace Imports

For multi-theme applications where the same component name appears across themes.

import { Obsidian, Aurora, Scholar, Neon, Retro } from '@dg-ui-react/react';

<Obsidian.Button variant="primary">Dashboard</Obsidian.Button>
<Aurora.PricingCard tier={tier} />
<Scholar.QuizCard questions={questions} />
<Neon.Card>Cyberpunk content</Neon.Card>
<Retro.Button palette="sunset">Retro action</Retro.Button>

All 15 themes are available as namespaces: Obsidian, Aurora, Forge, Mobile, Neon, Vapor, Fluid, Retro, Cinder, Dusk, Scholar, Corporate, Glass, Memphis, BioOrganic.

Pattern 3: Motion Subpath Imports

import {
  Motion,
  MotionProvider,
  useMotionPreset,
  useGesture,
  useDrag,
  useScrollTrigger,
  useTimeline,
} from '@dg-ui-react/react/motion';

The root package @dg-ui-react/react exports theme namespaces, cn, and DgMotion. Flat component imports from the root are not supported — use subpath or namespace imports.

What Not to Do

// Wrong — components are not exported flat from the root
import { Button, Card } from '@dg-ui-react/react';

// Correct
import { Button } from '@dg-ui-react/react/obsidian';
// or
import { Obsidian } from '@dg-ui-react/react';
<Obsidian.Button />

Motion System

DG Motion is a zero-dependency animation engine built directly into @dg-ui-react/react. It is available at @dg-ui-react/react/motion and covers the full spectrum from declarative components to imperative timelines, physics, text animation, SVG morphing, scroll-linked animation, and a first-party Tailwind CSS plugin — all with automatic prefers-reduced-motion support.

No external dependencies. DG Motion replaces framer-motion, GSAP, tailwindcss-animate, and tailwindcss-motion with a unified, bundled-in engine.

Declarative Animation

import { Motion, MotionPresence, MotionProvider } from '@dg-ui-react/react/motion';

// Wrap any content with a preset animation
<Motion preset="fadeInUp" duration="normal">
  <Card>Animated content</Card>
</Motion>

// Animate enter/exit with presence detection
<MotionPresence>
  {isVisible && (
    <Motion preset="scaleIn">
      <Dialog>Modal content</Dialog>
    </Motion>
  )}
</MotionPresence>

// Stagger children
<StaggerContainer staggerDelay={0.05}>
  {items.map(item => (
    <StaggerItem key={item.id} preset="fadeInUp">
      <ListItem>{item.name}</ListItem>
    </StaggerItem>
  ))}
</StaggerContainer>

Imperative Animation & Timelines

import { animate, timeline, useAnimate } from '@dg-ui-react/react/motion';

// Tween any element imperatively
animate('#hero', { opacity: 1, y: 0 }, { duration: 0.4, ease: 'easeOut' });

// Animate with a Promise
await animate(ref.current, { x: 200 }, { duration: 0.3 });

// Build a timeline with relative positions
const tl = timeline();
tl.to('#backdrop', { opacity: 1 }, 0)
  .to('#panel', { y: 0 }, '+=0.05')
  .to('#content', { opacity: 1 }, '<0.1')
  .play();

// Scoped imperative hook (auto-cleans up on unmount)
function MyComponent() {
  const [scope, animate] = useAnimate();
  return (
    <div ref={scope}>
      <button onClick={() => animate('li', { opacity: 1, x: 0 }, { stagger: 0.05 })}>
        Reveal items
      </button>
    </div>
  );
}

Motion Values & Transforms

import {
  useMotionValue, useTransform, useSpring,
  useVelocity, useTime,
} from '@dg-ui-react/react/motion';

const x = useMotionValue(0);
const rotate = useTransform(x, [-200, 200], [-15, 15]);
const opacity = useTransform(x, [-200, 0, 200], [0.5, 1, 0.5]);
const smoothX = useSpring(x, { stiffness: 300, damping: 30 });
const xVelocity = useVelocity(x);
const time = useTime(); // elapsed ms as MotionValue

Scroll-Linked Animation

import { useScrollTrigger, useScrollMotion, useInViewMotion } from '@dg-ui-react/react/motion';

// Scrub a timeline to scroll position
useScrollTrigger({
  trigger: '#section',
  start: 'top 80%',
  end: 'bottom 20%',
  scrub: true,
  onEnter: () => tl.play(),
  onLeaveBack: () => tl.reverse(),
});

// Parallax
function ParallaxHero() {
  const { scrollProgress } = useScrollMotion();
  const y = useTransform(scrollProgress, [0, 1], [0, -200]);
  return <motion.div style={{ y }}>Parallax content</motion.div>;
}

// Viewport detection
function FadeInSection() {
  const { ref, inView } = useInViewMotion({ once: true, margin: '-15%' });
  return (
    <motion.div ref={ref} animate={inView ? { opacity: 1 } : { opacity: 0 }}>
      Appears on scroll
    </motion.div>
  );
}

Gesture System

import { useGesture, useDrag, useDragControls } from '@dg-ui-react/react/motion';

// Preset gestures (button, card, listItem)
const gesture = useGesture('button');
<motion.button {...gesture}>Click me</motion.button>

// Full drag with bounds, snap, and momentum
const drag = useDrag({
  drag: 'x',
  dragConstraints: { left: -200, right: 200 },
  dragElastic: 0.2,
  dragMomentum: true,
  onDragEnd: (_, info) => {
    if (info.offset.x > 100) handleSwipeRight();
  },
});

// Long-press, double-tap, pinch, swipe
const swipe = useGesture({
  onSwipe: ({ direction }) => navigate(direction),
  onLongPress: () => openContextMenu(),
  onPinch: ({ scale }) => setZoom(scale),
});

Layout Animation

import { useLayoutAnimation, useSharedLayout, LayoutGroup } from '@dg-ui-react/react/motion';

// FLIP-based smooth layout transition
function ExpandableCard({ expanded }) {
  const layout = useLayoutAnimation();
  return (
    <motion.div {...layout} className={expanded ? 'h-64' : 'h-16'}>
      {expanded && <p>Details...</p>}
    </motion.div>
  );
}

// Shared element transitions across components
<LayoutGroup>
  <Tab layoutId="underline" /> {/* smoothly animates between tab positions */}
</LayoutGroup>

Text Animation

import { TextMotion, useTextSplit } from '@dg-ui-react/react/motion';

// 30+ built-in text effects
<TextMotion effect="typewriter" speed={0.04}>Hello World</TextMotion>
<TextMotion effect="scramble" duration={0.8}>Loading…</TextMotion>
<TextMotion effect="wave" stagger={0.03}>Wave text</TextMotion>

// Manual split + animate
const { chars, words } = useTextSplit('#heading');
animate(chars, { y: [20, 0], opacity: [0, 1] }, { stagger: 0.02 });

SVG Animation

import { useSVGMorph, usePathDraw, useFollowPath } from '@dg-ui-react/react/motion';

// Shape morphing
const morph = useSVGMorph({ from: '#shape-a', to: '#shape-b' });
morph.play();

// Path drawing (DrawSVG equivalent, free)
const draw = usePathDraw({ pathLength: 0 });
animate(draw.ref.current, { pathLength: 1 }, { duration: 1.5, ease: 'easeInOut' });

// Follow a path with auto-rotate
useFollowPath({ path: '#track', target: '#car', rotate: true });

Physics Engine

import { useGravity, useMagnetic, useParticleEmitter } from '@dg-ui-react/react/motion';

// Gravity with floor bounce
useGravity({ targets: '.ball', floor: 400, bounce: 0.7 });

// Magnetic attraction on hover
useMagnetic({ target: '#btn', strength: 0.4, falloff: 'quadratic' });

// Particle presets: confetti, snow, sparks, smoke, rain, fireflies
const emitter = useParticleEmitter({
  preset: 'confetti',
  count: 200,
  origin: { x: 0.5, y: 0 },
});
emitter.fire();

Tailwind CSS Plugin

DG Motion ships a first-party Tailwind plugin that replaces tailwindcss-animate and tailwindcss-motion with a superset of their combined features:

// tailwind.config.js
import { dgMotionPlugin } from '@dg-ui-react/react/motion';

export default {
  plugins: [dgMotionPlugin()],
};
<!-- 100% tailwindcss-animate compat -->
<div class="animate-in fade-in slide-in-from-top duration-300">...</div>

<!-- 100% tailwindcss-motion (Rombo) compat -->
<div class="motion-preset-fade motion-duration-300">...</div>

<!-- DG-exclusive: stagger children with CSS only -->
<ul class="motion-stagger-50">
  <li class="motion-preset-slide-up">Item 1</li>
  <li class="motion-preset-slide-up">Item 2</li>
</ul>

<!-- Scroll-triggered (CSS-only, no JS) -->
<div class="motion-on-scroll motion-preset-fade">Appears on scroll</div>

<!-- Reduced-motion safe -->
<div class="motion-reduced-safe motion-preset-bounce">...</div>

Performance Budgets & DevTools

import { MotionProvider, DevTools } from '@dg-ui-react/react/motion';

// Three performance tiers
<MotionProvider config={{ budget: 'full' }}>        {/* Default */}
<MotionProvider config={{ budget: 'performance' }}> {/* Reduces complex physics */}
<MotionProvider config={{ budget: 'minimal' }}>     {/* CSS fallbacks only */}

// In-app FPS monitor + timeline scrubber
<DevTools /> {/* add anywhere in the tree */}

18 Motion Presets

Preset Effect
fadeIn Opacity 0 → 1
fadeInUp Fade + translate up
fadeInDown Fade + translate down
fadeInLeft Fade + translate from left
fadeInRight Fade + translate from right
scaleIn Fade + scale from 0.95
scaleInUp Fade + scale + translate up
popIn Fade + scale from 0.9 (more pronounced)
slideInLeft Slide from -100% X
slideInRight Slide from +100% X
slideInUp Slide from +100% Y
slideInDown Slide from -100% Y
expand Height 0 → auto + fade
collapse Height auto → 0 + fade
reveal Fade + subtle scale + translate
dismiss Exit: fade + slide right + scale down
highlight Attention pulse (scale 1 → 1.03 → 1)
none Identity preset — no animation, for conditional toggling

Design Tokens

Durations:

Token Seconds Use Case
instant 0 Reduced-motion fallback
fast 0.12 Menus, dropdowns, tooltips
normal 0.2 Modals, backdrops, most transitions
moderate 0.3 Accordions, reveals, expansions
slow 0.45 Page-level animations
slower 0.6 Dramatic emphasis, onboarding

Springs:

Preset Stiffness Damping Use Case
default 400 30 Dialogs, toasts
snappy 500 35 Dropdowns, toggles
gentle 300 28 Drawers, sheets
bouncy 600 18 Notifications, badges
stiff 700 40 Button feedback

Easings: linear, easeOut, easeIn, easeInOut, emphasized, decelerate, accelerate, plus 80+ named eases (power1.in, elastic.out, bounce.inOut, etc.)

Theme-Aware Motion

Each theme has its own motion personality — speed multiplier, spring stiffness, easing preferences.

<MotionProvider config={{ theme: 'obsidian' }}>
  <App /> {/* Crisp, professional springs */}
</MotionProvider>

<MotionProvider config={{ theme: 'vapor' }}>
  <App /> {/* Dreamy, floaty motion with gentler springs */}
</MotionProvider>
Theme Character Preference
Obsidian Crisp, professional Spring-based (stiffness: 450, damping: 32)
Aurora Soft, elegant, slightly slower Easing-based (speed: 1.1×)
Forge Punchy, direct, faster Spring-based (speed: 0.9×)
Mobile Fast, responsive, momentum-driven Spring-based (speed: 0.85×)
Neon Energetic, bouncy Spring-based (stiffness: 500, damping: 22)
Vapor Dreamy, floaty, slow Spring-based (speed: 1.15×)
Retro Warm, weighted Spring-based (stiffness: 320, damping: 28)
Glass Smooth, glassy Easing-based (speed: 1.05×)
Scholar Restrained, minimal Easing-based (speed: 1.2×)
Corporate Professional, no-nonsense Easing-based (speed: 0.95×)
Memphis Playful, bouncy Spring-based (stiffness: 550, damping: 20)
Bio-Organic Organic, flowing Spring-based (stiffness: 280, damping: 24)

Accessibility

Every motion hook and component automatically respects prefers-reduced-motion. Three enforcement tiers:

  • zero-duration — all durations collapse to 0ms (default reduced-motion behavior)
  • smart reduction — preserves informative transitions, removes decorative ones
  • epilepsy safety — automatically caps animations that flash faster than 3Hz

Override globally:

<MotionProvider config={{ reducedMotion: true }}>
  {/* All animations reduced regardless of OS setting */}
</MotionProvider>

Migration from framer-motion

If you were previously using framer-motion directly, DG Motion provides a fromMotion() config translator and a codemod CLI:

npx dg-motion migrate --from framer-motion

Or translate config objects at runtime:

import { fromMotion } from '@dg-ui-react/react/motion';

const dgConfig = fromMotion({
  initial: { opacity: 0 },
  animate: { opacity: 1 },
  transition: { duration: 0.3 },
});

TypeScript

All components ship with full TypeScript declarations. Import types alongside components:

import { Button } from '@dg-ui-react/react/obsidian';
import type { ButtonProps, ButtonVariant, ButtonSize } from '@dg-ui-react/react/obsidian';

import type { PricingTier } from '@dg-ui-react/react/aurora';
import type { RetroComponentProps, RetroPalette } from '@dg-ui-react/react/retro';
import type { MotionPresetName, ThemeName, EaseName } from '@dg-ui-react/react/motion';

TypeScript Configuration

Set moduleResolution to a strategy that supports package.json exports:

{
  "compilerOptions": {
    "moduleResolution": "bundler"
  }
}

Compatible values: "bundler", "node16", "nodenext".


Framework Integration

Vite + React

// src/main.tsx
import '@dg-ui-react/react/styles.css';

Next.js App Router

// app/layout.tsx
import '@dg-ui-react/react/styles.css';

DG Motion animations run client-side. Add 'use client' at the top of files that import animated DG-UI components. For zero-flash SSR, DG Motion pre-renders initial animation states as inline CSS @keyframes — no layout shift.

Next.js Pages Router

// pages/_app.tsx
import '@dg-ui-react/react/styles.css';

Remix

// app/root.tsx
import dgStyles from '@dg-ui-react/react/styles.css?url';
export const links = () => [{ rel: 'stylesheet', href: dgStyles }];

Complete Example

import '@dg-ui-react/react/styles.css';

import { Button, Card, Input, Tabs } from '@dg-ui-react/react/obsidian';
import { PricingCard } from '@dg-ui-react/react/aurora';
import { Badge } from '@dg-ui-react/react/neon';
import { Motion, MotionProvider, MotionPresence } from '@dg-ui-react/react/motion';
import { useState } from 'react';

import type { TabItem } from '@dg-ui-react/react/obsidian';

const tabs: TabItem[] = [
  { value: 'overview', label: 'Overview' },
  { value: 'pricing', label: 'Pricing' },
];

export default function App() {
  const [activeTab, setActiveTab] = useState('overview');
  const [showDialog, setShowDialog] = useState(false);

  return (
    <MotionProvider config={{ theme: 'obsidian' }}>
      <Motion preset="fadeInUp">
        <Card>
          <Badge variant="success">Live</Badge>
          <Tabs items={tabs} value={activeTab} onValueChange={setActiveTab} />

          <MotionPresence>
            {activeTab === 'overview' && (
              <Motion preset="fadeIn">
                <Input placeholder="Search components..." />
                <Button variant="primary" onClick={() => setShowDialog(true)}>
                  Open Dialog
                </Button>
              </Motion>
            )}
          </MotionPresence>
        </Card>
      </Motion>
    </MotionProvider>
  );
}

Troubleshooting

Components render with no styles — The stylesheet import is missing or placed too late. Put import '@dg-ui-react/react/styles.css' at the top of your application root, before any other CSS imports.

Animations are missing — Ensure you are not importing from an outdated cached version that listed framer-motion as a peer dep. Run npm install @dg-ui-react/react@latest — DG Motion is fully bundled, no extra install needed.

Next.js App Router: "You're importing a component that needs useState" — Add 'use client' at the top of the file where you import DG-UI components.

TypeScript cannot find module '@dg-ui-react/react/obsidian' — Set moduleResolution to "bundler", "node16", or "nodenext" in tsconfig.json.

Bundle size seems large — Use subpath imports (@dg-ui-react/react/obsidian) instead of root imports. Per-theme entry points give bundlers the narrowest possible tree-shaking surface. The motion engine is split into its own entry point (@dg-ui-react/react/motion) and is not included in theme bundles unless imported.


What's Included

Feature Details
Themes 15 published design themes, each with its own subpath entry point
Components 1,478+ exports across all themes
Motion Engine Zero-dependency DG Motion: 80+ eases, spring physics, timelines, scroll, gestures, drag, layout FLIP, text animation, SVG morph, particles, Tailwind plugin
TypeScript Full declarations for every component, hook, and type
CSS Single pre-compiled stylesheet — no Tailwind config needed in consumer projects
Tree-Shaking ESM + CJS dual output via tsup, per-theme entry points
Accessibility Three-level reduced-motion enforcement in every animated component
Framework Support Vite, Next.js (App Router + Pages Router), Remix
Zero Dependencies No framer-motion, no GSAP, no tailwindcss-animate — all motion is bundled

About

@dg-ui-react/react is created and maintained by AahPlexX.

License

MIT — Copyright © 2026 AahPlexX