From f188d3a27a316e0e821afcf507733d7cc253eb7e Mon Sep 17 00:00:00 2001 From: sean-eskerium Date: Mon, 22 Sep 2025 02:52:45 -0400 Subject: [PATCH] First implementation of the style guide. --- PRPs/interactive-style-guide.md | 967 ++++++++++++++ archon-ui-main/package-lock.json | 87 ++ archon-ui-main/package.json | 3 + archon-ui-main/src/App.tsx | 2 + .../src/components/layout/Navigation.tsx | 8 +- .../components/style-guide/StyleGuideView.tsx | 150 +++ .../configurators/ButtonConfigurator.tsx | 214 +++ .../configurators/FormConfigurator.tsx | 219 +++ .../configurators/GlassCardConfigurator.tsx | 327 +++++ .../configurators/ModalConfigurator.tsx | 235 ++++ .../configurators/TableConfigurator.tsx | 196 +++ .../configurators/ToggleConfigurator.tsx | 174 +++ .../examples/CompositionsExample.tsx | 638 +++++++++ .../style-guide/examples/PagesExample.tsx | 94 ++ .../style-guide/examples/WorkflowsExample.tsx | 137 ++ .../foundations/ColorsFoundation.tsx | 258 ++++ .../foundations/EffectsFoundation.tsx | 380 ++++++ .../foundations/SpacingFoundation.tsx | 322 +++++ .../foundations/TypographyFoundation.tsx | 346 +++++ .../patterns/DataDisplayPattern.tsx | 1180 +++++++++++++++++ .../style-guide/patterns/FeedbackPattern.tsx | 861 ++++++++++++ .../style-guide/patterns/LayoutsPattern.tsx | 743 +++++++++++ .../patterns/NavigationPattern.tsx | 866 ++++++++++++ .../style-guide/shared/CodeDisplay.tsx | 106 ++ .../style-guide/shared/ConfigPanel.tsx | 15 + .../style-guide/shared/ConfigRow.tsx | 17 + .../style-guide/shared/LivePreview.tsx | 64 + .../style-guide/shared/NavigationSidebar.tsx | 91 ++ .../style-guide/shared/PillNavigation.tsx | 162 +++ .../style-guide/standards/modalStandards.ts | 32 + .../src/components/style-guide/types/index.ts | 24 + .../src/features/ui/primitives/card.tsx | 82 ++ .../src/features/ui/primitives/label.tsx | 20 + .../features/ui/primitives/radio-group.tsx | 32 + .../src/features/ui/primitives/styles.ts | 270 +++- .../src/features/ui/primitives/switch.tsx | 35 + .../features/ui/primitives/toggle-group.tsx | 3 +- archon-ui-main/src/pages/StyleGuidePage.tsx | 8 + 38 files changed, 9341 insertions(+), 27 deletions(-) create mode 100644 PRPs/interactive-style-guide.md create mode 100644 archon-ui-main/src/components/style-guide/StyleGuideView.tsx create mode 100644 archon-ui-main/src/components/style-guide/configurators/ButtonConfigurator.tsx create mode 100644 archon-ui-main/src/components/style-guide/configurators/FormConfigurator.tsx create mode 100644 archon-ui-main/src/components/style-guide/configurators/GlassCardConfigurator.tsx create mode 100644 archon-ui-main/src/components/style-guide/configurators/ModalConfigurator.tsx create mode 100644 archon-ui-main/src/components/style-guide/configurators/TableConfigurator.tsx create mode 100644 archon-ui-main/src/components/style-guide/configurators/ToggleConfigurator.tsx create mode 100644 archon-ui-main/src/components/style-guide/examples/CompositionsExample.tsx create mode 100644 archon-ui-main/src/components/style-guide/examples/PagesExample.tsx create mode 100644 archon-ui-main/src/components/style-guide/examples/WorkflowsExample.tsx create mode 100644 archon-ui-main/src/components/style-guide/foundations/ColorsFoundation.tsx create mode 100644 archon-ui-main/src/components/style-guide/foundations/EffectsFoundation.tsx create mode 100644 archon-ui-main/src/components/style-guide/foundations/SpacingFoundation.tsx create mode 100644 archon-ui-main/src/components/style-guide/foundations/TypographyFoundation.tsx create mode 100644 archon-ui-main/src/components/style-guide/patterns/DataDisplayPattern.tsx create mode 100644 archon-ui-main/src/components/style-guide/patterns/FeedbackPattern.tsx create mode 100644 archon-ui-main/src/components/style-guide/patterns/LayoutsPattern.tsx create mode 100644 archon-ui-main/src/components/style-guide/patterns/NavigationPattern.tsx create mode 100644 archon-ui-main/src/components/style-guide/shared/CodeDisplay.tsx create mode 100644 archon-ui-main/src/components/style-guide/shared/ConfigPanel.tsx create mode 100644 archon-ui-main/src/components/style-guide/shared/ConfigRow.tsx create mode 100644 archon-ui-main/src/components/style-guide/shared/LivePreview.tsx create mode 100644 archon-ui-main/src/components/style-guide/shared/NavigationSidebar.tsx create mode 100644 archon-ui-main/src/components/style-guide/shared/PillNavigation.tsx create mode 100644 archon-ui-main/src/components/style-guide/standards/modalStandards.ts create mode 100644 archon-ui-main/src/components/style-guide/types/index.ts create mode 100644 archon-ui-main/src/features/ui/primitives/card.tsx create mode 100644 archon-ui-main/src/features/ui/primitives/label.tsx create mode 100644 archon-ui-main/src/features/ui/primitives/radio-group.tsx create mode 100644 archon-ui-main/src/features/ui/primitives/switch.tsx create mode 100644 archon-ui-main/src/pages/StyleGuidePage.tsx diff --git a/PRPs/interactive-style-guide.md b/PRPs/interactive-style-guide.md new file mode 100644 index 00000000..e6661ab9 --- /dev/null +++ b/PRPs/interactive-style-guide.md @@ -0,0 +1,967 @@ +# PRP: Interactive Style Guide Implementation + +## Overview +Implement a comprehensive interactive style guide page for the Archon UI system that provides configurators for glass morphism components, standardized modal types, layout templates, and generates copy-ready code with AI-friendly documentation. + +## Context for AI Implementation +This PRP provides complete implementation guidance for creating an interactive style guide at `/style-guide` route. The style guide will showcase existing Archon glass morphism components with interactive configurators, allowing developers to visually configure components and copy production-ready code. + +**CRITICAL LAYOUT CONSTRAINT**: The Archon app has a fixed left navigation sidebar and potential right chat sidebar. The style guide must work within these constraints: +- Main app navigation stays on the left (always visible) +- Style guide has its own internal navigation (sections/components) +- Layout templates must include collapsible sidebars that work within the main content area +- The "Sidebar Layout" template should demonstrate a collapsible project sidebar (like ProjectsView) + +**CRITICAL COMPONENT CONSISTENCY**: The style guide must use existing Radix UI primitives and extend them, not create new competing components. All components should import from `/features/ui/primitives/`. + +## Existing Patterns to Follow + +### Glass Morphism Styles (Reference) +- **Location**: `/archon-ui-main/src/features/ui/primitives/styles.ts` +- Glass backgrounds, borders, shadows with glow effects +- Priority colors system already defined +- Use existing `glassmorphism` and `compoundStyles` objects + +### Button Component (Reference) +- **Location**: `/archon-ui-main/src/features/ui/primitives/button.tsx` +- Variants: default, destructive, outline, ghost, link, cyan, knowledge +- Sizes: xs, sm, default, lg, icon +- Loading state support built-in + +### Modal Patterns (Reference) +- **Location**: `/archon-ui-main/src/features/ui/components/DeleteConfirmModal.tsx` +- Uses AlertDialog from primitives +- Size prop support (compact, default, large) +- Proper glass morphism styling + +### Routing Pattern (Reference) +- **Location**: `/archon-ui-main/src/App.tsx` +- Add new route: `} />` +- Follow existing page import pattern + +## Implementation Tasks + +### Task 0: Create Missing Radix Primitives (PRIORITY) +Before implementing the style guide, we need to create missing Radix primitives that the configurators will use: + +#### Create RadioGroup Primitive +```typescript +// /src/features/ui/primitives/radio-group.tsx +import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"; +import { Circle } from "lucide-react"; +import React from "react"; +import { cn, glassmorphism } from "./styles"; + +export const RadioGroup = RadioGroupPrimitive.Root; + +export const RadioGroupItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + + +)); +RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName; +``` + +#### Create Label Primitive +```typescript +// /src/features/ui/primitives/label.tsx +import * as LabelPrimitive from "@radix-ui/react-label"; +import React from "react"; +import { cn } from "./styles"; + +export const Label = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +Label.displayName = LabelPrimitive.Root.displayName; +``` + +#### Create Card Primitive +```typescript +// /src/features/ui/primitives/card.tsx +import React from "react"; +import { cn, glassmorphism } from "./styles"; + +interface CardProps extends React.HTMLAttributes { + glowColor?: keyof typeof glassmorphism.shadow.glow | 'none'; + edgePosition?: keyof typeof glassmorphism.edgeGlow | 'none'; + size?: keyof typeof glassmorphism.sizes.card; +} + +export const Card = React.forwardRef( + ({ className, glowColor = 'none', edgePosition = 'none', size = 'md', children, ...props }, ref) => { + return ( +
+ {children} +
+ ); + } +); +Card.displayName = "Card"; +``` + +#### Enhance styles.ts +```typescript +// Add to /src/features/ui/primitives/styles.ts + +export const glassmorphism = { + // ... existing code ... + + // Add edge glow positions for card configurator + edgeGlow: { + top: "border-t-2 border-t-cyan-400 relative before:content-[''] before:absolute before:top-0 before:left-0 before:right-0 before:h-[2px] before:bg-gradient-to-r before:from-transparent before:via-cyan-400 before:to-transparent", + left: "border-l-2 border-l-cyan-400 relative before:content-[''] before:absolute before:top-0 before:left-0 before:bottom-0 before:w-[2px] before:bg-gradient-to-b before:from-transparent before:via-cyan-400 before:to-transparent", + right: "border-r-2 border-r-cyan-400 relative before:content-[''] before:absolute before:top-0 before:right-0 before:bottom-0 before:w-[2px] before:bg-gradient-to-b before:from-transparent before:via-cyan-400 before:to-transparent", + bottom: "border-b-2 border-b-cyan-400 relative before:content-[''] before:absolute before:bottom-0 before:left-0 before:right-0 before:h-[2px] before:bg-gradient-to-r before:from-transparent before:via-cyan-400 before:to-transparent", + all: "border-2 border-cyan-400 relative before:content-[''] before:absolute before:inset-0 before:rounded-lg before:p-[2px] before:bg-gradient-to-r before:from-cyan-400 before:via-cyan-500 before:to-cyan-400 before:-z-10", + none: "" + }, + + // Add configurable sizes for cards + sizes: { + card: { + sm: "p-4 max-w-sm", + md: "p-6 max-w-md", + lg: "p-8 max-w-lg", + xl: "p-10 max-w-xl" + } + }, + + // Ensure all glow colors are available + shadow: { + // ... existing shadow code ... + glow: { + purple: "shadow-[0_0_10px_2px_rgba(168,85,247,0.4)] dark:shadow-[0_0_20px_5px_rgba(168,85,247,0.7)]", + blue: "shadow-[0_0_10px_2px_rgba(59,130,246,0.4)] dark:shadow-[0_0_20px_5px_rgba(59,130,246,0.7)]", + green: "shadow-[0_0_10px_2px_rgba(16,185,129,0.4)] dark:shadow-[0_0_20px_5px_rgba(16,185,129,0.7)]", + red: "shadow-[0_0_10px_2px_rgba(239,68,68,0.4)] dark:shadow-[0_0_20px_5px_rgba(239,68,68,0.7)]", + orange: "shadow-[0_0_10px_2px_rgba(251,146,60,0.4)] dark:shadow-[0_0_20px_5px_rgba(251,146,60,0.7)]", + cyan: "shadow-[0_0_10px_2px_rgba(34,211,238,0.4)] dark:shadow-[0_0_20px_5px_rgba(34,211,238,0.7)]", + pink: "shadow-[0_0_10px_2px_rgba(236,72,153,0.4)] dark:shadow-[0_0_20px_5px_rgba(236,72,153,0.7)]" + } + } +}; +``` + +### Task 1: Create Page Structure and Routing +```typescript +// 1. Create /src/pages/StyleGuidePage.tsx +// 2. Add route in App.tsx +// 3. Add navigation link in MainLayout navigation +``` + +### Task 2: Create Base Components Structure +``` +/src/components/style-guide/ +├── shared/ +│ ├── NavigationSidebar.tsx # 4 sections with expandable items +│ ├── LivePreview.tsx # Preview container with zoom controls +│ ├── CodeDisplay.tsx # Syntax highlighted code with copy +│ └── ConfigPanel.tsx # Configuration controls container +``` + +### Task 3: Implement Component Configurators +``` +/src/components/style-guide/configurators/ +├── GlassCardConfigurator.tsx # Glow colors, edge positions, sizes +├── ButtonConfigurator.tsx # All variants, sizes, states +├── ModalConfigurator.tsx # 6 standard types showcase +├── TableConfigurator.tsx # Table with glass effects +├── FormConfigurator.tsx # Input states and validation +└── ToggleConfigurator.tsx # PowerButton variations +``` + +### Task 4: Create Modal Standards +```typescript +// /src/components/style-guide/standards/modalStandards.ts +export const MODAL_TYPES = { + confirmation: { size: "sm", glowColor: "red", purpose: "Destructive actions" }, + formCreate: { size: "md", glowColor: "green", purpose: "Creating resources" }, + formEdit: { size: "md", glowColor: "blue", purpose: "Editing resources" }, + display: { size: "lg", glowColor: "purple", purpose: "Detailed information" }, + codeViewer: { size: "xl", glowColor: "cyan", purpose: "Code display" }, + settings: { size: "lg", glowColor: "blue", purpose: "App settings" } +}; +``` + +### Task 5: Implement Layout Templates +``` +/src/components/style-guide/layout-templates/ +├── DashboardTemplate.tsx # Grid of cards/widgets +├── SidebarTemplate.tsx # Collapsible sidebar + main (like ProjectsView) +├── KanbanTemplate.tsx # Column-based organization +├── TableViewTemplate.tsx # Data table with actions +└── CenteredFormTemplate.tsx # Single focus area +``` + +**SidebarTemplate Special Requirements:** +- Must show a collapsible sidebar within the main content area +- Sidebar toggles between top position (cards) and left position (list) +- Similar to ProjectsView with project cards that can be toggled to sidebar +- Include toggle button to switch between layouts +- Sidebar width: 280px when on left, full width when on top + +### Task 6: Code Generation System +```typescript +// Each configurator must: +// 1. Generate real-time code based on configuration +// 2. Include all imports +// 3. Add AI context comments with decision trees +// 4. Provide copy-to-clipboard functionality +``` + +## Component Implementation Details + +### ConfigPanel Component (Uses Card Primitive) +```typescript +// /src/components/style-guide/shared/ConfigPanel.tsx +import { Card } from '@/features/ui/primitives/card'; +import { cn } from '@/features/ui/primitives/styles'; + +interface ConfigPanelProps { + title?: string; + children: React.ReactNode; + className?: string; +} + +export const ConfigPanel = ({ title, children, className }: ConfigPanelProps) => ( + + {title &&

{title}

} + {children} +
+); +``` + +### GlassCardConfigurator (Using All Primitives) +```typescript +// Configuration Options: +- glowColor: ["purple", "blue", "green", "orange", "red", "none"] +- edgePosition: ["top", "left", "right", "bottom", "all", "none"] +- size: ["sm", "md", "lg", "xl"] + +// Generated Code must include: +/** + * 🤖 AI CONTEXT: GlassCard Component + * PURPOSE: Container with glass morphism effect + * WHEN TO USE: Primary content containers, cards, panels + * WHEN NOT TO USE: Backgrounds, layout wrappers + * + * DECISION TREE: + * - If primary content → glowColor="purple" + * - If success message → glowColor="green" + * - If error/danger → glowColor="red" + */ +``` + +### NavigationSidebar Structure +```typescript +const NAVIGATION = { + foundations: { + label: "Foundations", + items: ["Colors", "Typography", "Spacing", "Effects"] + }, + components: { + label: "Components", + items: ["Cards", "Buttons", "Forms", "Tables", "Modals", "Toggles"] + }, + patterns: { + label: "Patterns", + items: ["Layouts", "Feedback", "Navigation", "Data Display"] + }, + examples: { + label: "Examples", + items: ["Compositions", "Pages", "Workflows"] + } +}; +``` + +### LivePreview Component +```typescript +// Implementation: /src/components/style-guide/shared/LivePreview.tsx +import { useState } from 'react'; +import { ZoomIn, ZoomOut, RotateCcw } from 'lucide-react'; +import { Button } from '@/features/ui/primitives/button'; +import { cn } from '@/features/ui/primitives/styles'; + +interface LivePreviewProps { + children: React.ReactNode; + className?: string; + minHeight?: string; +} + +export const LivePreview = ({ children, className, minHeight = "400px" }: LivePreviewProps) => { + const [zoom, setZoom] = useState(100); + + return ( +
+ {/* Zoom Controls */} +
+ + + +
+ + {/* Grid Background */} +
+
+ {children} +
+
+
+ ); +}; +``` + +### CodeDisplay Component +```typescript +// Implementation: /src/components/style-guide/shared/CodeDisplay.tsx +import { useState } from 'react'; +import { Check, Copy } from 'lucide-react'; +import { Button } from '@/features/ui/primitives/button'; +import { cn } from '@/features/ui/primitives/styles'; + +interface CodeDisplayProps { + code: string; + language?: 'typescript' | 'jsx' | 'css'; + showLineNumbers?: boolean; + className?: string; +} + +export const CodeDisplay = ({ + code, + language = 'typescript', + showLineNumbers = false, + className +}: CodeDisplayProps) => { + const [copied, setCopied] = useState(false); + + const handleCopy = async () => { + await navigator.clipboard.writeText(code); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + }; + + const lines = code.split('\n'); + + // Basic syntax highlighting with regex + const highlightCode = (line: string) => { + // Escape HTML + line = line.replace(/&/g, '&').replace(//g, '>'); + + // Keywords + line = line.replace( + /\b(import|export|from|const|let|var|function|return|if|else|interface|type|class|extends|implements)\b/g, + '$1' + ); + + // Strings + line = line.replace( + /(["'`])([^"'`]*)\1/g, + '$1$2$1' + ); + + // Comments + line = line.replace( + /(\/\/.*$|\/\*.*\*\/)/g, + '$1' + ); + + // JSX tags + line = line.replace( + /<([A-Z][A-Za-z0-9]*)(\s|>|\/>)/g, + '<$1$2' + ); + + // Props + line = line.replace( + /(\w+)=/g, + '$1=' + ); + + return line; + }; + + return ( +
+ {/* Copy Button */} + + + {/* Code Content */} +
+        
+          {lines.map((line, index) => (
+            
+ {showLineNumbers && ( + + {index + 1} + + )} + +
+ ))} +
+
+
+ ); +}; +``` + +### Code Generation System (Updated with Proper Imports) +```typescript +// Detailed implementation for code generation +// Example: /src/components/style-guide/configurators/GlassCardConfigurator.tsx + +import { useState } from 'react'; +import { Card } from '@/features/ui/primitives/card'; +import { Button } from '@/features/ui/primitives/button'; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/features/ui/primitives/select'; +import { RadioGroup, RadioGroupItem } from '@/features/ui/primitives/radio-group'; +import { Label } from '@/features/ui/primitives/label'; +import { LivePreview } from '../shared/LivePreview'; +import { CodeDisplay } from '../shared/CodeDisplay'; +import { ConfigPanel } from '../shared/ConfigPanel'; +import { glassmorphism } from '@/features/ui/primitives/styles'; + +interface GlassCardConfig { + glowColor: 'purple' | 'blue' | 'green' | 'orange' | 'red' | 'none'; + edgePosition: 'top' | 'left' | 'right' | 'bottom' | 'all' | 'none'; + size: 'sm' | 'md' | 'lg' | 'xl'; + content: string; +} + +export const GlassCardConfigurator = () => { + const [config, setConfig] = useState({ + glowColor: 'purple', + edgePosition: 'top', + size: 'md', + content: 'Your content here' + }); + + const generateCode = (config: GlassCardConfig) => { + const imports = `import { Card } from '@/features/ui/primitives/card';`; + + const aiContext = `/** + * 🤖 AI CONTEXT: GlassCard Component + * + * PURPOSE: Container with glass morphism effect for primary content + * WHEN TO USE: Feature cards, content sections, important information displays + * WHEN NOT TO USE: Backgrounds, full-page layouts, navigation elements + * + * DECISION TREE: + * - If primary/featured content → glowColor="purple" + * - If success state/creation → glowColor="green" + * - If error/danger/deletion → glowColor="red" + * - If informational/edit → glowColor="blue" + * - If warning/caution → glowColor="orange" + * + * SEMANTIC COLORS: + * - purple: Primary actions, featured content, main CTAs + * - green: Success states, creation, positive feedback + * - red: Destructive actions, errors, critical alerts + * - blue: Information, editing, secondary actions + * - orange: Warnings, important notices, caution states + * + * EDGE POSITION GUIDELINES: + * - top: Default, draws eye downward into content + * - left: For sidebar items or navigation cards + * - right: For action panels or secondary info + * - bottom: For footer-like content or summaries + * - all: For highly important or selected states + * - none: For subtle, non-emphasized containers + */`; + + const component = `export const MyCard = ({ children }) => { + return ( + + {children} + + ); +};`; + + return `${imports}\n\n${aiContext}\n\n${component}`; + }; + + return ( +
+ {/* Left side: Configuration */} +
+ +
+ {/* Glow Color */} +
+ + +
+ + {/* Edge Position */} +
+ + setConfig({...config, edgePosition: value as any})} + > +
+ {['top', 'left', 'right', 'bottom', 'all', 'none'].map(position => ( +
+ + +
+ ))} +
+
+
+ + {/* Size */} +
+ + setConfig({...config, size: value as any})} + > +
+ {['sm', 'md', 'lg', 'xl'].map(size => ( +
+ + +
+ ))} +
+
+
+
+
+ + {/* Live Preview */} + + +

Glass Card Example

+

+ {config.content} +

+
+
+
+ + {/* Right side: Generated Code */} +
+

Generated Code

+ +
+
+ ); +}; +``` + +### SidebarTemplate Implementation (Using Primitives) +```typescript +// /src/components/style-guide/layout-templates/SidebarTemplate.tsx +import { useState } from 'react'; +import { ChevronLeft, ChevronRight, LayoutGrid, List } from 'lucide-react'; +import { Button } from '@/features/ui/primitives/button'; +import { Card } from '@/features/ui/primitives/card'; +import { cn } from '@/features/ui/primitives/styles'; +import { CodeDisplay } from '../shared/CodeDisplay'; + +export const SidebarTemplate = () => { + const [sidebarPosition, setSidebarPosition] = useState<'top' | 'left'>('top'); + const [sidebarCollapsed, setSidebarCollapsed] = useState(false); + + const items = [ + { id: '1', title: 'Project Alpha', status: 'active' }, + { id: '2', title: 'Project Beta', status: 'pending' }, + { id: '3', title: 'Project Gamma', status: 'completed' }, + ]; + + const generateCode = () => { + return `import { useState } from 'react'; +import { motion, AnimatePresence } from 'framer-motion'; +import { Button } from '@/features/ui/primitives/button'; +import { Card } from '@/features/ui/primitives/card'; + +export const SidebarLayout = () => { + const [position, setPosition] = useState<'top' | 'left'>('top'); + const [collapsed, setCollapsed] = useState(false); + + return ( +
+ {/* Toggle Button */} +
+ +
+ +
+ {/* Sidebar Content */} + + + {/* Sidebar items here */} + + + + {/* Main Content Area */} +
+ {/* Main content here */} +
+
+
+ ); +};`; + }; + + return ( +
+
+

Sidebar Layout Template

+ +
+ + {/* Live Demo */} +
+
+ {/* Sidebar */} +
+ {sidebarPosition === 'top' ? ( +
+ {items.map(item => ( + +

{item.title}

+

{item.status}

+
+ ))} +
+ ) : ( +
+ {sidebarPosition === 'left' && ( + + )} + {items.map(item => ( + + {!sidebarCollapsed ? ( + <> +

{item.title}

+

{item.status}

+ + ) : ( +
+ {item.title[0]} +
+ )} +
+ ))} +
+ )} +
+ + {/* Main Content */} +
+
+

Main Content Area

+

This is where your main content would go

+

Sidebar is currently: {sidebarPosition === 'top' ? 'Top' : `Left (${sidebarCollapsed ? 'Collapsed' : 'Expanded'})`}

+
+
+
+
+ + +
+ ); +}; +``` + +## Confidence Score: 10/10 + +The PRP provides comprehensive implementation guidance with: +- **Radix primitive creation tasks** for missing components +- **Style enhancements** to support configurator needs +- **Consistent imports** from `/features/ui/primitives/` +- **Complete code examples** using actual primitives +- **Clear implementation order** with primitive creation first + +The score is 10/10 because: +- **Component consistency**: All configurators use existing primitives +- **No duplicate components**: Reuses existing infrastructure +- **Enhanced flexibility**: styles.ts gets necessary additions +- **Complete primitive set**: Creates missing RadioGroup, Label, and Card +- **Production ready**: Uses same components developers will use + +This PRP ensures the style guide showcases actual Archon components, not separate demo versions. + +## Validation Gates + +```bash +# Frontend checks +cd archon-ui-main +npm run lint # No linting errors +npx tsc --noEmit # No TypeScript errors +npm run test # All tests pass + +# Verify primitives work +# Check that all new primitives render correctly +# Verify Card primitive replaces old Card.tsx +# Test RadioGroup and Label components +# Confirm styles.ts enhancements work + +# Verify routes work +# Navigate to http://localhost:3737/style-guide +# Verify all configurators render +# Test code generation and copy functionality +# Check responsive behavior +``` + +## Dependencies +- Existing Archon UI primitives and components +- Tailwind CSS (already configured) +- Lucide React icons (already installed) +- React Router (already installed) +- Radix UI packages (already installed): + - @radix-ui/react-radio-group + - @radix-ui/react-label +- For syntax highlighting: Use simple regex-based solution (no external libs) + +## File Creation Order +1. **Create missing primitives first** (RadioGroup, Label, Card) +2. **Enhance styles.ts** with edgeGlow and sizes +3. Create page and add route +4. Build shared components (NavigationSidebar, LivePreview, CodeDisplay, ConfigPanel) +5. Implement GlassCardConfigurator first (as template) +6. Add ButtonConfigurator +7. Create modal standards and ModalConfigurator +8. Add remaining configurators +9. Implement layout templates +10. Add AI context comments throughout + +## Key Implementation Notes + +### State Management +- Use React hooks (useState) for configuration state +- Each configurator manages its own state +- URL params for sharing configurations (optional enhancement) + +### Import Consistency +- ALWAYS import from `/features/ui/primitives/` for UI components +- Never create duplicate components +- Use the Card primitive for all card needs +- Import glassmorphism styles from styles.ts + +### Performance Considerations +- Lazy load configurators that aren't visible +- Debounce configuration changes (200ms) +- Use React.memo for expensive preview renders +- Limit blur effects to 3 layers maximum + +## Success Criteria +- [ ] All primitives created and working +- [ ] Old Card.tsx replaced with new primitive +- [ ] All routes work and page loads without errors +- [ ] Navigation sidebar with 4 main sections +- [ ] GlassCard configurator with live preview using Card primitive +- [ ] Button configurator with all variants +- [ ] 6 modal types clearly documented +- [ ] 5 layout templates available +- [ ] Code generation with AI comments +- [ ] Copy-to-clipboard works +- [ ] Responsive design functions properly +- [ ] No TypeScript or linting errors +- [ ] All imports from primitives folder + +## Common Pitfalls to Avoid +- Don't create new component variants - use existing ones +- Don't duplicate components - use primitives +- Don't add external libraries for syntax highlighting initially +- Don't forget AI context comments in generated code +- Don't nest glass effects more than 3 levels +- Don't hardcode values - use configuration objects +- Don't import from old `/components/ui/` folder + +## Testing Approach +1. Manual testing of all configurators +2. Verify code generation accuracy +3. Test copy-to-clipboard functionality +4. Check responsive breakpoints +5. Validate AI comments are included +6. Test with actual AI assistant to verify comments help +7. Verify all imports use primitives + +## References +- Button component: `/archon-ui-main/src/features/ui/primitives/button.tsx` +- Glass morphism styles: `/archon-ui-main/src/features/ui/primitives/styles.ts` +- Select primitive: `/archon-ui-main/src/features/ui/primitives/select.tsx` +- Modal example: `/archon-ui-main/src/features/ui/components/DeleteConfirmModal.tsx` +- Routing: `/archon-ui-main/src/App.tsx` +- Layout: `/archon-ui-main/src/components/layout/MainLayout.tsx` +- Projects View (sidebar example): `/archon-ui-main/src/features/projects/views/ProjectsView.tsx` +- Old Card to replace: `/archon-ui-main/src/components/ui/Card.tsx` \ No newline at end of file diff --git a/archon-ui-main/package-lock.json b/archon-ui-main/package-lock.json index a6653753..4c30a7ee 100644 --- a/archon-ui-main/package-lock.json +++ b/archon-ui-main/package-lock.json @@ -12,8 +12,11 @@ "@radix-ui/react-alert-dialog": "^1.1.15", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dropdown-menu": "^2.1.16", + "@radix-ui/react-label": "^2.1.7", "@radix-ui/react-popover": "^1.1.15", + "@radix-ui/react-radio-group": "^1.3.8", "@radix-ui/react-select": "^2.2.6", + "@radix-ui/react-switch": "^1.2.6", "@radix-ui/react-tabs": "^1.1.13", "@radix-ui/react-toast": "^1.2.15", "@radix-ui/react-tooltip": "^1.2.8", @@ -2745,6 +2748,29 @@ } } }, + "node_modules/@radix-ui/react-label": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.7.tgz", + "integrity": "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-menu": { "version": "2.1.16", "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.16.tgz", @@ -2925,6 +2951,38 @@ } } }, + "node_modules/@radix-ui/react-radio-group": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.3.8.tgz", + "integrity": "sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-roving-focus": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz", @@ -3040,6 +3098,35 @@ } } }, + "node_modules/@radix-ui/react-switch": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.2.6.tgz", + "integrity": "sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-tabs": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.13.tgz", diff --git a/archon-ui-main/package.json b/archon-ui-main/package.json index 31c07574..69d637b5 100644 --- a/archon-ui-main/package.json +++ b/archon-ui-main/package.json @@ -32,8 +32,11 @@ "@radix-ui/react-alert-dialog": "^1.1.15", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dropdown-menu": "^2.1.16", + "@radix-ui/react-label": "^2.1.7", "@radix-ui/react-popover": "^1.1.15", + "@radix-ui/react-radio-group": "^1.3.8", "@radix-ui/react-select": "^2.2.6", + "@radix-ui/react-switch": "^1.2.6", "@radix-ui/react-tabs": "^1.1.13", "@radix-ui/react-toast": "^1.2.15", "@radix-ui/react-tooltip": "^1.2.8", diff --git a/archon-ui-main/src/App.tsx b/archon-ui-main/src/App.tsx index 1d4e22d3..6a7f1439 100644 --- a/archon-ui-main/src/App.tsx +++ b/archon-ui-main/src/App.tsx @@ -13,6 +13,7 @@ import { ToastProvider } from './features/ui/components/ToastProvider'; import { SettingsProvider, useSettings } from './contexts/SettingsContext'; import { TooltipProvider } from './features/ui/primitives/tooltip'; import { ProjectPage } from './pages/ProjectPage'; +import StyleGuidePage from './pages/StyleGuidePage'; import { DisconnectScreenOverlay } from './components/DisconnectScreenOverlay'; import { ErrorBoundaryWithBugReport } from './components/bug-report/ErrorBoundaryWithBugReport'; import { MigrationBanner } from './components/ui/MigrationBanner'; @@ -29,6 +30,7 @@ const AppRoutes = () => { } /> } /> } /> + } /> {projectsEnabled ? ( <> } /> diff --git a/archon-ui-main/src/components/layout/Navigation.tsx b/archon-ui-main/src/components/layout/Navigation.tsx index e2f1e806..e79a050e 100644 --- a/archon-ui-main/src/components/layout/Navigation.tsx +++ b/archon-ui-main/src/components/layout/Navigation.tsx @@ -1,4 +1,4 @@ -import { BookOpen, Settings } from "lucide-react"; +import { BookOpen, Palette, Settings } from "lucide-react"; import type React from "react"; import { Link, useLocation } from "react-router-dom"; // TEMPORARY: Use old SettingsContext until settings are migrated @@ -54,6 +54,12 @@ export function Navigation({ className }: NavigationProps) { label: "MCP Server", enabled: true, }, + { + path: "/style-guide", + icon: , + label: "Style Guide", + enabled: true, + }, { path: "/settings", icon: , diff --git a/archon-ui-main/src/components/style-guide/StyleGuideView.tsx b/archon-ui-main/src/components/style-guide/StyleGuideView.tsx new file mode 100644 index 00000000..fc67422a --- /dev/null +++ b/archon-ui-main/src/components/style-guide/StyleGuideView.tsx @@ -0,0 +1,150 @@ +import { useState } from 'react'; +import { Palette, Component, Layout, Code } from 'lucide-react'; +import { PillNavigation } from './shared/PillNavigation'; +import { ThemeToggle } from '../ui/ThemeToggle'; +import { GlassCardConfigurator } from './configurators/GlassCardConfigurator'; +import { ButtonConfigurator } from './configurators/ButtonConfigurator'; +import { ModalConfigurator } from './configurators/ModalConfigurator'; +import { FormConfigurator } from './configurators/FormConfigurator'; +import { TableConfigurator } from './configurators/TableConfigurator'; +import { ToggleConfigurator } from './configurators/ToggleConfigurator'; +import { ColorsFoundation } from './foundations/ColorsFoundation'; +import { TypographyFoundation } from './foundations/TypographyFoundation'; +import { SpacingFoundation } from './foundations/SpacingFoundation'; +import { EffectsFoundation } from './foundations/EffectsFoundation'; +import { LayoutsPattern } from './patterns/LayoutsPattern'; +import { FeedbackPattern } from './patterns/FeedbackPattern'; +import { NavigationPattern } from './patterns/NavigationPattern'; +import { DataDisplayPattern } from './patterns/DataDisplayPattern'; +import { CompositionsExample } from './examples/CompositionsExample'; +import { PagesExample } from './examples/PagesExample'; +import { WorkflowsExample } from './examples/WorkflowsExample'; + +const FOUNDATION_TABS = [ + { id: 'Colors', label: 'Colors', component: ColorsFoundation }, + { id: 'Typography', label: 'Typography', component: TypographyFoundation }, + { id: 'Spacing', label: 'Spacing', component: SpacingFoundation }, + { id: 'Effects', label: 'Effects', component: EffectsFoundation }, +]; + +const COMPONENT_TABS = [ + { id: 'Cards', label: 'Cards', component: GlassCardConfigurator }, + { id: 'Buttons', label: 'Buttons', component: ButtonConfigurator }, + { id: 'Forms', label: 'Forms', component: FormConfigurator }, + { id: 'Tables', label: 'Tables', component: TableConfigurator }, + { id: 'Modals', label: 'Modals', component: ModalConfigurator }, + { id: 'Toggles', label: 'Toggles', component: ToggleConfigurator }, +]; + +const PATTERN_TABS = [ + { id: 'Layouts', label: 'Layouts', component: LayoutsPattern }, + { id: 'Feedback', label: 'Feedback', component: FeedbackPattern }, + { id: 'Navigation', label: 'Navigation', component: NavigationPattern }, + { id: 'Data Display', label: 'Data Display', component: DataDisplayPattern }, +]; + +const EXAMPLE_TABS = [ + { id: 'Compositions', label: 'Compositions', component: CompositionsExample }, + { id: 'Pages', label: 'Pages', component: PagesExample }, + { id: 'Workflows', label: 'Workflows', component: WorkflowsExample }, +]; + +export const StyleGuideView = () => { + const [selectedSection, setSelectedSection] = useState('foundations'); + const [selectedComponent, setSelectedComponent] = useState('Colors'); + + const handleSectionChange = (section: string) => { + setSelectedSection(section); + // Reset to first item of new section + if (section === 'foundations') setSelectedComponent('Colors'); + else if (section === 'components') setSelectedComponent('Cards'); + else if (section === 'patterns') setSelectedComponent('Layouts'); + else if (section === 'examples') setSelectedComponent('Compositions'); + else setSelectedComponent(null); + }; + + const renderContent = () => { + if (selectedSection === 'foundations' && selectedComponent) { + const tab = FOUNDATION_TABS.find(t => t.id === selectedComponent); + if (tab) { + const FoundationComponent = tab.component; + return ; + } + } + + if (selectedSection === 'components' && selectedComponent) { + const tab = COMPONENT_TABS.find(t => t.id === selectedComponent); + if (tab) { + const ComponentConfigurator = tab.component; + return ; + } + } + + if (selectedSection === 'patterns' && selectedComponent) { + const tab = PATTERN_TABS.find(t => t.id === selectedComponent); + if (tab) { + const PatternComponent = tab.component; + return ; + } + } + + if (selectedSection === 'examples' && selectedComponent) { + const tab = EXAMPLE_TABS.find(t => t.id === selectedComponent); + if (tab) { + const ExampleComponent = tab.component; + return ; + } + } + + // Default content for other sections or no selection + const sectionContent = { + foundations: { icon: , text: "Select a foundation element from the dropdown above" }, + components: { icon: , text: "Select a component from the dropdown above" }, + patterns: { icon: , text: "Select a pattern from the dropdown above" }, + examples: { icon: , text: "Select an example from the dropdown above" } + }; + + const content = sectionContent[selectedSection as keyof typeof sectionContent]; + + return ( +
+ {content.icon} +

{content.text}

+
+ ); + }; + + return ( +
+ {/* Header */} +
+ {/* Theme Toggle in top right */} +
+ +
+ +
+

Interactive Style Guide

+

+ Configure and preview Archon's glassmorphism components with live code generation. +

+
+
+ + {/* Pill Navigation */} +
+ +
+ + {/* Content */} +
+ {renderContent()} +
+
+ ); +}; \ No newline at end of file diff --git a/archon-ui-main/src/components/style-guide/configurators/ButtonConfigurator.tsx b/archon-ui-main/src/components/style-guide/configurators/ButtonConfigurator.tsx new file mode 100644 index 00000000..a5d33a96 --- /dev/null +++ b/archon-ui-main/src/components/style-guide/configurators/ButtonConfigurator.tsx @@ -0,0 +1,214 @@ +import { useState } from 'react'; +import { Button } from '@/features/ui/primitives/button'; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/features/ui/primitives/select'; +import { Switch } from '@/features/ui/primitives/switch'; +import { Input } from '@/features/ui/primitives/input'; +import { LivePreview } from '../shared/LivePreview'; +import { CodeDisplay } from '../shared/CodeDisplay'; +import { ConfigPanel } from '../shared/ConfigPanel'; +import { ConfigRow } from '../shared/ConfigRow'; +import { Loader2, Download, Eye, Code } from 'lucide-react'; +import type { ButtonVariant, ButtonSize } from '../types'; + +interface ButtonConfig { + variant: ButtonVariant; + size: ButtonSize; + loading: boolean; + disabled: boolean; + withIcon: boolean; + text: string; +} + +export const ButtonConfigurator = () => { + const [config, setConfig] = useState({ + variant: 'default', + size: 'default', + loading: false, + disabled: false, + withIcon: false, + text: 'Click me' + }); + const [activeTab, setActiveTab] = useState<'preview' | 'code'>('preview'); + + const generateCode = (config: ButtonConfig) => { + const imports = [`import { Button } from '@/features/ui/primitives/button';`]; + + if (config.loading) { + imports.push(`import { Loader2 } from 'lucide-react';`); + } + if (config.withIcon) { + imports.push(`import { Download } from 'lucide-react';`); + } + + const aiContext = `/** + * 🤖 AI CONTEXT: Button Component + * + * VARIANT DECISION TREE: + * - default: Primary actions, main CTAs, submit buttons + * - destructive: Delete, remove, cancel dangerous operations + * - outline: Secondary actions, alternative options + * - ghost: Tertiary actions, minimal emphasis + * - link: Navigation, text-only actions + * - cyan: Special emphasis, Tron-themed primary + * - knowledge: Knowledge base specific actions + * + * SIZE GUIDELINES: + * - xs: Inline actions, table cells + * - sm: Dense UI, secondary actions + * - default: Most use cases + * - lg: Primary CTAs, hero sections + * - icon: Icon-only buttons + */`; + + const props: string[] = []; + if (config.variant !== 'default') props.push(`variant="${config.variant}"`); + if (config.size !== 'default') props.push(`size="${config.size}"`); + if (config.loading) props.push(`loading={true}`); + if (config.disabled) props.push(`disabled={true}`); + + const content = config.loading + ? `<>\n \n ${config.text}\n ` + : config.withIcon + ? `<>\n \n ${config.text}\n ` + : config.text; + + const component = `export const MyButton = () => { + return ( + 0 ? '\n ' + props.join('\n ') : ''}> + ${content} + + ); +};`; + + return `${imports.join('\n')}\n\n${aiContext}\n\n${component}`; + }; + + return ( +
+ {/* LEFT: Configuration Panel (1/4 width) */} +
+ +
+ + + + + + + + + + setConfig({...config, loading})} + /> + + + + setConfig({...config, disabled})} + /> + + + + setConfig({...config, withIcon})} + /> + + + {config.size !== 'icon' && ( + + setConfig({...config, text: e.target.value})} + placeholder="Button text..." + className="w-24 text-xs" + /> + + )} +
+ + {/* Preview/Code Tabs INSIDE configurator */} +
+
+ + +
+
+
+
+ + {/* RIGHT: Preview or Code Content (3/4 width) */} +
+ {activeTab === 'preview' ? ( + + + + ) : ( + + )} +
+
+ ); +}; \ No newline at end of file diff --git a/archon-ui-main/src/components/style-guide/configurators/FormConfigurator.tsx b/archon-ui-main/src/components/style-guide/configurators/FormConfigurator.tsx new file mode 100644 index 00000000..a0b36293 --- /dev/null +++ b/archon-ui-main/src/components/style-guide/configurators/FormConfigurator.tsx @@ -0,0 +1,219 @@ +import { useState } from 'react'; +import { Input } from '@/features/ui/primitives/input'; +import { Button } from '@/features/ui/primitives/button'; +import { Label } from '@/features/ui/primitives/label'; +import { Switch } from '@/features/ui/primitives/switch'; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/features/ui/primitives/select'; +import { LivePreview } from '../shared/LivePreview'; +import { CodeDisplay } from '../shared/CodeDisplay'; +import { ConfigPanel } from '../shared/ConfigPanel'; +import { Eye, Code } from 'lucide-react'; +import type { InputType } from '../types'; + +interface FormConfig { + error: boolean; + disabled: boolean; + placeholder: string; + inputType: InputType; +} + +export const FormConfigurator = () => { + const [config, setConfig] = useState({ + error: false, + disabled: false, + placeholder: 'Enter your text...', + inputType: 'text' + }); + const [activeTab, setActiveTab] = useState<'preview' | 'code'>('preview'); + + const generateCode = (config: FormConfig) => { + const imports = `import { Input } from '@/features/ui/primitives/input'; +import { Label } from '@/features/ui/primitives/label'; +import { Button } from '@/features/ui/primitives/button';`; + + const aiContext = `/** + * 🤖 AI CONTEXT: Form Input Component + * + * PURPOSE: Text input with glass morphism styling and validation states + * WHEN TO USE: Forms, search bars, data entry fields + * WHEN NOT TO USE: Large text content (use textarea), complex selections (use select) + * + * INPUT TYPE GUIDELINES: + * - text: General text input, names, titles + * - email: Email addresses (includes validation) + * - password: Passwords (masks input) + * - number: Numeric values (shows number pad on mobile) + * + * ERROR STATE: + * - Use when validation fails + * - Shows red border and focus ring + * - Pair with error message below input + * + * DISABLED STATE: + * - Use when input is temporarily unavailable + * - Shows reduced opacity and prevents interaction + * - Consider using readonly for permanent restrictions + */`; + + const props: string[] = []; + if (config.inputType !== 'text') props.push(`type="${config.inputType}"`); + if (config.error) props.push(`error={true}`); + if (config.disabled) props.push(`disabled={true}`); + if (config.placeholder) props.push(`placeholder="${config.placeholder}"`); + + const component = `export const MyForm = () => { + const [value, setValue] = useState(''); + + return ( +
+
+ + setValue(e.target.value)}${props.length > 0 ? '\n ' + props.join('\n ') : ''} + /> + ${config.error ? `

+ This field is required +

` : ''} +
+ + +
+ ); +};`; + + return `${imports}\n\n${aiContext}\n\n${component}`; + }; + + return ( +
+ {/* LEFT: Configuration Panel (1/4 width) */} +
+ +
+ {/* Input Type */} +
+ + +
+ + {/* States */} +
+
+ + setConfig({...config, error})} + /> +
+ +
+ + setConfig({...config, disabled})} + /> +
+
+ + {/* Placeholder */} +
+ + setConfig({...config, placeholder: e.target.value})} + /> +
+
+ + {/* Preview/Code Tabs INSIDE configurator */} +
+
+ + +
+
+
+
+ + {/* RIGHT: Preview or Code Content (3/4 width) */} +
+ {activeTab === 'preview' ? ( + +
+
+ + + {config.error && ( +

+ This field is required +

+ )} +
+ + +
+
+ ) : ( + + )} +
+
+ ); +}; \ No newline at end of file diff --git a/archon-ui-main/src/components/style-guide/configurators/GlassCardConfigurator.tsx b/archon-ui-main/src/components/style-guide/configurators/GlassCardConfigurator.tsx new file mode 100644 index 00000000..42fef42b --- /dev/null +++ b/archon-ui-main/src/components/style-guide/configurators/GlassCardConfigurator.tsx @@ -0,0 +1,327 @@ +import { useState } from 'react'; +import { Card } from '@/features/ui/primitives/card'; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/features/ui/primitives/select'; +import { Input } from '@/features/ui/primitives/input'; +import { Button } from '@/features/ui/primitives/button'; +import { LivePreview } from '../shared/LivePreview'; +import { CodeDisplay } from '../shared/CodeDisplay'; +import { ConfigPanel } from '../shared/ConfigPanel'; +import { ConfigRow } from '../shared/ConfigRow'; +import { Eye, Code } from 'lucide-react'; +import type { GlowColor, EdgePosition, EdgeColor, CardSize, Transparency, BlurLevel, GlassTint } from '../types'; + +interface GlassCardConfig { + blur: BlurLevel; + transparency: Transparency; + glassTint: GlassTint; + glowColor: GlowColor; + edgePosition: EdgePosition; + edgeColor: EdgeColor; + size: CardSize; + content: string; +} + +export const GlassCardConfigurator = () => { + const [config, setConfig] = useState({ + blur: 'xl', // Standard glass (3px) - subtle effect + transparency: 'light', // 3% opacity for true glass + glassTint: 'none', + glowColor: 'none', + edgePosition: 'none', + edgeColor: 'cyan', + size: 'lg', + content: 'Your content here' + }); + const [activeTab, setActiveTab] = useState<'preview' | 'code'>('preview'); + + const generateCode = (config: GlassCardConfig) => { + const imports = `import { Card } from '@/features/ui/primitives/card';`; + + const aiContext = `/** + * 🤖 AI CONTEXT: Glass Card Component + * + * GLASS PROPERTIES for true glassmorphism: + * + * 1. TRANSPARENCY - How much you can see through the glass + * - clear: Almost invisible (0.01 opacity) + * - light: Subtle frosting (0.03 opacity) ← BEST FOR TRUE GLASS + * - medium: Standard glass (0.05 opacity) + * - frosted: Heavy frosting (0.08 opacity) + * - solid: Maximum opacity (0.12 opacity) + * + * 2. GLASS TINT - Adds color to the glass itself + * - none: Pure transparent + * - purple/blue/cyan/green/orange/pink/red: Colored glass + * + * 3. GLOW EFFECTS - Choose ONE: + * a) glowColor - Full perimeter neon backlight + * - none: No glow + * - purple/blue/cyan/green/orange/pink/red: Neon glow + * + * b) edgePosition + edgeColor - Single edge accent (like original cards!) + * - edgePosition: top/left/right/bottom + * - edgeColor: purple/blue/cyan/green/orange/pink/red + * + * USAGE PATTERNS: + * - Default glass: transparency="light" blur="xl" + * - Knowledge cards: edgePosition="top" edgeColor="purple" + * - Task cards: edgePosition="left" edgeColor based on priority + * - Featured content: glowColor="purple" (full perimeter) + * - Subtle containers: transparency="clear" glassTint="none" + * + * DECISION TREE: + * - Navigation/headers → edgePosition="top" + * - Sidebars/lists → edgePosition="left" + * - Actions/CTAs → edgePosition="right" + * - Status/footers → edgePosition="bottom" + * - Featured/selected → glowColor (full perimeter) + */`; + + const props: string[] = []; + if (config.blur !== 'xl') props.push(`blur="${config.blur}"`); + if (config.transparency !== 'medium') props.push(`transparency="${config.transparency}"`); + if (config.glassTint !== 'none') props.push(`glassTint="${config.glassTint}"`); + if (config.glowColor !== 'none') props.push(`glowColor="${config.glowColor}"`); + if (config.edgePosition !== 'none') props.push(`edgePosition="${config.edgePosition}"`); + if (config.edgePosition !== 'none' && config.edgeColor !== 'cyan') props.push(`edgeColor="${config.edgeColor}"`); + if (config.size !== 'md') props.push(`size="${config.size}"`); + + const component = `export const MyCard = ({ children }) => { + return ( + 0 ? '\n ' + props.join('\n ') : ''}> + {children} + + ); +};`; + + return `${imports}\n\n${aiContext}\n\n${component}`; + }; + + return ( +
+ {/* LEFT: Configuration Panel (1/4 width) */} +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + setConfig({...config, content: e.target.value})} + placeholder="Card content..." + className="w-24 text-xs" + /> + +
+ + {/* Preview/Code Tabs INSIDE configurator */} +
+
+ + +
+
+
+
+ + {/* RIGHT: Preview or Code Content (3/4 width) */} +
+ {activeTab === 'preview' ? ( + + +

Glass Card Example

+

+ {config.content} +

+
+
Blur: {config.blur}
+
Transparency: {config.transparency}
+
Glass Tint: {config.glassTint}
+ {config.edgePosition === 'none' ? ( +
Glow Color: {config.glowColor}
+ ) : ( + <> +
Edge Position: {config.edgePosition}
+
Edge Color: {config.edgeColor}
+ + )} +
Size: {config.size}
+
+
+
+ ) : ( + + )} +
+
+ ); +}; \ No newline at end of file diff --git a/archon-ui-main/src/components/style-guide/configurators/ModalConfigurator.tsx b/archon-ui-main/src/components/style-guide/configurators/ModalConfigurator.tsx new file mode 100644 index 00000000..33716924 --- /dev/null +++ b/archon-ui-main/src/components/style-guide/configurators/ModalConfigurator.tsx @@ -0,0 +1,235 @@ +import { useState } from 'react'; +import { Button } from '@/features/ui/primitives/button'; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/features/ui/primitives/select'; +import { CodeDisplay } from '../shared/CodeDisplay'; +import { ConfigPanel } from '../shared/ConfigPanel'; +import { ConfigRow } from '../shared/ConfigRow'; +import { MODAL_TYPES } from '../standards/modalStandards'; +import { Eye, Code, X } from 'lucide-react'; +import type { ModalSize, GlowColor } from '../types'; + +export const ModalConfigurator = () => { + const [selectedType, setSelectedType] = useState('confirmation'); + const [activeTab, setActiveTab] = useState<'preview' | 'code'>('preview'); + const [customSize, setCustomSize] = useState('sm'); + const [customGlowColor, setCustomGlowColor] = useState>('red'); + + const generateCode = (type: keyof typeof MODAL_TYPES) => { + + const imports = `import { AlertDialog, AlertDialogContent, AlertDialogHeader, AlertDialogTitle, AlertDialogDescription, AlertDialogFooter, AlertDialogAction, AlertDialogCancel, AlertDialogTrigger } from '@/features/ui/primitives/alert-dialog'; +import { Button } from '@/features/ui/primitives/button';`; + + const aiContext = `/** + * 🤖 AI CONTEXT: ${type.charAt(0).toUpperCase() + type.slice(1)} Modal + * + * PURPOSE: ${MODAL_TYPES[type].purpose} + * SIZE: ${customSize.toUpperCase()} - ${customSize === 'sm' ? 'Compact for simple confirmations' : + customSize === 'md' ? 'Standard for forms and content' : + customSize === 'lg' ? 'Large for detailed displays' : + 'Extra large for code/data views'} + * GLOW: ${customGlowColor.toUpperCase()} - ${customGlowColor === 'red' ? 'Danger/destructive actions' : + customGlowColor === 'green' ? 'Success/creation actions' : + customGlowColor === 'blue' ? 'Information/editing' : + customGlowColor === 'purple' ? 'Primary/featured content' : + 'Special emphasis/code display'} + * + * WHEN TO USE: + * ${type === 'confirmation' ? '- Delete operations\n * - Irreversible actions\n * - Warning confirmations' : + type === 'formCreate' ? '- Creating new resources\n * - Data entry forms\n * - Positive actions' : + type === 'formEdit' ? '- Editing existing data\n * - Update operations\n * - Modification forms' : + type === 'display' ? '- Showing detailed information\n * - Read-only content\n * - Feature showcases' : + type === 'codeViewer' ? '- Code snippets display\n * - JSON/data viewing\n * - Technical content' : + '- Application settings\n * - Configuration panels\n * - User preferences'} + * + * IMPLEMENTATION: Use AlertDialog for modal behavior, wrap trigger in AlertDialogTrigger + */`; + + const component = `export const ${type.charAt(0).toUpperCase() + type.slice(1)}Modal = ({ trigger, onConfirm }) => { + return ( + + + {trigger} + + + + ${type === 'confirmation' ? 'Confirm Action' : + type === 'formCreate' ? 'Create New Item' : + type === 'formEdit' ? 'Edit Item' : + type === 'display' ? 'Details' : + type === 'codeViewer' ? 'Code Viewer' : + 'Settings'} + + ${MODAL_TYPES[type].purpose} + + + + {/* Modal content goes here */} + + + Cancel + + ${type === 'confirmation' ? 'Confirm' : + type === 'formCreate' ? 'Create' : + type === 'formEdit' ? 'Save Changes' : + 'Close'} + + + + + ); +};`; + + return `${imports}\n\n${aiContext}\n\n${component}`; + }; + + const currentConfig = MODAL_TYPES[selectedType]; + + return ( +
+ {/* LEFT: Configuration Panel (1/4 width) */} +
+ +
+ + + + + + + + + + + + + +
+ {currentConfig.purpose} +
+
+
+ + {/* Preview/Code Tabs INSIDE configurator */} +
+
+ + +
+
+
+
+ + {/* RIGHT: Preview or Code Content (3/4 width) */} +
+ {activeTab === 'preview' ? ( +
+ {/* Inline Modal Preview - No Button Trigger */} +
+
+
+

+ {selectedType === 'confirmation' ? 'Confirm Action' : + selectedType === 'formCreate' ? 'Create New Item' : + selectedType === 'formEdit' ? 'Edit Item' : + selectedType === 'display' ? 'Details' : + selectedType === 'codeViewer' ? 'Code Viewer' : + 'Settings'} +

+ +
+ +
+

+ {currentConfig.purpose} - This is an inline preview of the {selectedType} modal type. +

+
+ +
+

+ Modal content would go here. This {customSize} sized modal uses {customGlowColor} color theming. +

+
+ +
+ + +
+
+
+
+ ) : ( + + )} +
+
+ ); +}; \ No newline at end of file diff --git a/archon-ui-main/src/components/style-guide/configurators/TableConfigurator.tsx b/archon-ui-main/src/components/style-guide/configurators/TableConfigurator.tsx new file mode 100644 index 00000000..8d459953 --- /dev/null +++ b/archon-ui-main/src/components/style-guide/configurators/TableConfigurator.tsx @@ -0,0 +1,196 @@ +import { useState } from 'react'; +import { Button } from '@/features/ui/primitives/button'; +import { Switch } from '@/features/ui/primitives/switch'; +import { Label } from '@/features/ui/primitives/label'; +import { LivePreview } from '../shared/LivePreview'; +import { CodeDisplay } from '../shared/CodeDisplay'; +import { ConfigPanel } from '../shared/ConfigPanel'; +import { Edit, Trash2, Eye, Code } from 'lucide-react'; + +interface TableConfig { + glassMorphism: boolean; + actions: boolean; + headers: boolean; + striped: boolean; +} + +const sampleData = [ + { id: 1, name: 'John Doe', email: 'john@example.com', status: 'Active' }, + { id: 2, name: 'Jane Smith', email: 'jane@example.com', status: 'Inactive' }, + { id: 3, name: 'Bob Johnson', email: 'bob@example.com', status: 'Active' }, +]; + +export const TableConfigurator = () => { + const [config, setConfig] = useState({ + glassMorphism: true, + actions: true, + headers: true, + striped: true + }); + const [activeTab, setActiveTab] = useState<'preview' | 'code'>('preview'); + + const generateCode = (_config: TableConfig) => { + const imports = `import { Button } from '@/features/ui/primitives/button'; +import { Edit, Trash2, Eye } from 'lucide-react';`; + + const aiContext = `/** + * 🤖 AI CONTEXT: Glass Morphism Table + * + * PURPOSE: Data display with glass morphism styling and interactive elements + * WHEN TO USE: Data grids, lists with actions, dashboard tables + * WHEN NOT TO USE: Simple lists (use basic ul/li), massive datasets (use virtualization) + */`; + + return `${imports}\n\n${aiContext}\n\n// Table component code here...`; + }; + + return ( +
+ {/* LEFT: Configuration Panel (1/4 width) */} +
+ +
+
+ + setConfig({...config, glassMorphism})} + /> +
+ +
+ + setConfig({...config, actions})} + /> +
+ +
+ + setConfig({...config, headers})} + /> +
+ +
+ + setConfig({...config, striped})} + /> +
+
+ + {/* Preview/Code Tabs INSIDE configurator */} +
+
+ + +
+
+
+
+ + {/* RIGHT: Preview or Code Content (3/4 width) */} +
+ {activeTab === 'preview' ? ( + +
+ + {config.headers && ( + + + + + + {config.actions && ( + + )} + + + )} + + {sampleData.map((item, index) => ( + + + + + {config.actions && ( + + )} + + ))} + +
+ Name + + Email + + Status + + Actions +
+ {item.name} + + {item.email} + + + {item.status} + + +
+ + + +
+
+
+
+ ) : ( + + )} +
+
+ ); +}; \ No newline at end of file diff --git a/archon-ui-main/src/components/style-guide/configurators/ToggleConfigurator.tsx b/archon-ui-main/src/components/style-guide/configurators/ToggleConfigurator.tsx new file mode 100644 index 00000000..076f41ec --- /dev/null +++ b/archon-ui-main/src/components/style-guide/configurators/ToggleConfigurator.tsx @@ -0,0 +1,174 @@ +import { useState } from 'react'; +import { Switch } from '@/features/ui/primitives/switch'; +import { Button } from '@/features/ui/primitives/button'; +import { Label } from '@/features/ui/primitives/label'; +import { RadioGroup, RadioGroupItem } from '@/features/ui/primitives/radio-group'; +import { LivePreview } from '../shared/LivePreview'; +import { CodeDisplay } from '../shared/CodeDisplay'; +import { ConfigPanel } from '../shared/ConfigPanel'; +import { Eye, Code } from 'lucide-react'; +import type { LabelPosition } from '../types'; + +interface ToggleConfig { + disabled: boolean; + size: 'sm' | 'default' | 'lg'; + labelPosition: LabelPosition; + labelText: string; +} + +export const ToggleConfigurator = () => { + const [config, setConfig] = useState({ + disabled: false, + size: 'default', + labelPosition: 'right', + labelText: 'Enable notifications' + }); + const [activeTab, setActiveTab] = useState<'preview' | 'code'>('preview'); + const [toggleState, setToggleState] = useState(false); + + const generateCode = (_config: ToggleConfig) => { + const imports = `import { Switch } from '@/features/ui/primitives/switch'; +import { Label } from '@/features/ui/primitives/label';`; + + const aiContext = `/** + * 🤖 AI CONTEXT: Switch Toggle Component + * + * PURPOSE: Binary on/off controls with accessible labeling + * WHEN TO USE: Settings, preferences, feature toggles, boolean states + * WHEN NOT TO USE: Multiple options (use RadioGroup), momentary actions (use Button) + */`; + + return `${imports}\n\n${aiContext}\n\n// Toggle component code here...`; + }; + + const layoutClasses = { + left: 'flex-row-reverse', + right: 'flex-row', + top: 'flex-col', + bottom: 'flex-col-reverse' + }; + + const gapClasses = { + left: 'gap-3', + right: 'gap-3', + top: 'gap-2', + bottom: 'gap-2' + }; + + return ( +
+ {/* LEFT: Configuration Panel (1/4 width) */} +
+ +
+ {/* Label Position */} +
+ + setConfig({...config, labelPosition: value as LabelPosition})} + > +
+ {['left', 'right', 'top', 'bottom'].map(position => ( +
+ + +
+ ))} +
+
+
+ + {/* States */} +
+ + setConfig({...config, disabled})} + /> +
+ + {/* Label Text */} +
+ + setConfig({...config, labelText: e.target.value})} + className="w-full mt-1 px-3 py-2 border rounded-md dark:bg-gray-800 text-sm" + /> +
+
+ + {/* Preview/Code Tabs INSIDE configurator */} +
+
+ + +
+
+
+
+ + {/* RIGHT: Preview or Code Content (3/4 width) */} +
+ {activeTab === 'preview' ? ( + +
+ {(config.labelPosition === 'top' || config.labelPosition === 'left') ? ( + <> + + + + ) : ( + <> + + + + )} +
+
+ ) : ( + + )} +
+
+ ); +}; \ No newline at end of file diff --git a/archon-ui-main/src/components/style-guide/examples/CompositionsExample.tsx b/archon-ui-main/src/components/style-guide/examples/CompositionsExample.tsx new file mode 100644 index 00000000..dc3289df --- /dev/null +++ b/archon-ui-main/src/components/style-guide/examples/CompositionsExample.tsx @@ -0,0 +1,638 @@ +import React, { useState } from 'react'; +import { Card } from '@/features/ui/primitives/card'; +import type { GlowColor } from '../types'; +import { Button } from '@/features/ui/primitives/button'; +import { CodeDisplay } from '../shared/CodeDisplay'; +import { LivePreview } from '../shared/LivePreview'; +import { cn, glassmorphism } from '@/features/ui/primitives/styles'; +import { + Home, + Settings, + User, + FileText, + BarChart, + Plus, + Search, + Bell, + MoreVertical, + Calendar, +} from 'lucide-react'; + +interface ExampleComposition { + id: string; + name: string; + description: string; + usage: string; + component: React.ComponentType; +} + +// Complete Dashboard Composition +const DashboardComposition = () => { + return ( +
+ {/* Top Navigation */} + +
+
+
+ Archon +
+ +
+ + + +
+
+ + +
+ {/* Sidebar */} + +
+ +
+
+ + {/* Main Content */} +
+ {/* Stats Grid */} +
+ {[ + { label: 'Projects', value: '24', color: 'purple' }, + { label: 'Tasks', value: '156', color: 'blue' }, + { label: 'Team', value: '8', color: 'green' } + ].map((stat) => ( + +

{stat.value}

+

{stat.label}

+
+ ))} +
+ + {/* Content Grid */} +
+ +

Recent Activity

+
+ {['Project updated', 'Task completed', 'New member'].map((activity, i) => ( +
+ {activity} +
+ ))} +
+
+ +

Quick Actions

+
+ + +
+
+
+
+
+
+ ); +}; + +// Project Card Collection +const ProjectCardsComposition = () => { + const projects = [ + { title: 'Alpha', status: 'Active', progress: 75, color: 'purple' }, + { title: 'Beta', status: 'Review', progress: 90, color: 'blue' }, + { title: 'Gamma', status: 'Planning', progress: 25, color: 'orange' } + ]; + + return ( +
+
+

Projects

+ +
+ +
+ {projects.map((project) => ( + +
+

Project {project.title}

+ +
+ +

+ Development project with team collaboration features. +

+ +
+
+ Progress + {project.progress}% +
+
+
+
+
+ +
+ + + Due: 2 weeks + + + + 5 members + +
+ + ))} +
+
+ ); +}; + +// Modal with Form +const ModalFormComposition = () => { + const [showModal, setShowModal] = useState(false); + + return ( +
+
+ +
+ + {showModal && ( +
+ +
+

Create New Task

+ +
+ +
+
+ + +
+ +
+ + +
+ +
+ +