Lachlan McMurtrie
The app is a collaborative component builder. it begin by starting a project, entering in a description. the next page will be an ai assisted project scope, where the user will type the component type, which will be a list of core components (all that are core across ui domains). The ai will then ask for a framework of native react or react for web. the behavioral hooks, interactions and utilites that align with the component will then be showed. for web, these must be all react-aria, for native, these will be react-native. assume react-shared types for cross platform as common, as well as react-stately for states which are also cross platform. provide the user with a the data attributes as per react-aria or native equivilant documentation, ask them how they want to recieve their code files - combined as typed primitives, or separated through the use of an adapter that exports the behaviors etc to the primitive.
499a14d verified | <html lang="en" class="dark"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>ComponentForge - Code Generation</title> | |
| <link rel="icon" type="image/x-icon" href="/static/favicon.ico"> | |
| <link rel="stylesheet" href="style.css"> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script> | |
| <script src="https://unpkg.com/feather-icons"></script> | |
| </head> | |
| <body class="bg-gray-900 text-white min-h-screen"> | |
| <custom-header></custom-header> | |
| <main class="container mx-auto px-4 py-8"> | |
| <div class="max-w-6xl mx-auto"> | |
| <!-- Progress Bar --> | |
| <div class="mb-8"> | |
| <div class="flex items-center justify-between mb-2"> | |
| <span class="text-sm text-gray-400">Step 3 of 3</span> | |
| <span class="text-sm text-green-400">Code Generation</span> | |
| </div> | |
| <div class="w-full bg-gray-700 rounded-full h-2"> | |
| <div class="bg-gradient-to-r from-purple-500 via-pink-500 to-green-500 h-2 rounded-full w-full"></div> | |
| </div> | |
| <!-- Project Summary --> | |
| <div class="bg-gray-800 rounded-xl p-6 mb-6 border border-gray-700"> | |
| <div class="flex items-center justify-between"> | |
| <div> | |
| <h2 class="text-xl font-bold" id="finalProjectTitle">Project: Loading...</h2> | |
| <div class="flex items-center space-x-4 mt-2"> | |
| <span class="inline-flex items-center px-3 py-1 rounded-full text-xs font-medium bg-purple-500/20 text-purple-300 border border-purple-500/30" id="frameworkBadge"></span> | |
| <span class="inline-flex items-center px-3 py-1 rounded-full text-xs font-medium bg-pink-500/20 text-pink-300 border border-pink-500/30" id="structureBadge"></span> | |
| </div> | |
| </div> | |
| <button onclick="window.location.href = 'scope.html'" class="text-gray-400 hover:text-white transition-colors"> | |
| <i data-feather="arrow-left" class="w-5 h-5"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Generated Code --> | |
| <div class="grid lg:grid-cols-2 gap-8"> | |
| <!-- Component Files --> | |
| <div class="space-y-6"> | |
| <div class="bg-gray-800 rounded-xl p-6 border border-gray-700"> | |
| <div class="flex items-center justify-between mb-4"> | |
| <div class="flex items-center"> | |
| <i data-feather="file-text" class="w-6 h-6 text-purple-500 mr-3"></i> | |
| <h3 class="text-lg font-semibold">Generated Files</h3> | |
| </div> | |
| <button id="downloadAllBtn" class="px-4 py-2 bg-green-600 hover:bg-green-700 text-white font-medium rounded-lg transition-all duration-200 flex items-center"> | |
| <i data-feather="download" class="w-4 h-4 mr-2"></i> | |
| Download All | |
| </button> | |
| </div> | |
| <!-- File Tabs --> | |
| <div class="border-b border-gray-700 mb-4"> | |
| <div class="flex space-x-2"> | |
| <button class="file-tab active px-4 py-2 text-sm font-medium border-b-2 border-purple-500"> | |
| Component.tsx | |
| </button> | |
| <button class="file-tab px-4 py-2 text-sm font-medium text-gray-400 hover:text-white transition-colors" data-file="hooks"> | |
| Hooks.ts | |
| </button> | |
| <button class="file-tab px-4 py-2 text-sm font-medium text-gray-400 hover:text-white transition-colors" data-file="types"> | |
| Types.ts | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Code Preview --> | |
| <div class="bg-gray-900 rounded-lg p-4 border border-gray-700"> | |
| <pre id="codePreview" class="text-sm font-mono text-gray-300 overflow-x-auto"> | |
| <code>// Your component code will appear here</code> | |
| </pre> | |
| </div> | |
| </div> | |
| <!-- Next Steps --> | |
| <div class="bg-gray-800 rounded-xl p-6 border border-gray-700"> | |
| <div class="flex items-center mb-4"> | |
| <i data-feather="check-circle" class="w-6 h-6 text-green-500 mr-3"></i> | |
| <h3 class="text-lg font-semibold">Next Steps</h3> | |
| </div> | |
| <div class="space-y-3"> | |
| <div class="flex items-center p-3 bg-gray-700 rounded-lg border border-gray-600"> | |
| <i data-feather="download" class="w-4 h-4 text-green-500 mr-3"></i> | |
| <span class="text-sm">Install dependencies in your project</span> | |
| </div> | |
| <div class="flex items-center p-3 bg-gray-700 rounded-lg border border-gray-600"> | |
| <i data-feather="folder" class="w-4 h-4 text-blue-500 mr-3"></i> | |
| <span class="text-sm">Copy the generated files to your codebase</span> | |
| </div> | |
| <div class="flex items-center p-3 bg-gray-700 rounded-lg border border-gray-600"> | |
| <i data-feather="settings" class="w-4 h-4 text-yellow-500 mr-3"></i> | |
| <span class="text-sm">Configure TypeScript paths if needed</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Preview & Documentation --> | |
| <div class="space-y-6"> | |
| <!-- Component Preview --> | |
| <div class="bg-gray-800 rounded-xl p-6 border border-gray-700"> | |
| <div class="flex items-center mb-4"> | |
| <i data-feather="eye" class="w-6 h-6 text-pink-500 mr-3"></i> | |
| <h3 class="text-lg font-semibold">Live Preview</h3> | |
| </div> | |
| <div class="bg-gray-900 rounded-lg p-8 border border-gray-700 flex items-center justify-center min-h-[200px]"> | |
| <div class="text-center text-gray-500"> | |
| <i data-feather="code" class="w-12 h-12 mx-auto mb-3"></i> | |
| <p class="text-sm">Component preview will appear here</p> | |
| </div> | |
| </div> | |
| <!-- Documentation --> | |
| <div class="bg-gray-800 rounded-xl p-6 border border-gray-700"> | |
| <div class="flex items-center mb-4"> | |
| <i data-feather="book" class="w-6 h-6 text-blue-500 mr-3"></i> | |
| <h3 class="text-lg font-semibold">Usage Documentation</h3> | |
| </div> | |
| <div class="space-y-3"> | |
| <div class="p-3 bg-gray-700 rounded-lg border border-gray-600"> | |
| <h4 class="font-semibold text-sm mb-2">Basic Usage</h4> | |
| <pre class="text-xs font-mono text-gray-400 bg-gray-800 p-2 rounded mt-1"> | |
| <code>import { Component } from './Component';</code> | |
| </pre> | |
| </div> | |
| <div class="p-3 bg-gray-700 rounded-lg border border-gray-600"> | |
| <h4 class="font-semibold text-sm mb-2">Props</h4> | |
| <div class="text-xs text-gray-400 mt-1"> | |
| <div class="flex justify-between py-1 border-b border-gray-600"> | |
| <span class="font-mono">value</span> | |
| <span class="text-gray-500">string</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Action Buttons --> | |
| <div class="flex justify-between items-center mt-8"> | |
| <button onclick="window.location.href = 'scope.html'" class="px-6 py-3 bg-gray-700 hover:bg-gray-600 text-white font-medium rounded-lg transition-all duration-200 flex items-center"> | |
| <i data-feather="arrow-left" class="w-5 h-5 mr-2"></i> | |
| Back to Scope | |
| </button> | |
| <button onclick="window.location.href = 'index.html'" class="px-6 py-3 bg-gradient-to-r from-purple-600 to-pink-600 hover:from-purple-700 hover:to-pink-700 text-white font-semibold rounded-lg transition-all duration-200 transform hover:scale-105 focus:ring-4 focus:ring-purple-500 focus:ring-opacity-50 flex items-center"> | |
| <i data-feather="plus" class="w-5 h-5 mr-2"></i> | |
| Start New Project | |
| </button> | |
| </div> | |
| </div> | |
| </main> | |
| <custom-footer></custom-footer> | |
| <script src="components/header.js"></script> | |
| <script src="components/footer.js"></script> | |
| <script src="script.js"></script> | |
| <script> | |
| feather.replace(); | |
| document.addEventListener('DOMContentLoaded', function() { | |
| const projectData = StorageManager.getProjectData(); | |
| document.getElementById('finalProjectTitle').textContent = `Project: ${projectData.name}`; | |
| // Update badges | |
| const frameworkBadge = document.getElementById('frameworkBadge'); | |
| const structureBadge = document.getElementById('structureBadge'); | |
| frameworkBadge.innerHTML = `<i data-feather="${projectData.framework === 'react-web' ? 'globe' : 'smartphone'}" class="w-3 h-3 mr-1"></i> ${projectData.framework === 'react-web' ? 'React Web' : 'React Native'}`; | |
| structureBadge.innerHTML = `<i data-feather="${projectData.codeStructure === 'typed-primitives' ? 'type' : 'layers'}" class="w-3 h-3 mr-1"></i> ${projectData.codeStructure === 'typed-primitives' ? 'Typed Primitives' : 'Adapter Pattern'}`; | |
| // File tab switching | |
| document.querySelectorAll('.file-tab').forEach(tab => { | |
| tab.addEventListener('click', function() { | |
| document.querySelectorAll('.file-tab').forEach(t => { | |
| t.classList.remove('active', 'border-purple-500', 'text-white'}; | |
| t.classList.add('text-gray-400'}); | |
| }); | |
| this.classList.add('active', 'border-purple-500', 'text-white'}); | |
| this.classList.remove('text-gray-400'}); | |
| // Update code preview based on selected file | |
| const fileType = this.dataset.file || 'component'; | |
| this.updateCodePreview(fileType); | |
| }); | |
| }); | |
| // Download all files | |
| document.getElementById('downloadAllBtn').addEventListener('click', function() { | |
| // Generate and download all files as zip | |
| this.generateAndDownloadFiles(); | |
| }.bind(this)); | |
| }); | |
| // Update code preview based on file type | |
| function updateCodePreview(fileType) { | |
| const codePreview = document.getElementById('codePreview'); | |
| const mockCode = { | |
| component: `import React from 'react'; | |
| import { useButton } from '@react-aria/button'; | |
| import { useFocusRing } from '@react-aria/focus'; | |
| import type { ButtonProps } from './types'; | |
| export const Button: React.FC<ButtonProps> = (props) => { | |
| const ref = React.useRef<HTMLButtonElement>(null); | |
| const { buttonProps } = useButton(props, ref); | |
| const { focusProps, isFocusVisible } = useFocusRing(); | |
| return ( | |
| <button | |
| {...buttonProps} | |
| {...focusProps} | |
| ref={ref} | |
| data-focused={isFocusVisible} | |
| data-pressed={buttonProps['aria-pressed']} | |
| data-disabled={props.disabled} | |
| className={\`px-4 py-2 rounded-lg transition-all \${props.disabled ? 'opacity-50 cursor-not-allowed' : 'hover:bg-opacity-90'} \${isFocusVisible ? 'ring-2 ring-purple-500' : ''}\`} | |
| > | |
| {props.children} | |
| </button> | |
| ); | |
| };`, | |
| hooks: `import { useButton } from '@react-aria/button'; | |
| import { useFocusRing } from '@react-aria/focus'; | |
| export const useButtonBehavior = (props: ButtonProps) => { | |
| const ref = React.useRef<HTMLButtonElement>(null); | |
| const { buttonProps } = useButton(props, ref); | |
| const { focusProps, isFocusVisible } = useFocusRing(); | |
| return { | |
| buttonProps: { | |
| ...buttonProps, | |
| ...focusProps | |
| }, | |
| ref, | |
| state: { | |
| isFocusVisible, | |
| isPressed: buttonProps['aria-pressed'] | |
| } | |
| }; | |
| };`, | |
| types: `export interface ButtonProps { | |
| children: React.ReactNode; | |
| disabled?: boolean; | |
| onPress?: () => void; | |
| type?: 'button' | 'submit' | 'reset'; | |
| }` | |
| }; | |
| codePreview.innerHTML = `<code>${mockCode[fileType]}</code>`; | |
| } | |
| // Generate and download files as zip | |
| function generateAndDownloadFiles() { | |
| // In a real implementation, this would generate actual files and create a zip | |
| alert('All files would be downloaded as a ZIP archive in a real implementation!'); | |
| } | |
| </script> | |
| </body> | |
| </html> |