paradox-ui
v1.0.0
Published
A modern, DaisyUI-inspired React component library built as a Tailwind CSS plugin
Maintainers
Readme
Paradox UI
A modern, DaisyUI-inspired React component library built as a Tailwind CSS plugin. Paradox UI provides semantic, high-level component class names that are abstractions of Tailwind's low-level utility classes, improving developer speed, code readability, and maintainability while retaining the full customization power of Tailwind.
✨ Features
- 🎨 DaisyUI-Inspired: Semantic component class names like
btn,card - 🧩 Compound Components: Flexible component composition patterns
- 🎯 TypeScript First: Full TypeScript support with strict typing
- 🌓 Theme System: Dynamic theming with CSS custom properties
- ♿ Accessible: Built with accessibility best practices
- 📱 Responsive: Mobile-first design approach
- 🎭 Storybook: Comprehensive component documentation
- 🧪 Tested: Full test coverage with Jest and React Testing Library
- 📦 Tree-Shakable: Optimized bundle size with selective imports
- 🔧 Developer Friendly: Excellent DX with hot reload and IntelliSense
🚀 Installation
npm install paradox-ui
# or
yarn add paradox-ui
# or
pnpm add paradox-uiPeer Dependencies
Paradox UI requires the following peer dependencies:
npm install react react-dom tailwindcss
# or
yarn add react react-dom tailwindcss
# or
pnpm add react react-dom tailwindcss⚙️ Setup
1. Configure Tailwind CSS
Make sure you have Tailwind CSS configured in your project. If you don't, create a tailwind.config.js:
module.exports = {
content: [
'./src/**/*.{js,ts,jsx,tsx}',
'./node_modules/paradox-ui/dist/**/*.{js,ts,jsx,tsx}',
],
theme: {
extend: {},
},
plugins: [],
};2. Import Styles
Import the Paradox UI styles in your main CSS file:
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';3. Set Up Theme Provider
Wrap your application with the ThemeProvider:
import React from 'react';
import { ThemeProvider } from 'paradox-ui';
function App() {
return (
<ThemeProvider defaultTheme="light">
{/* Your app content */}
</ThemeProvider>
);
}📚 Usage
Button Component
import { Button } from 'paradox-ui';
function Example() {
return (
<div className="space-x-4">
<Button variant="primary" onClick={() => console.log('clicked')}>
Primary Button
</Button>
<Button variant="outline" size="lg">
Large Outline
</Button>
<Button loading disabledWhileLoading>
Loading...
</Button>
<Button
variant="success"
icon={<PlusIcon />}
iconPosition="right"
>
Add New
</Button>
</div>
);
}Card Component
import { Card, CardTitle, CardBody, CardActions, CardMedia } from 'paradox-ui';
function Example() {
return (
<Card className="w-96">
<CardTitle>Card Title</CardTitle>
<CardBody>
This is the card body content. You can put any content here.
</CardBody>
<CardActions>
<Button size="sm">Action 1</Button>
<Button size="sm" variant="outline">Action 2</Button>
</CardActions>
</Card>
);
}
// Card with image
function CardWithImage() {
return (
<Card imageSrc="/path/to/image.jpg" imageAlt="Card image">
<CardTitle>Beautiful Image</CardTitle>
<CardBody>
Cards can have images at the top, bottom, left, or right.
</CardBody>
<CardActions>
<Button size="sm">View Details</Button>
</CardActions>
</Card>
);
}Using with Custom Icons
Paradox UI works great with icon libraries like Heroicons, Lucide React, or custom SVG icons:
import { Button } from 'paradox-ui';
import { PlusIcon, TrashIcon } from '@heroicons/react/24/outline';
function IconExample() {
return (
<div className="space-x-4">
<Button icon={<PlusIcon className="h-4 w-4" />}>
Add Item
</Button>
<Button
variant="error"
icon={<TrashIcon className="h-4 w-4" />}
iconPosition="right"
>
Delete
</Button>
</div>
);
}🎨 Theming
Default Themes
Paradox UI comes with built-in light and dark themes:
import { ThemeProvider, useTheme } from 'paradox-ui';
function App() {
return (
<ThemeProvider
defaultTheme="light"
persistTheme={true} // Save theme preference to localStorage
>
<ThemeToggle />
{/* Your app content */}
</ThemeProvider>
);
}
function ThemeToggle() {
const { theme, setTheme, toggleDarkMode } = useTheme();
return (
<div>
<p>Current theme: {theme.displayName}</p>
<button onClick={toggleDarkMode}>
Toggle Dark Mode
</button>
<button onClick={() => setTheme('light')}>
Light Theme
</button>
<button onClick={() => setTheme('dark')}>
Dark Theme
</button>
</div>
);
}Custom Themes
Create your own themes by extending the base theme:
import { ThemeProvider, createThemeVariant } from 'paradox-ui';
import { lightTheme } from 'paradox-ui/themes';
const corporateTheme = createThemeVariant(
lightTheme,
'corporate',
'Corporate',
(theme) => ({
colors: {
...theme.colors,
primary: {
...theme.colors.primary,
500: '#1e40af', // Custom primary color
},
},
})
);
function App() {
return (
<ThemeProvider
defaultTheme="corporate"
themes={[lightTheme, corporateTheme]}
>
{/* Your app content */}
</ThemeProvider>
);
}🔧 Component API Reference
Button
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: 'primary' | 'secondary' | 'outline' | 'ghost' | 'link' | 'info' | 'success' | 'warning' | 'error';
size?: 'sm' | 'md' | 'lg';
loading?: boolean;
disabledWhileLoading?: boolean;
fullWidth?: boolean;
shape?: 'default' | 'square' | 'circle';
icon?: React.ReactNode;
iconPosition?: 'left' | 'right';
loadingIndicator?: React.ReactNode;
as?: React.ElementType;
}Card
interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
variant?: 'default' | 'bordered' | 'compact' | 'side';
shadow?: boolean;
responsive?: boolean;
backgroundColor?: 'base-100' | 'base-200' | 'neutral';
imageSrc?: string;
imageAlt?: string;
imagePosition?: 'top' | 'bottom' | 'left' | 'right';
}Card Sub-components
CardTitle: Card title with configurable heading levelCardBody: Main content areaCardActions: Action buttons areaCardMedia: Image or custom media contentCardFooter: Footer section
📦 Bundle Size
Paradox UI is optimized for minimal bundle impact:
- Full Library: ~45KB gzipped
- Individual Components: ~8-15KB gzipped each
- Tree-shakable: Only import what you use
Selective Imports
You can import individual components to reduce bundle size further:
// Import all components (larger bundle)
import { Button, Card } from 'paradox-ui';
// Import individual components (smaller bundle)
import Button from 'paradox-ui/Button';
import Card from 'paradox-ui/Card';🧪 Development
Setup Development Environment
# Clone the repository
git clone https://github.com/yourusername/paradox-ui.git
cd paradox-ui
# Install dependencies
npm install
# Start development server
npm run dev
# Start Storybook
npm run storybook
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Build library
npm run buildProject Structure
paradox-ui/
├── src/
│ ├── components/ # React components
│ │ ├── Button/
│ │ └── Card/
│ ├── providers/ # React context providers
│ ├── types/ # TypeScript type definitions
│ ├── utils/ # Utility functions
│ ├── hooks/ # Custom React hooks
│ ├── styles/ # CSS and styling
│ └── index.ts # Main entry point
├── .storybook/ # Storybook configuration
├── stories/ # Storybook stories
├── dist/ # Built library
└── package.jsonAdding New Components
- Create component directory in
src/components/ - Implement component with TypeScript
- Create Storybook stories
- Write comprehensive tests
- Update exports in
src/index.ts
Example:
// src/components/Alert/Alert.tsx
import React from 'react';
import { cn } from '../../utils/cn';
interface AlertProps extends React.HTMLAttributes<HTMLDivElement> {
variant?: 'info' | 'success' | 'warning' | 'error';
children: React.ReactNode;
}
export const Alert = ({ variant = 'info', className, children, ...props }: AlertProps) => {
const variantClasses = {
info: 'alert-info',
success: 'alert-success',
warning: 'alert-warning',
error: 'alert-error',
};
return (
<div
className={cn('alert', variantClasses[variant], className)}
role="alert"
{...props}
>
{children}
</div>
);
};🤝 Contributing
Contributions are welcome! Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.
Development Guidelines
- TypeScript: All components must have full TypeScript support
- Accessibility: Components must be accessible (ARIA attributes, keyboard navigation)
- Testing: New components require comprehensive tests
- Documentation: Update Storybook stories and API documentation
- Code Style: Follow existing patterns and use ESLint configuration
📄 License
MIT License - see the LICENSE file for details.
🙏 Acknowledgments
- DaisyUI for the inspiration and design philosophy
- Tailwind CSS for the amazing utility-first CSS framework
- Storybook for the component documentation platform
- The React community for excellent patterns and practices
🔗 Links
Built with ❤️ for the React community
