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
17.7 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 - AI Scope 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 2 of 3</span>
<span class="text-sm text-purple-400">AI Scope Generation</span>
</div>
<div class="w-full bg-gray-700 rounded-full h-2">
<div class="bg-gradient-to-r from-purple-500 to-pink-500 h-2 rounded-full w-2/3"></div>
</div>
<!-- Project Info -->
<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="projectTitle">Project: Loading...</h2>
<p class="text-gray-400 mt-1" id="projectDesc"></p>
</div>
<button onclick="window.location.href = 'index.html'" class="text-gray-400 hover:text-white transition-colors">
<i data-feather="edit" class="w-5 h-5"></i>
</button>
</div>
</div>
<!-- AI Scope Generator -->
<div class="grid lg:grid-cols-2 gap-8">
<!-- Left Column - Input -->
<div class="space-y-6">
<!-- Component Type Selection -->
<div class="bg-gray-800 rounded-xl p-6 border border-gray-700">
<div class="flex items-center mb-4">
<i data-feather="grid" class="w-6 h-6 text-purple-500 mr-3"></i>
<h3 class="text-lg font-semibold">Component Type</h3>
</div>
<div class="grid grid-cols-2 gap-3">
<button class="component-type-btn bg-gray-700 hover:bg-purple-600 p-4 rounded-lg border border-gray-600 hover:border-purple-500 transition-all duration-200" data-type="button">
<i data-feather="mouse-pointer" class="w-6 h-6 mb-2 mx-auto"></i>
<span class="text-sm font-medium">Button</span>
</button>
<button class="component-type-btn bg-gray-700 hover:bg-pink-600 p-4 rounded-lg border border-gray-600 hover:border-pink-500 transition-all duration-200" data-type="input">
<i data-feather="edit" class="w-6 h-6 mb-2 mx-auto"></i>
<span class="text-sm font-medium">Input</span>
</button>
<button class="component-type-btn bg-gray-700 hover:bg-blue-600 p-4 rounded-lg border border-gray-600 hover:border-blue-500 transition-all duration-200" data-type="select">
<i data-feather="chevron-down" class="w-6 h-6 mb-2 mx-auto"></i>
<span class="text-sm font-medium">Select</span>
</button>
<button class="component-type-btn bg-gray-700 hover:bg-green-600 p-4 rounded-lg border border-gray-600 hover:border-green-500 transition-all duration-200" data-type="modal">
<i data-feather="square" class="w-6 h-6 mb-2 mx-auto"></i>
<span class="text-sm font-medium">Modal</span>
</button>
<button class="component-type-btn bg-gray-700 hover:bg-yellow-600 p-4 rounded-lg border border-gray-600 hover:border-yellow-500 transition-all duration-200" data-type="menu">
<i data-feather="menu" class="w-6 h-6 mb-2 mx-auto"></i>
<span class="text-sm font-medium">Menu</span>
</button>
<button class="component-type-btn bg-gray-700 hover:bg-indigo-600 p-4 rounded-lg border border-gray-600 hover:border-indigo-500 transition-all duration-200" data-type="tabs">
<i data-feather="folder" class="w-6 h-6 mb-2 mx-auto"></i>
<span class="text-sm font-medium">Tabs</span>
</button>
</div>
<!-- Additional Requirements -->
<div class="bg-gray-800 rounded-xl p-6 border border-gray-700">
<div class="flex items-center mb-4">
<i data-feather="list" class="w-6 h-6 text-purple-500 mr-3"></i>
<h3 class="text-lg font-semibold">Additional Requirements</h3>
</div>
<textarea
id="additionalReqs"
class="w-full px-4 py-3 bg-gray-700 border border-gray-600 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent text-white placeholder-gray-400 resize-none transition-all duration-200"
rows="3"
placeholder="Any specific behaviors, accessibility requirements, or custom features?"
></textarea>
</div>
<!-- Generate Button -->
<button
id="generateScopeBtn"
class="w-full px-6 py-4 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 justify-center"
>
<i data-feather="zap" class="w-5 h-5 mr-2"></i>
Generate AI Scope
</button>
</div>
<!-- Right Column - AI Output -->
<div class="space-y-6">
<!-- Loading State -->
<div id="loadingState" class="hidden bg-gray-800 rounded-xl p-8 border border-gray-700 text-center">
<div class="animate-spin rounded-full h-12 w-12 border-b-2 border-purple-500 mx-auto mb-4"></div>
<p class="text-gray-300">AI is analyzing your requirements and generating optimal component scope...</p>
</div>
<!-- Framework Selection -->
<div id="frameworkSection" class="hidden bg-gray-800 rounded-xl p-6 border border-gray-700">
<div class="flex items-center mb-4">
<i data-feather="smartphone" class="w-6 h-6 text-purple-500 mr-3"></i>
<h3 class="text-lg font-semibold">Target Framework</h3>
</div>
<div class="grid grid-cols-2 gap-4">
<button class="framework-btn bg-gray-700 hover:bg-purple-600 p-4 rounded-lg border border-gray-600 transition-all duration-200" data-framework="react-web">
<i data-feather="globe" class="w-8 h-8 mb-3 mx-auto"></i>
<span class="text-sm font-medium">React Web</span>
<p class="text-xs text-gray-400 mt-1">With react-aria hooks</p>
</button>
<button class="framework-btn bg-gray-700 hover:bg-pink-600 p-4 rounded-lg border border-gray-600 transition-all duration-200" data-framework="react-native">
<i data-feather="smartphone" class="w-8 h-8 mb-3 mx-auto"></i>
<span class="text-sm font-medium">React Native</span>
<p class="text-xs text-gray-400 mt-1">With native APIs</p>
</button>
</div>
</div>
<!-- Hooks & Behaviors -->
<div id="hooksSection" class="hidden bg-gray-800 rounded-xl p-6 border border-gray-700">
<div class="flex items-center mb-4">
<i data-feather="anchor" class="w-6 h-6 text-purple-500 mr-3"></i>
<h3 class="text-lg font-semibold">Suggested Hooks & Behaviors</h3>
</div>
<div id="hooksList" class="space-y-2">
<!-- Hooks will be populated here -->
</div>
</div>
<!-- Data Attributes -->
<div id="attributesSection" class="hidden bg-gray-800 rounded-xl p-6 border border-gray-700">
<div class="flex items-center mb-4">
<i data-feather="database" class="w-6 h-6 text-purple-500 mr-3"></i>
<h3 class="text-lg font-semibold">Data Attributes</h3>
</div>
<div id="attributesList" class="space-y-2">
<!-- Attributes will be populated here -->
</div>
</div>
<!-- Code Structure -->
<div id="structureSection" class="hidden bg-gray-800 rounded-xl p-6 border border-gray-700">
<div class="flex items-center mb-4">
<i data-feather="code" class="w-6 h-6 text-purple-500 mr-3"></i>
<h3 class="text-lg font-semibold">Code Structure</h3>
</div>
<div class="grid grid-cols-2 gap-4">
<button class="structure-btn bg-gray-700 hover:bg-purple-600 p-4 rounded-lg border border-gray-600 transition-all duration-200" data-structure="typed-primitives">
<i data-feather="type" class="w-8 h-8 mb-3 mx-auto"></i>
<span class="text-sm font-medium">Typed Primitives</span>
<p class="text-xs text-gray-400 mt-1">Combined approach</p>
</button>
<button class="structure-btn bg-gray-700 hover:bg-pink-600 p-4 rounded-lg border border-gray-600 transition-all duration-200" data-structure="adapter-pattern">
<i data-feather="layers" class="w-8 h-8 mb-3 mx-auto"></i>
<span class="text-sm font-medium">Adapter Pattern</span>
<p class="text-xs text-gray-400 mt-1">Separated behaviors</p>
</button>
</div>
</div>
<!-- Continue Button -->
<div id="continueSection" class="hidden">
<button
id="continueBtn"
class="w-full px-6 py-4 bg-gradient-to-r from-green-600 to-emerald-600 hover:from-green-700 hover:to-emerald-700 text-white font-semibold rounded-lg transition-all duration-200 transform hover:scale-105 focus:ring-4 focus:ring-green-500 focus:ring-opacity-50 flex items-center justify-center"
>
<i data-feather="arrow-right" class="w-5 h-5 mr-2"></i>
Continue to Code Generation
</button>
</div>
</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();
// Load project data
document.addEventListener('DOMContentLoaded', function() {
const projectData = StorageManager.getProjectData();
document.getElementById('projectTitle').textContent = `Project: ${projectData.name}`;
document.getElementById('projectDesc').textContent = projectData.description;
// Component type selection
document.querySelectorAll('.component-type-btn').forEach(btn => {
btn.addEventListener('click', function() {
document.querySelectorAll('.component-type-btn').forEach(b => b.classList.remove('bg-purple-600', 'bg-pink-600', 'bg-blue-600', 'bg-green-600', 'bg-yellow-600', 'bg-indigo-600'));
this.classList.add(this.classList.contains('hover:bg-purple-600') ? 'bg-purple-600' :
this.classList.contains('hover:bg-pink-600') ? 'bg-pink-600' :
this.classList.contains('hover:bg-blue-600') ? 'bg-blue-600' :
this.classList.contains('hover:bg-green-600') ? 'bg-green-600' :
this.classList.contains('hover:bg-yellow-600') ? 'bg-yellow-600' : 'bg-indigo-600');
});
});
// Generate scope
document.getElementById('generateScopeBtn').addEventListener('click', async function() {
const selectedType = document.querySelector('.component-type-btn.bg-purple-600, .component-type-btn.bg-pink-600, .component-type-btn.bg-blue-600, .component-type-btn.bg-green-600, .component-type-btn.bg-yellow-600, .component-type-btn.bg-indigo-600')?.dataset.type || 'button';
const additionalReqs = document.getElementById('additionalReqs').value;
// Show loading
document.getElementById('loadingState').classList.remove('hidden');
try {
const scope = await AIService.generateComponentScope(projectData.description, selectedType);
// Store scope
localStorage.setItem('projectScope', JSON.stringify(scope));
// Hide loading, show results
document.getElementById('loadingState').classList.add('hidden');
document.getElementById('frameworkSection').classList.remove('hidden');
document.getElementById('hooksSection').classList.remove('hidden');
document.getElementById('attributesSection').classList.remove('hidden');
document.getElementById('structureSection').classList.remove('hidden');
// Populate hooks
const hooksList = document.getElementById('hooksList');
hooksList.innerHTML = scope.suggestedHooks.map(hook => `
<div class="flex items-center p-3 bg-gray-700 rounded-lg border border-gray-600">
<i data-feather="check-circle" class="w-4 h-4 text-green-500 mr-3"></i>
<span class="text-sm font-mono">${hook}</span>
`).join('');
// Populate attributes
const attributesList = document.getElementById('attributesList');
attributesList.innerHTML = scope.dataAttributes.map(attr => `
<div class="flex items-center p-3 bg-gray-700 rounded-lg border border-gray-600">
<i data-feather="tag" class="w-4 h-4 text-blue-500 mr-3"></i>
<span class="text-sm font-mono">${attr}</span>
</div>
`).join('');
} catch (error) {
console.error('Error generating scope:', error);
document.getElementById('loadingState').classList.add('hidden');
alert('Error generating scope. Please try again.');
}
});
// Framework selection
document.querySelectorAll('.framework-btn').forEach(btn => {
btn.addEventListener('click', function() {
document.querySelectorAll('.framework-btn').forEach(b => b.classList.remove('bg-purple-600', 'bg-pink-600'));
this.classList.add(this.classList.contains('hover:bg-purple-600') ? 'bg-purple-600' : 'bg-pink-600');
localStorage.setItem('selectedFramework', this.dataset.framework);
document.getElementById('continueSection').classList.remove('hidden');
});
// Structure selection
document.querySelectorAll('.structure-btn').forEach(btn => {
btn.addEventListener('click', function() {
document.querySelectorAll('.structure-btn').forEach(b => b.classList.remove('bg-purple-600', 'bg-pink-600'));
this.classList.add(this.classList.contains('hover:bg-purple-600') ? 'bg-purple-600' : 'bg-pink-600');
localStorage.setItem('selectedCodeStructure', this.dataset.structure);
});
// Continue to next page
document.getElementById('continueBtn').addEventListener('click', function() {
window.location.href = 'code.html';
});
});
</script>
</body>
</html>