import JSZip from "jszip" import saveAs from "file-saver" // Get current design settings from contexts interface ExportSettings { primaryColor: string borderRadius: number font: string materialType: string packageType: "free" | "pro" } // Generate package.json for each package type function generatePackageJson(packageType: "free" | "pro") { const baseDependencies = { "@heroicons/react": "^2.0.18", "@radix-ui/react-accordion": "^1.2.2", "@radix-ui/react-alert-dialog": "^1.1.4", "@radix-ui/react-avatar": "^1.1.2", "@radix-ui/react-checkbox": "^1.1.3", "@radix-ui/react-collapsible": "^1.1.2", "@radix-ui/react-dialog": "^1.1.4", "@radix-ui/react-dropdown-menu": "^2.1.4", "@radix-ui/react-hover-card": "^1.1.4", "@radix-ui/react-label": "^2.1.1", "@radix-ui/react-popover": "^1.1.4", "@radix-ui/react-progress": "^1.1.1", "@radix-ui/react-scroll-area": "^1.2.2", "@radix-ui/react-select": "^2.1.4", "@radix-ui/react-separator": "^1.1.1", "@radix-ui/react-slider": "^1.2.2", "@radix-ui/react-slot": "^1.1.1", "@radix-ui/react-switch": "^1.1.2", "@radix-ui/react-tabs": "^1.1.2", "@radix-ui/react-tooltip": "^1.1.6", "class-variance-authority": "^0.7.1", clsx: "^2.1.1", "lucide-react": "^0.454.0", next: "14.2.25", "next-themes": "^0.4.4", react: "^19", "react-dom": "^19", "tailwind-merge": "^2.5.5", "tailwindcss-animate": "^1.0.7", } const proDependencies = { ...baseDependencies, "@vercel/analytics": "^1.1.1", "react-dnd": "^16.0.1", "react-dnd-html5-backend": "^16.0.1", uuid: "^9.0.0", } return JSON.stringify( { name: `percolate-ui-${packageType}`, version: "1.0.0", private: true, scripts: { dev: "next dev", build: "next build", start: "next start", lint: "next lint", }, dependencies: packageType === "pro" ? proDependencies : baseDependencies, devDependencies: { "@types/node": "^22", "@types/react": "^18", "@types/react-dom": "^18", postcss: "^8", tailwindcss: "^3.4.17", typescript: "^5", }, }, null, 2, ) } // Generate globals.css with current customizations function generateGlobalsCss(settings: ExportSettings) { return `@tailwind base; @tailwind components; @tailwind utilities; :root { --background: 0 0% 100%; --foreground: 222.2 84% 4.9%; --card: 0 0% 100%; --card-foreground: 222.2 84% 4.9%; --popover: 0 0% 100%; --popover-foreground: 222.2 84% 4.9%; --primary: ${settings.primaryColor}; --primary-foreground: 210 40% 98%; --secondary: 210 40% 96%; --secondary-foreground: 222.2 84% 4.9%; --muted: 210 40% 96%; --muted-foreground: 215.4 16.3% 46.9%; --accent: 210 40% 96%; --accent-foreground: 222.2 84% 4.9%; --destructive: 0 84.2% 60.2%; --destructive-foreground: 210 40% 98%; --border: 214.3 31.8% 91.4%; --input: 214.3 31.8% 91.4%; --ring: ${settings.primaryColor}; --radius: ${settings.borderRadius}px; --background-primary: #ffffff; --background-secondary: #f9fafb; --text-primary: #111827; --primary-text: #ffffff; } .dark { --background: 222.2 84% 4.9%; --foreground: 210 40% 98%; --card: 222.2 84% 4.9%; --card-foreground: 210 40% 98%; --popover: 222.2 84% 4.9%; --popover-foreground: 210 40% 98%; --primary: ${settings.primaryColor}; --primary-foreground: 222.2 84% 4.9%; --secondary: 217.2 32.6% 17.5%; --secondary-foreground: 210 40% 98%; --muted: 217.2 32.6% 17.5%; --muted-foreground: 215 20.2% 65.1%; --accent: 217.2 32.6% 17.5%; --accent-foreground: 210 40% 98%; --destructive: 0 62.8% 30.6%; --destructive-foreground: 210 40% 98%; --border: 217.2 32.6% 17.5%; --input: 217.2 32.6% 17.5%; --ring: ${settings.primaryColor}; --background-primary: #0f172a; --background-secondary: #1e293b; --text-primary: #f1f5f9; --primary-text: #ffffff; } * { @apply border-border; } body { @apply bg-background text-foreground; font-family: ${settings.font}, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; } .text-crisp { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } ${ settings.materialType === "glass" ? ` .glass-effect { background: rgba(255, 255, 255, 0.1); backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.2); } .dark .glass-effect { background: rgba(0, 0, 0, 0.2); border: 1px solid rgba(255, 255, 255, 0.1); } ` : "" } /* Scrollbar Styles */ ::-webkit-scrollbar { width: 6px; height: 6px; } ::-webkit-scrollbar-track { background: transparent; } ::-webkit-scrollbar-thumb { background: hsl(var(--border)); border-radius: 3px; } ::-webkit-scrollbar-thumb:hover { background: hsl(var(--muted-foreground)); } ` } // Generate lib/utils.ts function generateUtils() { return `import { type ClassValue, clsx } from "clsx" import { twMerge } from "tailwind-merge" export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } ` } // Generate theme provider function generateThemeProvider() { return `"use client" import { ThemeProvider as NextThemesProvider } from "next-themes" import type { ThemeProviderProps } from "next-themes" import { useEffect } from "react" export function ThemeProvider({ children, ...props }: ThemeProviderProps) { // Force theme update on client side useEffect(() => { // This runs only on client side const savedTheme = localStorage.getItem("theme") || "light" // Set initial theme document.documentElement.classList.remove("light", "dark") document.documentElement.classList.add(savedTheme) document.documentElement.style.colorScheme = savedTheme }, []) return ( {children} ) } ` } // Generate Button component function generateButton() { return `"use client" import * as React from "react" import { cva, type VariantProps } from "class-variance-authority" import { cn } from "@/lib/utils" const buttonVariants = cva( "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", { variants: { variant: { default: "bg-primary text-[var(--primary-text)] hover:bg-primary/90", destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90", outline: "border border-input bg-background hover:bg-[var(--background-secondary)] hover:text-accent-foreground", secondary: "bg-[var(--background-secondary)] text-secondary-foreground hover:bg-[var(--background-secondary)]/80", ghost: "hover:bg-[var(--background-secondary)] hover:text-accent-foreground", link: "text-primary underline-offset-4 hover:underline", }, size: { default: "h-9 px-3 py-1.5", sm: "h-8 rounded-md px-2.5 text-xs", lg: "h-10 rounded-md px-6", icon: "h-9 w-9", }, }, defaultVariants: { variant: "default", size: "default", }, }, ) export interface ButtonProps extends React.ButtonHTMLAttributes, VariantProps { asChild?: boolean } const Button = React.forwardRef( ({ className, variant, size, asChild = false, ...props }, ref) => { return ) } ` } // Generate Starter Kit layout function generateStarterLayout() { return `import type { Metadata } from "next" import { Inter } from 'next/font/google' import { ThemeProvider } from "@/components/theme-provider" import "./globals.css" const inter = Inter({ subsets: ["latin"], variable: "--font-inter", display: "swap", }) export const metadata: Metadata = { title: "Percolate UI - Starter Kit", description: "A beautiful design system built with React and Tailwind CSS", } export default function RootLayout({ children, }: { children: React.ReactNode }) { return ( {children} ) } ` } // Generate Starter Kit main page function generateStarterPage() { return `"use client" import { Button } from "@/components/ui/button" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Badge } from "@/components/ui/badge" import { ThemeToggle } from "@/components/theme-toggle" import { CodeBracketIcon, SwatchIcon, SparklesIcon, CubeIcon, DocumentTextIcon, PaintBrushIcon, CheckCircleIcon } from "@heroicons/react/24/outline" export default function Home() { return (
{/* Header */}
P

Percolate UI

Starter Kit
{/* Main Content */}
{/* Hero Section */}

Welcome to Percolate UI

A beautiful design system built with React, TypeScript, and Tailwind CSS. Start building amazing interfaces today.

{/* Features Grid */}

Copy & Paste

No package installation required. Simply copy the code and paste it into your project.

Fully Customizable

Built with CSS variables and Tailwind CSS. Customize colors, spacing, and styling to match your brand.

Production Ready

Accessible, responsive, and built with TypeScript. Ready for your next production application.

{/* What's Included */}

What's included in Starter Kit

Essential Components

20+ production-ready components including buttons, cards, forms, and navigation elements.

Button Card Badge Form +16 more

Design Foundation

Complete design system with colors, typography, spacing, and theming support.

Colors Typography Dark Mode Responsive

TypeScript Support

Full TypeScript support with proper type definitions and IntelliSense.

TypeScript Type Safety IntelliSense

Best Practices

Built with accessibility, performance, and maintainability in mind.

WCAG 2.1 Performance SEO Ready
{/* Getting Started */}

Ready to get started?

This starter kit includes all the essential components and foundation elements you need to build beautiful interfaces. Perfect for learning and small projects.

{/* Footer */}
P
Percolate UI

Built with React, TypeScript, and Tailwind CSS

) } ` } // Main export function export async function exportStyleguide(options: { packageType: "free" | "pro" primaryColor?: string borderRadius?: number font?: string materialType?: string }) { try { const { packageType, primaryColor = "222.2 47.4% 11.2%", borderRadius = 6, font = "Inter", materialType = "flat", } = options const settings: ExportSettings = { primaryColor, borderRadius, font, materialType, packageType, } const zip = new JSZip() // Add configuration files zip.file("package.json", generatePackageJson(packageType)) zip.file("README.md", generateReadme(packageType, settings)) zip.file("next.config.mjs", generateNextConfig()) zip.file("tailwind.config.ts", generateTailwindConfig(settings)) zip.file("tsconfig.json", generateTsConfig()) zip.file("postcss.config.js", generatePostcssConfig()) // Add app files const appFolder = zip.folder("app")! appFolder.file("globals.css", generateGlobalsCss(settings)) appFolder.file("layout.tsx", packageType === "free" ? generateStarterLayout() : generateProLayout(settings)) appFolder.file("page.tsx", packageType === "free" ? generateStarterPage() : generateProPage()) // Add lib files const libFolder = zip.folder("lib")! libFolder.file("utils.ts", generateUtils()) // Add components const componentsFolder = zip.folder("components")! componentsFolder.file("theme-provider.tsx", generateThemeProvider()) componentsFolder.file("theme-toggle.tsx", generateThemeToggle()) // Add UI components const uiFolder = componentsFolder.folder("ui")! uiFolder.file("button.tsx", generateButton()) uiFolder.file("card.tsx", generateCard()) uiFolder.file("badge.tsx", generateBadge()) // Add more components for Pro version if (packageType === "pro") { // Add contexts const contextsFolder = zip.folder("contexts")! contextsFolder.file("sidebar-context.tsx", generateSidebarContext()) contextsFolder.file("color-context.tsx", generateColorContext()) contextsFolder.file("design-context.tsx", generateDesignContext()) contextsFolder.file("material-context.tsx", generateMaterialContext()) // Add more UI components uiFolder.file("input.tsx", generateInput()) uiFolder.file("dialog.tsx", generateDialog()) uiFolder.file("collapsible.tsx", generateCollapsible()) // Add layout components const layoutsFolder = componentsFolder.folder("layouts")! layoutsFolder.file("app-layout.tsx", generateAppLayout()) // Add other components componentsFolder.file("sidebar.tsx", generateSidebar()) componentsFolder.file("fixed-header.tsx", generateFixedHeader()) componentsFolder.file("right-sidebar.tsx", generateRightSidebar()) componentsFolder.file("right-sidebar-toggle.tsx", generateRightSidebarToggle()) } // Generate and download the zip const content = await zip.generateAsync({ type: "blob" }) const filename = `percolate-ui-${packageType}.zip` try { saveAs(content, filename) } catch (error) { // Fallback to native browser download const url = URL.createObjectURL(content) const link = document.createElement("a") link.href = url link.download = filename document.body.appendChild(link) link.click() document.body.removeChild(link) URL.revokeObjectURL(url) } return { success: true, filename } } catch (error) { console.error("Error exporting design system:", error) throw new Error(`Export failed: ${error}`) } } // Additional helper functions for configuration files function generateNextConfig() { return `/** @type {import('next').NextConfig} */ const nextConfig = {} export default nextConfig ` } function generateTailwindConfig(settings: ExportSettings) { return `import type { Config } from "tailwindcss" const config = { darkMode: ["class"], content: [ "./pages/**/*.{ts,tsx}", "./components/**/*.{ts,tsx}", "./app/**/*.{ts,tsx}", "./src/**/*.{ts,tsx}", ], prefix: "", theme: { container: { center: true, padding: "2rem", screens: { "2xl": "1400px", }, }, extend: { colors: { border: "hsl(var(--border))", input: "hsl(var(--input))", ring: "hsl(var(--ring))", background: "hsl(var(--background))", foreground: "hsl(var(--foreground))", "background-primary": "var(--background-primary)", "background-secondary": "var(--background-secondary)", "text-primary": "var(--text-primary)", "primary-text": "var(--primary-text)", primary: { DEFAULT: "hsl(var(--primary))", foreground: "hsl(var(--primary-foreground))", }, secondary: { DEFAULT: "hsl(var(--secondary))", foreground: "hsl(var(--secondary-foreground))", }, destructive: { DEFAULT: "hsl(var(--destructive))", foreground: "hsl(var(--destructive-foreground))", }, muted: { DEFAULT: "hsl(var(--muted))", foreground: "hsl(var(--muted-foreground))", }, accent: { DEFAULT: "hsl(var(--accent))", foreground: "hsl(var(--accent-foreground))", }, popover: { DEFAULT: "hsl(var(--popover))", foreground: "hsl(var(--popover-foreground))", }, card: { DEFAULT: "hsl(var(--card))", foreground: "hsl(var(--card-foreground))", }, }, borderRadius: { lg: "var(--radius)", md: "calc(var(--radius) - 2px)", sm: "calc(var(--radius) - 4px)", }, keyframes: { "accordion-down": { from: { height: "0" }, to: { height: "var(--radix-accordion-content-height)" }, }, "accordion-up": { from: { height: "var(--radix-accordion-content-height)" }, to: { height: "0" }, }, }, animation: { "accordion-down": "accordion-down 0.2s ease-out", "accordion-up": "accordion-up 0.2s ease-out", }, }, }, plugins: [require("tailwindcss-animate")], } satisfies Config export default config ` } function generateTsConfig() { return JSON.stringify( { compilerOptions: { target: "es5", lib: ["dom", "dom.iterable", "esnext"], allowJs: true, skipLibCheck: true, strict: true, forceConsistentCasingInFileNames: true, noEmit: true, esModuleInterop: true, module: "esnext", moduleResolution: "node", resolveJsonModule: true, isolatedModules: true, jsx: "preserve", incremental: true, plugins: [ { name: "next", }, ], paths: { "@/*": ["./*"], }, }, include: ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], exclude: ["node_modules"], }, null, 2, ) } function generatePostcssConfig() { return `module.exports = { plugins: { tailwindcss: {}, autoprefixer: {}, }, } ` } function generateReadme(packageType: "free" | "pro", settings: ExportSettings) { return `# Percolate UI ${packageType === "free" ? "Starter Kit" : "Full Package"} A beautiful design system built with React, TypeScript, and Tailwind CSS. ## 🚀 Quick Start ### Prerequisites - Node.js 18+ - npm, yarn, or pnpm ### Installation 1. **Install dependencies:** \`\`\`bash npm install # or yarn install # or pnpm install \`\`\` 2. **Start the development server:** \`\`\`bash npm run dev # or yarn dev # or pnpm dev \`\`\` 3. **Open your browser:** Navigate to [http://localhost:3000](http://localhost:3000) ## 📦 What's Included ${ packageType === "free" ? ` ### Starter Kit Features - **🎨 Design Foundation**: Colors, typography, spacing, and design tokens - **🧩 Essential Components**: 20+ production-ready React components - **🌙 Theming**: Light/dark mode support with smooth transitions - **📱 Responsive**: Mobile-first responsive design - **♿ Accessible**: WCAG 2.1 AA compliant components - **🔧 TypeScript**: Full TypeScript support with proper type definitions ### Components Included - Button, Card, Badge - Theme Toggle - Typography system - Color system - And more... ### Current Customizations Applied - **Primary Color**: ${settings.primaryColor} - **Border Radius**: ${settings.borderRadius}px - **Font Family**: ${settings.font} - **Material Type**: ${settings.materialType} ` : ` ### Full Package Features - **✨ Everything in Starter Kit** - **🎛️ Design Controls**: Live customization interface - **🏗️ Complete Layout**: Full application layout with sidebars - **📋 Advanced Components**: 35+ components including complex patterns - **🎨 Material System**: Flat and Glass material design options - **⚙️ Live Customization**: Real-time design system customization - **📱 Responsive Sidebars**: Collapsible navigation and control panels ### Additional Features - Live color customization - Typography controls - Material system (Flat/Glass) - Border radius controls - Component showcase - Advanced layout system ### Current Customizations Applied - **Primary Color**: ${settings.primaryColor} - **Border Radius**: ${settings.borderRadius}px - **Font Family**: ${settings.font} - **Material Type**: ${settings.materialType} ` } ## 🏗️ Project Structure \`\`\` ├── app/ # Next.js app directory │ ├── globals.css # Global styles with your customizations │ ├── layout.tsx # Root layout │ └── page.tsx # Home page ├── components/ # React components │ ├── ui/ # Base UI components │ ├── theme-provider.tsx │ └── theme-toggle.tsx ├── lib/ # Utility functions │ └── utils.ts # Tailwind merge utility ${ packageType === "pro" ? `├── contexts/ # React contexts for state management ├── layouts/ # Layout components` : "" } └── ... \`\`\` ## 🎨 Customization ### Colors Colors are defined in \`app/globals.css\` using CSS custom properties: \`\`\`css :root { --primary: ${settings.primaryColor}; --background-primary: #ffffff; /* ... */ } \`\`\` ### Typography Font family is configured in \`app/layout.tsx\`: \`\`\`tsx const inter = Inter({ subsets: ["latin"], variable: "--font-inter", display: "swap", }) \`\`\` ### Border Radius Global border radius is set to \`${settings.borderRadius}px\` and can be adjusted in the CSS variables. ## 🚀 Building for Production \`\`\`bash npm run build npm start \`\`\` ## 📚 Learn More - [Next.js Documentation](https://nextjs.org/docs) - [Tailwind CSS](https://tailwindcss.com) - [Radix UI](https://www.radix-ui.com) - [Heroicons](https://heroicons.com) ## 📄 License This project is licensed under the MIT License. --- **Built with ❤️ using Percolate UI** ` } // Pro version specific generators function generateProLayout(settings: ExportSettings) { return `import type { Metadata } from "next" import { Inter } from 'next/font/google' import { ThemeProvider } from "@/components/theme-provider" import { MaterialProvider } from "@/contexts/material-context" import { SidebarProvider } from "@/contexts/sidebar-context" import { ColorProvider from "@/contexts/color-context" import { DesignProvider from "@/contexts/design-context" import AppLayout from "@/components/layouts/app-layout" import "./globals.css" const inter = Inter({ subsets: ["latin"], variable: "--font-inter", display: "swap", }) export const metadata: Metadata = { title: "Percolate UI - Full Package", description: "A complete design system with live customization controls", } export default function RootLayout({ children, }: { children: React.ReactNode }) { return ( {children} ) } ` } function generateProPage() { return `"use client" import { useRef, useEffect } from "react" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { ArrowRightIcon, SwatchIcon, CubeIcon, DocumentTextIcon, CheckCircleIcon, CodeBracketIcon, PaintBrushIcon, CommandLineIcon, SparklesIcon, } from "@heroicons/react/24/outline" import Link from "next/link" // Introduction content component function IntroductionContent() { return (
{/* Hero Section */}

Percolate UI Design System

A complete design system with live customization controls. Explore components, customize colors and typography, and export your perfect design system.

Full Package - Live Customization Enabled
{/* Features Overview */}

Live Customization

Real-time design controls in the right sidebar. Customize colors, typography, and spacing instantly.

Complete Component Library

35+ production-ready components with advanced patterns and complex interactions.

Export Ready

Export your customized design system as a complete Next.js project ready for production.

{/* What's Included */}

Full Package Features

Complete Component Library

35+ components including advanced patterns, data tables, forms, and interactive elements.

Buttons Forms Tables Charts Modals +30 more

Live Design Controls

Real-time customization interface with color pickers, typography controls, and material options.

Color Picker Typography Spacing Materials Export

Advanced Layout System

Complete application layout with responsive sidebars, navigation, and content areas.

Responsive Sidebars Navigation Layouts

Production Ready

Enterprise-grade code quality with TypeScript, accessibility, and performance optimizations.

TypeScript WCAG 2.1 Performance SEO
{/* Quick Navigation */}
Foundation Colors, typography, spacing, and design principles that power the entire system.
Explore Foundation
Components Production-ready React components with TypeScript support and accessibility built-in.
Browse Components
Customization Use the right sidebar to customize colors, typography, and export your design system.
Start Customizing
{/* Technical Stack */}

Built with modern tools

Percolate UI is built on proven technologies and follows industry best practices for performance, accessibility, and developer experience.

React 19 TypeScript Tailwind CSS Radix UI Next.js 14 Heroicons
) } export default function HomePage() { const contentRef = useRef(null) useEffect(() => { // Force scroll to top on page load const forceScrollTop = () => { window.scrollTo(0, 0) document.documentElement.scrollTop = 0 document.body.scrollTop = 0 if (contentRef.current) { contentRef.current.scrollTop = 0 } } forceScrollTop() // Multiple attempts to ensure it works const timeouts = [ setTimeout(forceScrollTop, 0), setTimeout(forceScrollTop, 10), setTimeout(forceScrollTop, 50), setTimeout(forceScrollTop, 100], ] return () => { timeouts.forEach(clearTimeout) } }, []) return (
{/* Introduction Content */}
) } ` } // Context generators for Pro version function generateSidebarContext() { return `"use client" import React, { createContext, useContext, useState, useEffect } from "react" interface SidebarContextType { sidebarVisible: boolean setSidebarVisible: (visible: boolean) => void toggleSidebar: () => void } const SidebarContext = createContext(undefined) export function SidebarProvider({ children }: { children: React.ReactNode }) { const [sidebarVisible, setSidebarVisible] = useState(true) const toggleSidebar = () => { setSidebarVisible(!sidebarVisible) } return ( {children} ) } export function useSidebar() { const context = useContext(SidebarContext) if (!context) { throw new Error("useSidebar must be used within SidebarProvider") } return context } ` } function generateColorContext() { return `"use client" import React, { createContext, useContext, useState } from "react" interface ColorContextType { primaryColor: string setPrimaryColor: (color: string) => void } const ColorContext = createContext(undefined) export function ColorProvider({ children }: { children: React.ReactNode }) { const [primaryColor, setPrimaryColor] = useState("222.2 47.4% 11.2%") return ( {children} ) } export function useColorPalette() { const context = useContext(ColorContext) if (!context) { throw new Error("useColorPalette must be used within ColorProvider") } return context } ` } function generateDesignContext() { return `"use client" import React, { createContext, useContext, useState } from "react" interface DesignContextType { borderRadius: number setBorderRadius: (radius: number) => void font: string setFont: (font: string) => void } const DesignContext = createContext(undefined) export function DesignProvider({ children }: { children: React.ReactNode }) { const [borderRadius, setBorderRadius] = useState(6) const [font, setFont] = useState("Inter") return ( {children} ) } export function useDesign() { const context = useContext(DesignContext) if (!context) { throw new Error("useDesign must be used within DesignProvider") } return context } ` } function generateMaterialContext() { return `"use client" import React, { createContext, useContext, useState } from "react" interface Material { name: string description: string } interface MaterialContextType { selectedMaterial: Material setSelectedMaterial: (material: Material) => void materials: Material[] } const materials: Material[] = [ { name: "Flat", description: "Clean, minimal design" }, { name: "Glass", description: "Translucent glass effect" }, ] const MaterialContext = createContext(undefined) export function MaterialProvider({ children }: { children: React.ReactNode }) { const [selectedMaterial, setSelectedMaterial] = useState(materials[0]) return ( {children} ) } export function useMaterial() { const context = useContext(MaterialContext) if (!context) { throw new Error("useMaterial must be used within MaterialProvider") } return context } ` } // Additional UI components for Pro version function generateInput() { return `import * as React from "react" import { cn } from "@/lib/utils" export interface InputProps extends React.InputHTMLAttributes { error?: boolean } const Input = React.forwardRef( ({ className, type, error, ...props }, ref) => { return ( ) } ) Input.displayName = "Input" export { Input } ` } function generateDialog() { return `"use client" import * as React from "react" import * as DialogPrimitive from "@radix-ui/react-dialog" import { X } from 'lucide-react' import { cn } from "@/lib/utils" const Dialog = DialogPrimitive.Root const DialogTrigger = DialogPrimitive.Trigger const DialogPortal = DialogPrimitive.Portal const DialogClose = DialogPrimitive.Close const DialogOverlay = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef >(({ className, ...props }, ref) => ( )) DialogOverlay.displayName = DialogPrimitive.Overlay.displayName const DialogContent = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef >(({ className, ...props }, ref) => ( )) DialogContent.displayName = DialogPrimitive.Content.displayName const DialogHeader = ({ className, ...props }: React.HTMLAttributes) => (
) DialogHeader.displayName = "DialogHeader" const DialogFooter = ({ className, ...props }: React.HTMLAttributes) => (
) DialogFooter.displayName = "DialogFooter" const DialogTitle = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef >(({ className, ...props }, ref) => ( )) DialogTitle.displayName = DialogPrimitive.Title.displayName const DialogDescription = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef >(({ className, ...props }, ref) => ( )) DialogDescription.displayName = DialogPrimitive.Description.displayName export { Dialog, DialogPortal, DialogOverlay, DialogClose, DialogTrigger, DialogContent, DialogHeader, DialogFooter, DialogTitle, DialogDescription, } ` } function generateCollapsible() { return `"use client" import * as CollapsiblePrimitive from "@radix-ui/react-collapsible" const Collapsible = CollapsiblePrimitive.Root const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent export { Collapsible, CollapsibleTrigger, CollapsibleContent } ` } // Layout components for Pro version function generateAppLayout() { return `"use client" import type React from "react" import { useEffect, useState } from "react" import { Sidebar } from "@/components/sidebar" import { useSidebar from "@/contexts/sidebar-context" import { RightSidebar from "@/components/right-sidebar" import { FixedHeader from "@/components/fixed-header" import { RightSidebarToggle from "@/components/right-sidebar-toggle" // Create a wrapper component that uses the sidebar context function AppLayoutContent({ children }: { children: React.ReactNode }) { const { sidebarVisible, toggleSidebar } = useSidebar() const [isInitialized, setIsInitialized] = useState(false) // Add event listener for the toggle-sidebar event useEffect(() => { const handleToggleSidebar = () => { toggleSidebar() } window.addEventListener("toggle-sidebar", handleToggleSidebar) return () => { window.removeEventListener("toggle-sidebar", handleToggleSidebar) } }, [toggleSidebar]) // Mark as initialized after first render to enable transitions useEffect(() => { const timer = setTimeout(() => { setIsInitialized(true) }, 100) return () => clearTimeout(timer) }, []) return (
{/* Fixed Header */} {/* Left Sidebar */}
{/* Main Content Area */}
{children}
{/* Right Sidebar */}
{/* Right Sidebar Toggle */}
) } // Main layout component that sets up providers export default function AppLayout({ children }: { children: React.ReactNode }) { const [mounted, setMounted] = useState(false) useEffect(() => { setMounted(true) }, []) if (!mounted) { return (
Loading...
) } return {children} } ` } function generateSidebar() { return `"use client" import { useState, useEffect } from "react" import { usePathname } from "next/navigation" import Link from "next/link" import { cn } from "@/lib/utils" import { ChevronsLeft, ChevronDown } from 'lucide-react' import { useSidebar } from "@/contexts/sidebar-context" import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible" // Foundation items const foundationItems = [ { name: "Color", id: "color" }, { name: "Typography", id: "typography" }, { name: "Spacing", id: "spacing" }, { name: "Elevation", id: "elevation" }, ] // Component items const componentItems = [ { name: "Button", id: "buttons" }, { name: "Card", id: "cards" }, { name: "Badge", id: "badges" }, { name: "Input", id: "inputs" }, { name: "Dialog", id: "dialogs" }, ] export function Sidebar() { const pathname = usePathname() const [mounted, setMounted] = useState(false) const { setSidebarVisible } = useSidebar() const [openSections, setOpenSections] = useState({ foundation: true, components: true, }) const toggleSection = (section: string) => { setOpenSections((prev) => ({ ...prev, [section]: !prev[section], })) } useEffect(() => { setMounted(true) }, []) if (!mounted) { return null } const currentSection = pathname.replace("/", "") || "introduction" return (
{/* Logo and toggle header */}
P
Percolate UI
{/* Introduction section */}
{/* Foundation section */} toggleSection("foundation")}> FOUNDATION {/* Components section */} toggleSection("components")}> COMPONENTS
) } ` } function generateFixedHeader() { return `"use client" import { Button } from "@/components/ui/button" import { ThemeToggle } from "@/components/theme-toggle" import { Menu } from 'lucide-react' import { useSidebar } from "@/contexts/sidebar-context" export function FixedHeader() { const { sidebarVisible, toggleSidebar } = useSidebar() return (
{!sidebarVisible && ( )}
) } ` } function generateRightSidebar() { return `"use client" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Button } from "@/components/ui/button" import { Badge } from "@/components/ui/badge" import { useColorPalette } from "@/contexts/color-context" import { useDesign } from "@/contexts/design-context" import { useMaterial } from "@/contexts/material-context" export function RightSidebar() { const { primaryColor, setPrimaryColor } = useColorPalette() const { borderRadius, setBorderRadius, font, setFont } = useDesign() const { selectedMaterial, setSelectedMaterial, materials } = useMaterial() return (

Design Controls

Customize your design system in real-time

{/* Color Controls */} Primary Color Choose your brand's primary color
{["222.2 47.4% 11.2%", "221.2 83.2% 53.3%", "142.1 76.2% 36.3%"].map((color) => (
Current: {primaryColor}
{/* Border Radius */} Border Radius Adjust component roundness
{[0, 4, 6, 12].map((radius) => ( ))}
{/* Typography */} Typography Select your font family {["Inter", "Roboto", "Open Sans", "Poppins"].map((fontFamily) => ( ))} {/* Material Type */} Material Choose your design style {materials.map((material) => ( ))} {/* Export */} Export Download your customized design system
) } ` } function generateRightSidebarToggle() { return `"use client" import { Button } from "@/components/ui/button" import { Settings } from 'lucide-react' export function RightSidebarToggle() { return ( ) } ` }