@particle-academy/react-fancy
v3.0.1
Published
React UI component library — React port of the fancy-flux Blade component library
Maintainers
Readme
@particle-academy/react-fancy
React UI component library — the React port of the fancy-flux Blade/Livewire component library. The goal is visual and behavioral parity with fancy-flux.
Inertia.js integration
Using react-fancy with Inertia? Install the @particle-academy/fancy-inertia adapter — it ships a single <FancyAppRoot> provider that mounts Toast.Provider (and the modal portal root) above the Inertia outlet, plus useFancyForm() for one-line wiring of react-fancy form fields to Inertia's useForm() server-validated state, plus a <FancyClientOnly> boundary for SSR-skip needs. See fancy-inertia/docs/SSR.md for the per-component SSR-safety matrix.
Migration to v3
Canvas and Diagram were moved out of react-fancy in v3.0.0 to keep this package focused on generic React UI. They live in companion packages now:
- import { Canvas, useCanvas } from "@particle-academy/react-fancy";
+ import { Canvas, useCanvas } from "@particle-academy/fancy-3d/canvas";- import { Diagram } from "@particle-academy/react-fancy";
+ import { Diagram } from "@particle-academy/fancy-echarts";
// …or one of the new specialized presets:
// DataDiagram, Flowchart, Mindmap, OrgChart<Canvas> in fancy-3d is now engine-pluggable (engine="dom" | "babylon" | CustomEngine) and ships with built-in adapters for DOM/Web3D (default) and Babylon. fancy-echarts' diagram exports include four schema-driven specialized presets sharing one routing/marker engine.
Everything else in react-fancy is unchanged.
Installation
# npm
npm install @particle-academy/react-fancy
# pnpm
pnpm add @particle-academy/react-fancy
# yarn
yarn add @particle-academy/react-fancyPeer dependencies: react >= 18, react-dom >= 18, tailwindcss >= 4
Bundled dependencies: clsx, tailwind-merge, marked
External dependency: lucide-react (default icon library)
Usage
Add the @source directive to your main CSS file so Tailwind v4 scans the component library for class names:
@import "tailwindcss";
@source "../node_modules/@particle-academy/react-fancy/dist/**/*.js";Then import and use components:
import { Action, Input, Modal, Dropdown } from "@particle-academy/react-fancy";
import "@particle-academy/react-fancy/styles.css";Commands
pnpm --filter @particle-academy/react-fancy build # Build with tsup (ESM + CJS + DTS)
pnpm --filter @particle-academy/react-fancy dev # Watch mode
pnpm --filter @particle-academy/react-fancy lint # Type-check (tsc --noEmit)
pnpm --filter @particle-academy/react-fancy clean # Remove dist/The demo app consuming this package builds with Vite from the monorepo root:
npx vite build # Build demo app (verifies imports work)Components
Core
| Component | Description | Docs | |-----------|-------------|------| | Action | Button with colors, states, icons, emoji, avatar, badge, sort control | docs | | Carousel | Slide carousel with directional/wizard variants, autoplay, loop | docs | | ColorPicker | Native color input with swatch preview, hex display, presets | docs | | Emoji | Emoji renderer from slugs | docs | | EmojiSelect | Emoji search and selection dropdown | docs | | Table | Data table with sorting, pagination, search, and tray | docs |
Form Inputs
| Component | Description | Docs | |-----------|-------------|------| | Field | Form field wrapper with label and error display | docs | | Input | Text input | docs | | Textarea | Multi-line text input | docs | | Select | Native and listbox dropdown with multi-select support | docs | | Checkbox / CheckboxGroup | Checkbox inputs | docs | | RadioGroup | Radio button group | docs | | Switch | Toggle switch | docs | | Slider | Range slider (single and range modes) | docs | | MultiSwitch | Segmented toggle between multiple options | docs | | DatePicker | Date selection (single and range modes) | docs | | Autocomplete | Input with filtered dropdown suggestions, async search, keyboard nav | docs | | Pillbox | Tag/pill input with add/remove, backspace delete | docs | | OtpInput | Single-digit OTP code input with auto-advance and paste support | docs | | FileUpload | Drag-and-drop file upload with dropzone and file list | docs | | TimePicker | Hour/minute/AM-PM time selection | docs | | Calendar | Month grid with single, range, and multi-select modes | docs |
Display
| Component | Description | Docs |
|-----------|-------------|------|
| Heading | Semantic heading (h1–h6) with size and weight props | docs |
| Text | Paragraph/span with size, color, weight, and as prop | docs |
| Separator | Horizontal/vertical divider with optional label | docs |
| Badge | Inline label with color, variant, size, and dot indicator | docs |
| Icon | Size wrapper around icon ReactNode | docs |
| Avatar | Image with fallback initials, size variants, status indicator | docs |
| Skeleton | Animated placeholder (rect, circle, text), pulse animation | docs |
| Progress | Bar and circular variants, indeterminate mode | docs |
| Brand | Logo + text lockup | docs |
| Profile | Avatar + name + subtitle layout | docs |
| Card | Container with Header, Body, Footer compound slots | docs |
| Callout | Alert/info box with icon, color, and dismissible support | docs |
| Timeline | Stacked, alternating, and horizontal timeline with data-driven or compound API | docs |
Overlay & Floating
| Component | Description | Docs |
|-----------|-------------|------|
| Tooltip | Hover/focus tooltip with arrow and placement control | docs |
| Popover | Click or hover floating panel | docs |
| Dropdown | Popover with keyboard-navigable menu items | docs |
| ContextMenu | Right-click triggered dropdown | docs |
| Modal | Full-screen backdrop dialog with focus trap and scroll lock | docs |
| Toast | Notification stack with auto-dismiss, variants, and position options | docs |
| Command | Cmd+K command palette with search and keyboard navigation | docs |
Navigation & Layout
| Component | Description | Docs | |-----------|-------------|------| | Tabs | Tabbed content with underline, pills, and boxed variants | docs | | Accordion | Collapsible content sections (single/multiple mode) | docs | | Breadcrumbs | Navigation breadcrumb trail with separator | docs | | Navbar | Responsive navigation bar with hamburger collapse | docs | | Pagination | Page navigation with prev/next and ellipsis | docs | | TreeNav | Hierarchical file/folder tree with expand/collapse, selection, and extension-based icons | docs |
Rich Content
| Component | Description | Docs | |-----------|-------------|------| | Composer | Chat-style message input composing textarea + actions | docs | | Chart | SVG-based Bar, Line, Area, Pie, Donut, and Sparkline charts | docs | | Editor | Toolbar chrome wrapper for contentEditable | docs | | Kanban | Drag-and-drop board with columns and cards | docs | | Canvas | Interactive node canvas with pan, zoom, and connections | docs | | Diagram | Entity-relationship diagram with draggable nodes and relation lines | docs | | ContentRenderer | Markdown/HTML content renderer | docs |
Menus & Navigation
| Component | Description | Docs | |-----------|-------------|------| | Menu | Hierarchical menu with nested items | docs | | Sidebar | Collapsible sidebar navigation | docs | | MobileMenu | Responsive mobile navigation overlay | docs |
Utilities & Hooks
| Export | Description | Docs |
|--------|-------------|------|
| Portal | createPortal wrapper with automatic dark mode propagation | docs |
| cn() | clsx + tailwind-merge for conditional class composition | docs |
| Hooks | useControllableState, useFloatingPosition, useOutsideClick, useEscapeKey, useFocusTrap, useAnimation, useId, usePanZoom | docs |
Customization
All components render a data-react-fancy-* attribute on their root element (e.g., data-react-fancy-modal, data-react-fancy-dropdown-item). Use these for external CSS targeting or JavaScript integration:
[data-react-fancy-modal] {
--custom-border-radius: 1rem;
}document.querySelectorAll("[data-react-fancy-dropdown-item]");Dark Mode
Dark mode works via Tailwind's dark: class strategy. The library's Portal component automatically detects the dark class (or data-theme="dark") on <html> and propagates it into portaled content (modals, dropdowns, tooltips, toasts, etc.).
Architecture
Directory Layout
src/
├── components/ # One directory per component
│ ├── Action/
│ │ ├── Action.tsx # Component implementation
│ │ ├── Action.types.ts # Props interface
│ │ └── index.ts # Re-exports
│ ├── Modal/
│ │ ├── Modal.tsx # Root + Object.assign compound
│ │ ├── Modal.context.ts # React context (compound components)
│ │ ├── Modal.types.ts # Props interfaces
│ │ ├── ModalHeader.tsx # Sub-component
│ │ ├── ModalBody.tsx
│ │ ├── ModalFooter.tsx
│ │ └── index.ts
│ ├── inputs/ # Form input components (Field, Input, Select, etc.)
│ └── ...
├── data/ # Static data (emoji entries, etc.)
├── hooks/ # Shared React hooks
├── utils/ # Shared utilities (cn, types)
├── styles.css # Keyframe animations
└── index.ts # Public API — all exportsShared Types (utils/types.ts)
Size—"xs" | "sm" | "md" | "lg" | "xl"Color— Full Tailwind color palette (17 colors)ActionColor— Subset of 10 standalone colors matching fancy-fluxVariant—"solid" | "outline" | "ghost" | "soft"Placement—"top" | "bottom" | "left" | "right"+ start/end variants
Demo Pages
Component demos live in the monorepo at resources/js/react-demos/pages/. Each component has a ComponentNameDemo.tsx that exercises all props and states using the DemoSection wrapper component.
Agent Guidelines
Guidelines for AI agents (Claude Code, Copilot, etc.) working on this package.
Component Pattern
Every component follows this structure:
ComponentName.types.ts— Props interface extending native HTML element attributes. Import shared types from../../utils/types.ComponentName.tsx— Implementation usingforwardRef. Always setdisplayName. Usecn()for class merging. Adddata-react-fancy-{name}=""to the root element.- Compound components — Use
Object.assign(Root, { Sub1, Sub2 })pattern. Add a.context.tswith React context. Each sub-component gets its owndata-react-fancy-{parent}-{sub}attribute. index.ts— Re-exports both the component and its types.src/index.ts— Must export the component and its prop types. Update this file when adding new components.
Icons
Use lucide-react as the default icon library. It is a dependency of this package and marked as external in tsup. Components should import icons directly (e.g., import { X, ChevronDown } from "lucide-react").
Parity with fancy-flux
- Always reference the corresponding Blade component in
packages/fancy-flux/stubs/resources/views/flux/when implementing or updating a component. Match the Tailwind classes, color values, state logic, and dark mode support exactly. - React-specific additions (e.g.,
loadingspinner,hrefanchor rendering) are fine — they don't exist in Blade but are idiomatic in React. - Icons are passed as
ReactNode(not string names like Blade's<flux:icon>). This is the correct React pattern.
Styling
- Tailwind v4 — CSS-first config. Use
@import "tailwindcss"not@tailwinddirectives. - Dark mode — Every color variant must include
dark:equivalents. Check fancy-flux for the exact classes. Portal components get dark mode automatically via the Portal wrapper. - No component library deps — Only
clsx,tailwind-merge, andlucide-react. Don't add Radix, Headless UI, or similar. - Class maps should be
Record<Size, string>(or similar) constants outside the component function, not inline.
TypeScript
- Explicit types on all exports. Use
interfacefor props (nottype). - Extend native HTML attributes (
ButtonHTMLAttributes,InputHTMLAttributes, etc.) andOmitconflicting props (e.g.,Omit<..., "color">). - Export prop interfaces from the component's
index.tsand fromsrc/index.ts.
Build
- tsup handles the build — ESM, CJS, and
.d.tsgeneration. react,react-dom, andlucide-reactare external dependencies, never bundled.- After any change, verify with
pnpm --filter @particle-academy/react-fancy buildbefore considering the work done. - When updating a component, update its demo page in
resources/js/react-demos/pages/to cover all new features.
