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
Raw
History Blame Contribute Delete
14.4 kB
<!DOCTYPE html>
<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>