@dg-ui-react/react
v0.5.0
Published
Damn Good UI — production-ready React component library
Downloads
393
Maintainers
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.
Built with TypeScript 6 and Tailwind CSS v4. No external animation dependencies — all motion is powered by the built-in DG Motion engine.
Preview
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/reactPeer 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.
Pattern 1: Subpath Imports (Recommended)
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 MotionValueScroll-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-motionOr 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.
- Website: dg-ui.com
- npm: npmjs.com/package/@dg-ui-react/react
License
MIT — Copyright © 2026 AahPlexX
