UNPKG

@decidrcn/ui

Version:

Decidr UI - A comprehensive React component library built with shadcn/ui and Radix UI. Supports React, Next.js, Rails, and works with npm, yarn, and pnpm.

437 lines (341 loc) 10.6 kB
# Decidr UI A comprehensive React component library built with shadcn/ui and Radix UI, designed for modern web applications including Rails apps using Slim templates. --- ## Monorepo Structure This project uses a **pnpm monorepo** structure: - **Root**: Manages workspace dependencies and scripts - **packages/ui**: The Decidr UI component library (this package) - **apps/demo**: Demo app to showcase components All packages now use **React 19** for consistency and future-proofing. --- ## Features - 🎨 **Beautiful Design**: Built on shadcn/ui with Tailwind CSS - **Accessible**: Powered by Radix UI primitives - 🎯 **Type Safe**: Full TypeScript support - 🚀 **Fast**: Optimized for performance - 🎪 **Customizable**: Extensive theming and customization options - 📱 **Responsive**: Mobile-first design approach - ⚛️ **React19 Ready**: Fully compatible with React19🛤️ **Rails Compatible**: Works seamlessly with Rails applications using Slim templates --- ## Installation ### For React/Next.js Applications ```bash npm install @decidrcn/ui # or yarn add @decidrcn/ui # or pnpm add @decidrcn/ui ``` ### For Rails Applications1 **Add to your Gemfile:** ```ruby gemjsbundling-rails gem cssbundling-rails' ```2nstall the package:** ```bash yarn add @decidrcn/ui # or npm install @decidrcn/ui ``` 3. **Configure your build tool (esbuild, webpack, or Vite):** **With esbuild:** ```javascript // config/esbuild.config.js const esbuild = require('esbuild') esbuild.build({ entryPoints: ['app/javascript/application.js], bundle: true, outdir: app/assets/builds', format:esm, plugins: ], external: ['@decidrcn/ui'] }) ``` **With Vite:** ```javascript // vite.config.js import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' export default defineConfig({ plugins: react()], build: { rollupOptions:[object Object] external: ['@decidrcn/ui'] } } }) ``` 4**Import styles in your application:** ```javascript // app/javascript/application.js import '@decidrcn/ui/styles' ``` --- ## Usage ### React/Next.js Quick Start ```tsx import { Button } from@decidrcn/ui; function App() { return ( <Button variant="default> Hello Decidr UI! </Button> ); } ``` ### Rails with Slim Templates 1p React components in your Rails app:** ```javascript // app/javascript/components/DecidrButton.jsx import React from 'react' import { Button } from '@decidrcn/ui' export default function DecidrButton({ children, variant = 'default, ...props }) { return ( <Button variant={variant}[object Object]...props}> {children} </Button> ) } ```2 in Slim templates:** ```slim / app/views/layouts/application.html.slim doctype html html head title My Rails App = csrf_meta_tags = csp_meta_tag = stylesheet_link_tag "application",data-turbo-track": "reload = javascript_importmap_tags body / Your content here = yield / app/views/pages/home.html.slim .container h1 Welcome to My App / Using React components in Slim #react-button-container data-props={variant: 'gradient', children:Click me!'} / Or with more complex props #react-carousel-container data-props={products: @products.to_json} ```3t React components:** ```javascript // app/javascript/application.js import React from 'react' import { createRoot } fromreact-dom/client' import DecidrButton from./components/DecidrButton' import ProductCarousel from './components/ProductCarousel' // Mount components when DOM is ready document.addEventListener('DOMContentLoaded', () => { // Mount button component const buttonContainer = document.getElementById('react-button-container') if (buttonContainer)[object Object] const props = JSON.parse(buttonContainer.dataset.props || '{}') const root = createRoot(buttonContainer) root.render(React.createElement(DecidrButton, props)) } // Mount carousel component const carouselContainer = document.getElementById('react-carousel-container') if (carouselContainer)[object Object] const props = JSON.parse(carouselContainer.dataset.props || '{}') const root = createRoot(carouselContainer) root.render(React.createElement(ProductCarousel, props)) } }) ``` 4d Slim integration with helpers:** ```ruby # app/helpers/decidr_helper.rb module DecidrHelper def decidr_button(text, variant: 'default', **options) content_tag :div, , id:decidr-button-#[object Object]SecureRandom.hex(4)}, data: { component: 'DecidrButton', props: { children: text, variant: variant, **options }.to_json } end def decidr_carousel(items, **options) content_tag :div, , id: decidr-carousel-#[object Object]SecureRandom.hex(4)}, data: { component: 'ProductCarousel', props: { products: items, **options }.to_json } end end ``` ```slim / Using helpers in Slim .container = decidr_button "Submit Form", variant:gradient, size: lg" = decidr_carousel @products, opts: { loop: true } ``` --- ## Components ### Button Enhanced button component with support for: - Multiple variants (default, secondary, destructive, outline, ghost, link, success, warning, info, gradient) - Custom colors and gradients - Icon support (left, right, or icon-only) - Radius customization - Multiple sizes - Default variant: White background with black text - Gradient variant: Beautiful gradient with full radius support ```tsx import { Button } from '@decidrcn/ui'; import[object Object]PlusIcon } from '@radix-ui/react-icons; // Basic usage (white background, black text) <Button>Click me</Button> // Gradient button with full radius <Button variant="gradient radius=full Gradient Button </Button> // With custom colors <Button bgColor="#8B5CF6 textColor="white hoverBgColor="#7C3AED> Purple Button </Button> // With icons <Button leftIcon={<PlusIcon className="h-44/>}> Add Item </Button> // Icon only <Button size=icon" leftIcon={<PlusIcon className="h-4 w-4>} /> ``` ### Carousel Flexible carousel component perfect for products and events: ```tsx import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from @decidrcn/ui'; <Carousel className="w-full max-w-6 <CarouselContent> {products.map((product) => ( <CarouselItem key={product.id} className=md:basis-1/2 lg:basis-1/3"> <ProductCard product={product} /> </CarouselItem> ))} </CarouselContent> <CarouselPrevious /> <CarouselNext /> </Carousel> ``` ### Avatar Avatar component with shape variants: - Circle (default) - Square - Rounded variants ```tsx import { Avatar, AvatarFallback, AvatarImage } from @decidrcn/ui'; <Avatar shape="circle"> <AvatarImage src="user.jpg" alt="User /> <AvatarFallback>JD</AvatarFallback> </Avatar> ``` ### DecidrHeader Semantic header component with proper text sizes for different heading levels: - H1: Large title (text-4xl, font-bold) - H2: Section header (text-3xl, font-semibold) - H3: Subsection header (text-2l, font-semibold) - H4-H6aller headers with appropriate sizing ```tsx import { DecidrHeader } from@decidrcn/ui'; // Different heading levels with automatic text sizing <DecidrHeader as="h1>Main Page Title</DecidrHeader> <DecidrHeader as=h2Section Title</DecidrHeader> <DecidrHeader as="h3>Subsection Title</DecidrHeader> // Custom styling <DecidrHeader as="h2assName=text-blue-600> Custom Styled Header </DecidrHeader> ``` ### DecidrBody Body text component with different size variants for optimal readability: - xs: Extra small (text-xs) - Fine print, metadata - sm: Small (text-sm) - Captions, secondary info - base: Default (text-base) - Standard paragraphs - lg: Large (text-lg) - Important content, emphasis - xl: Extra large (text-xl) - Prominent content sections ```tsx import { DecidrBody } from@decidrcn/ui'; // Different text sizes <DecidrBody size="xl">Prominent content section</DecidrBody> <DecidrBody size="lg">Important information</DecidrBody> <DecidrBody size="base">Standard paragraph text</DecidrBody> <DecidrBody size="sm">Secondary information</DecidrBody> <DecidrBody size="xs">Fine print and metadata</DecidrBody> // Different HTML elements <DecidrBody as=span>Inline text</DecidrBody> <DecidrBody as=div">Block text</DecidrBody> // Custom styling <DecidrBody size="lg" className="text-blue-600 italic>Custom styled body text </DecidrBody> ``` --- ## Rails Integration Best Practices ### 1. Component Organization ``` app/javascript/ ├── components/ ├── decidr/ ├── DecidrButton.jsx ├── DecidrCarousel.jsx └── DecidrCard.jsx └── shared/ └── application.js ``` ### 2. Data Flow - Pass data from Rails controllers to React components via `data-props` - Use JSON serialization for complex objects - Keep React components stateless when possible ### 3. Styling - Import Decidr UI styles in your main application file - Use Tailwind CSS classes in Slim templates - Customize theme variables in your CSS ### 4Performance - Lazy load React components when needed - Use Turbo for fast page transitions - Bundle components efficiently --- ## Decidr Logo The Decidr logo is available as a React component: ```tsx import { Logo } from @decidrcn/ui'; <Logo className="w-20 h-5 text-primary" /> ``` - Used in Storybook and throughout the design system - SVG-based, theme-aware (uses `currentColor`) - Easily resizable and styleable --- ## Development ### Running Storybook ```bash pnpm storybook ``` This will start Storybook on `http://localhost:66re you can explore all components, including the Decidr logo. ### Building ```bash pnpm build ``` ### Testing ```bash pnpm test ``` --- ## Contributing 1. Fork the repository 2. Create a feature branch 3. Make your changes 4. Add tests if applicable 5. Submit a pull request --- ## Third-Party Licenses & Attribution This package is built with and depends on: - [shadcn/ui](https://github.com/shadcn-ui/ui) MIT License © shadcn - [Radix UI](https://www.radix-ui.com/) MIT License © WorkOS, Inc. Both projects are licensed under the [MIT License](https://opensource.org/licenses/MIT). Copies of their licenses are available in their respective repositories. We thank the authors and contributors of these projects for their amazing work! ## License MIT © Decidr Team