Spaces:
Running
Running
I want the info icon button inside the dropdown menu, if possible. The reason is to maximize the size of select box
Browse files- index.html +94 -35
- script.js +89 -38
- style.css +68 -2
index.html
CHANGED
|
@@ -68,50 +68,110 @@
|
|
| 68 |
<p class="text-sm text-gray-500 dark:text-gray-400">Configure your AI image generation settings</p>
|
| 69 |
</div>
|
| 70 |
</div>
|
| 71 |
-
|
| 72 |
<!-- Model Selector Component -->
|
| 73 |
<div class="space-y-4">
|
| 74 |
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
| 75 |
Select Model
|
| 76 |
</label>
|
| 77 |
|
| 78 |
-
<!-- Custom
|
| 79 |
-
<div class="relative group">
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
<option value="stable-diffusion-xl">Stable Diffusion XL</option>
|
| 89 |
-
<option value="dall-e-3">DALL-E 3</option>
|
| 90 |
-
<option value="midjourney-v6">Midjourney V6</option>
|
| 91 |
-
<option value="imagen-3">Imagen 3</option>
|
| 92 |
-
<option value="firefly-3">Adobe Firefly 3</option>
|
| 93 |
-
<option value="leonardo-phoenix">Leonardo Phoenix</option>
|
| 94 |
-
</select>
|
| 95 |
-
<!-- Custom Arrow -->
|
| 96 |
-
<div class="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none">
|
| 97 |
-
<i data-feather="chevron-down" class="w-5 h-5 text-gray-400"></i>
|
| 98 |
-
</div>
|
| 99 |
-
</div>
|
| 100 |
-
|
| 101 |
-
<!-- Info Button -->
|
| 102 |
-
<button
|
| 103 |
-
id="infoBtn"
|
| 104 |
-
disabled
|
| 105 |
-
class="px-4 bg-gray-100 dark:bg-gray-700 border border-l-0 border-gray-300 dark:border-gray-600 rounded-r-xl flex items-center justify-center transition-all duration-200 disabled:opacity-40 disabled:cursor-not-allowed hover:bg-primary-50 dark:hover:bg-primary-900/20 hover:border-primary-300 dark:hover:border-primary-700 group/btn"
|
| 106 |
-
>
|
| 107 |
-
<i data-feather="info" class="w-5 h-5 text-gray-500 dark:text-gray-400 group-hover/btn:text-primary-500 transition-colors"></i>
|
| 108 |
-
</button>
|
| 109 |
-
</div>
|
| 110 |
|
| 111 |
<!-- Floating Label Animation -->
|
| 112 |
<div class="absolute -top-2 left-3 px-1 bg-white dark:bg-gray-800 text-xs text-primary-500 font-medium opacity-0 transition-opacity duration-200" id="floatingLabel">
|
| 113 |
Modelo
|
| 114 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 115 |
</div>
|
| 116 |
|
| 117 |
<!-- Selected Model Display -->
|
|
@@ -127,8 +187,7 @@
|
|
| 127 |
</div>
|
| 128 |
</div>
|
| 129 |
</div>
|
| 130 |
-
|
| 131 |
-
<!-- Additional Settings -->
|
| 132 |
<div class="mt-8 pt-6 border-t border-gray-100 dark:border-gray-700">
|
| 133 |
<h3 class="text-sm font-medium text-gray-700 dark:text-gray-300 mb-4">Quick Settings</h3>
|
| 134 |
<div class="grid grid-cols-2 gap-4">
|
|
|
|
| 68 |
<p class="text-sm text-gray-500 dark:text-gray-400">Configure your AI image generation settings</p>
|
| 69 |
</div>
|
| 70 |
</div>
|
|
|
|
| 71 |
<!-- Model Selector Component -->
|
| 72 |
<div class="space-y-4">
|
| 73 |
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
| 74 |
Select Model
|
| 75 |
</label>
|
| 76 |
|
| 77 |
+
<!-- Custom Dropdown with Info Button Inside -->
|
| 78 |
+
<div class="relative group" id="customDropdown">
|
| 79 |
+
<!-- Dropdown Trigger -->
|
| 80 |
+
<button
|
| 81 |
+
id="dropdownTrigger"
|
| 82 |
+
class="w-full flex items-center justify-between bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-xl px-4 py-3 text-gray-700 dark:text-gray-200 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent transition-all duration-200 hover:border-primary-300 dark:hover:border-primary-700"
|
| 83 |
+
>
|
| 84 |
+
<span id="dropdownSelectedText">Choose a model...</span>
|
| 85 |
+
<i data-feather="chevron-down" class="w-5 h-5 text-gray-400 transition-transform duration-200" id="dropdownArrow"></i>
|
| 86 |
+
</button>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 87 |
|
| 88 |
<!-- Floating Label Animation -->
|
| 89 |
<div class="absolute -top-2 left-3 px-1 bg-white dark:bg-gray-800 text-xs text-primary-500 font-medium opacity-0 transition-opacity duration-200" id="floatingLabel">
|
| 90 |
Modelo
|
| 91 |
</div>
|
| 92 |
+
|
| 93 |
+
<!-- Dropdown Menu -->
|
| 94 |
+
<div id="dropdownMenu" class="absolute z-20 w-full mt-2 bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-xl shadow-xl opacity-0 invisible transform scale-95 transition-all duration-200 origin-top">
|
| 95 |
+
<div class="py-1 max-h-64 overflow-y-auto">
|
| 96 |
+
<!-- Stable Diffusion XL -->
|
| 97 |
+
<div class="dropdown-item group/item flex items-center justify-between px-4 py-3 hover:bg-primary-50 dark:hover:bg-primary-900/20 cursor-pointer transition-colors border-b border-gray-100 dark:border-gray-600 last:border-b-0" data-value="stable-diffusion-xl">
|
| 98 |
+
<div class="flex items-center gap-3">
|
| 99 |
+
<div class="w-8 h-8 rounded-lg bg-gradient-to-br from-blue-500 to-cyan-500 flex items-center justify-center">
|
| 100 |
+
<i data-feather="cpu" class="text-white w-4 h-4"></i>
|
| 101 |
+
</div>
|
| 102 |
+
<span class="font-medium text-gray-800 dark:text-gray-200">Stable Diffusion XL</span>
|
| 103 |
+
</div>
|
| 104 |
+
<button class="info-btn p-2 rounded-lg hover:bg-primary-200 dark:hover:bg-primary-800 transition-colors opacity-0 group-hover/item:opacity-100" data-model="stable-diffusion-xl">
|
| 105 |
+
<i data-feather="info" class="w-4 h-4 text-primary-600 dark:text-primary-400"></i>
|
| 106 |
+
</button>
|
| 107 |
+
</div>
|
| 108 |
+
|
| 109 |
+
<!-- DALL-E 3 -->
|
| 110 |
+
<div class="dropdown-item group/item flex items-center justify-between px-4 py-3 hover:bg-primary-50 dark:hover:bg-primary-900/20 cursor-pointer transition-colors border-b border-gray-100 dark:border-gray-600 last:border-b-0" data-value="dall-e-3">
|
| 111 |
+
<div class="flex items-center gap-3">
|
| 112 |
+
<div class="w-8 h-8 rounded-lg bg-gradient-to-br from-green-500 to-emerald-500 flex items-center justify-center">
|
| 113 |
+
<i data-feather="image" class="text-white w-4 h-4"></i>
|
| 114 |
+
</div>
|
| 115 |
+
<span class="font-medium text-gray-800 dark:text-gray-200">DALL-E 3</span>
|
| 116 |
+
</div>
|
| 117 |
+
<button class="info-btn p-2 rounded-lg hover:bg-primary-200 dark:hover:bg-primary-800 transition-colors opacity-0 group-hover/item:opacity-100" data-model="dall-e-3">
|
| 118 |
+
<i data-feather="info" class="w-4 h-4 text-primary-600 dark:text-primary-400"></i>
|
| 119 |
+
</button>
|
| 120 |
+
</div>
|
| 121 |
+
|
| 122 |
+
<!-- Midjourney V6 -->
|
| 123 |
+
<div class="dropdown-item group/item flex items-center justify-between px-4 py-3 hover:bg-primary-50 dark:hover:bg-primary-900/20 cursor-pointer transition-colors border-b border-gray-100 dark:border-gray-600 last:border-b-0" data-value="midjourney-v6">
|
| 124 |
+
<div class="flex items-center gap-3">
|
| 125 |
+
<div class="w-8 h-8 rounded-lg bg-gradient-to-br from-purple-500 to-pink-500 flex items-center justify-center">
|
| 126 |
+
<i data-feather="aperture" class="text-white w-4 h-4"></i>
|
| 127 |
+
</div>
|
| 128 |
+
<span class="font-medium text-gray-800 dark:text-gray-200">Midjourney V6</span>
|
| 129 |
+
</div>
|
| 130 |
+
<button class="info-btn p-2 rounded-lg hover:bg-primary-200 dark:hover:bg-primary-800 transition-colors opacity-0 group-hover/item:opacity-100" data-model="midjourney-v6">
|
| 131 |
+
<i data-feather="info" class="w-4 h-4 text-primary-600 dark:text-primary-400"></i>
|
| 132 |
+
</button>
|
| 133 |
+
</div>
|
| 134 |
+
|
| 135 |
+
<!-- Imagen 3 -->
|
| 136 |
+
<div class="dropdown-item group/item flex items-center justify-between px-4 py-3 hover:bg-primary-50 dark:hover:bg-primary-900/20 cursor-pointer transition-colors border-b border-gray-100 dark:border-gray-600 last:border-b-0" data-value="imagen-3">
|
| 137 |
+
<div class="flex items-center gap-3">
|
| 138 |
+
<div class="w-8 h-8 rounded-lg bg-gradient-to-br from-red-500 to-orange-500 flex items-center justify-center">
|
| 139 |
+
<i data-feather="camera" class="text-white w-4 h-4"></i>
|
| 140 |
+
</div>
|
| 141 |
+
<span class="font-medium text-gray-800 dark:text-gray-200">Imagen 3</span>
|
| 142 |
+
</div>
|
| 143 |
+
<button class="info-btn p-2 rounded-lg hover:bg-primary-200 dark:hover:bg-primary-800 transition-colors opacity-0 group-hover/item:opacity-100" data-model="imagen-3">
|
| 144 |
+
<i data-feather="info" class="w-4 h-4 text-primary-600 dark:text-primary-400"></i>
|
| 145 |
+
</button>
|
| 146 |
+
</div>
|
| 147 |
+
|
| 148 |
+
<!-- Adobe Firefly 3 -->
|
| 149 |
+
<div class="dropdown-item group/item flex items-center justify-between px-4 py-3 hover:bg-primary-50 dark:hover:bg-primary-900/20 cursor-pointer transition-colors border-b border-gray-100 dark:border-gray-600 last:border-b-0" data-value="firefly-3">
|
| 150 |
+
<div class="flex items-center gap-3">
|
| 151 |
+
<div class="w-8 h-8 rounded-lg bg-gradient-to-br from-yellow-500 to-amber-500 flex items-center justify-center">
|
| 152 |
+
<i data-feather="sun" class="text-white w-4 h-4"></i>
|
| 153 |
+
</div>
|
| 154 |
+
<span class="font-medium text-gray-800 dark:text-gray-200">Adobe Firefly 3</span>
|
| 155 |
+
</div>
|
| 156 |
+
<button class="info-btn p-2 rounded-lg hover:bg-primary-200 dark:hover:bg-primary-800 transition-colors opacity-0 group-hover/item:opacity-100" data-model="firefly-3">
|
| 157 |
+
<i data-feather="info" class="w-4 h-4 text-primary-600 dark:text-primary-400"></i>
|
| 158 |
+
</button>
|
| 159 |
+
</div>
|
| 160 |
+
|
| 161 |
+
<!-- Leonardo Phoenix -->
|
| 162 |
+
<div class="dropdown-item group/item flex items-center justify-between px-4 py-3 hover:bg-primary-50 dark:hover:bg-primary-900/20 cursor-pointer transition-colors" data-value="leonardo-phoenix">
|
| 163 |
+
<div class="flex items-center gap-3">
|
| 164 |
+
<div class="w-8 h-8 rounded-lg bg-gradient-to-br from-indigo-500 to-violet-500 flex items-center justify-center">
|
| 165 |
+
<i data-feather="zap" class="text-white w-4 h-4"></i>
|
| 166 |
+
</div>
|
| 167 |
+
<span class="font-medium text-gray-800 dark:text-gray-200">Leonardo Phoenix</span>
|
| 168 |
+
</div>
|
| 169 |
+
<button class="info-btn p-2 rounded-lg hover:bg-primary-200 dark:hover:bg-primary-800 transition-colors opacity-0 group-hover/item:opacity-100" data-model="leonardo-phoenix">
|
| 170 |
+
<i data-feather="info" class="w-4 h-4 text-primary-600 dark:text-primary-400"></i>
|
| 171 |
+
</button>
|
| 172 |
+
</div>
|
| 173 |
+
</div>
|
| 174 |
+
</div>
|
| 175 |
</div>
|
| 176 |
|
| 177 |
<!-- Selected Model Display -->
|
|
|
|
| 187 |
</div>
|
| 188 |
</div>
|
| 189 |
</div>
|
| 190 |
+
<!-- Additional Settings -->
|
|
|
|
| 191 |
<div class="mt-8 pt-6 border-t border-gray-100 dark:border-gray-700">
|
| 192 |
<h3 class="text-sm font-medium text-gray-700 dark:text-gray-300 mb-4">Quick Settings</h3>
|
| 193 |
<div class="grid grid-cols-2 gap-4">
|
script.js
CHANGED
|
@@ -61,10 +61,12 @@ const modelData = {
|
|
| 61 |
tags: ['Gaming', 'Assets', 'Fine-tune', 'Community']
|
| 62 |
}
|
| 63 |
};
|
| 64 |
-
|
| 65 |
// DOM Elements
|
| 66 |
-
const
|
| 67 |
-
const
|
|
|
|
|
|
|
|
|
|
| 68 |
const modal = document.getElementById('modelModal');
|
| 69 |
const modalBackdrop = document.getElementById('modalBackdrop');
|
| 70 |
const modalContent = document.getElementById('modalContent');
|
|
@@ -73,7 +75,6 @@ const floatingLabel = document.getElementById('floatingLabel');
|
|
| 73 |
const selectedDisplay = document.getElementById('selectedDisplay');
|
| 74 |
const selectedModelName = document.getElementById('selectedModelName');
|
| 75 |
const themeToggle = document.getElementById('themeToggle');
|
| 76 |
-
|
| 77 |
// Modal content elements
|
| 78 |
const modalTitle = document.getElementById('modalTitle');
|
| 79 |
const modalVersion = document.getElementById('modalVersion');
|
|
@@ -83,16 +84,16 @@ const modalSpeed = document.getElementById('modalSpeed');
|
|
| 83 |
const modalStyle = document.getElementById('modalStyle');
|
| 84 |
const modalLicense = document.getElementById('modalLicense');
|
| 85 |
const modalTags = document.getElementById('modalTags');
|
| 86 |
-
|
| 87 |
// State
|
| 88 |
let currentModel = null;
|
|
|
|
| 89 |
|
| 90 |
// Initialize
|
| 91 |
document.addEventListener('DOMContentLoaded', () => {
|
| 92 |
feather.replace();
|
| 93 |
initTheme();
|
|
|
|
| 94 |
});
|
| 95 |
-
|
| 96 |
// Theme handling
|
| 97 |
function initTheme() {
|
| 98 |
const savedTheme = localStorage.getItem('theme') || 'light';
|
|
@@ -107,42 +108,104 @@ themeToggle.addEventListener('click', () => {
|
|
| 107 |
localStorage.setItem('theme', isDark ? 'dark' : 'light');
|
| 108 |
feather.replace();
|
| 109 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 110 |
|
| 111 |
-
|
| 112 |
-
modelSelect.addEventListener('change', (e) => {
|
| 113 |
-
const value = e.target.value;
|
| 114 |
currentModel = value;
|
| 115 |
|
| 116 |
if (value) {
|
| 117 |
-
// Enable info button
|
| 118 |
-
infoBtn.disabled = false;
|
| 119 |
-
|
| 120 |
// Show floating label
|
| 121 |
floatingLabel.classList.add('show-label');
|
| 122 |
|
| 123 |
-
//
|
| 124 |
const model = modelData[value];
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
selectedModelName.textContent = model.name;
|
| 126 |
selectedDisplay.classList.remove('hidden');
|
| 127 |
selectedDisplay.classList.add('selected-show');
|
| 128 |
|
| 129 |
// Add focus ring animation
|
| 130 |
-
|
| 131 |
setTimeout(() => {
|
| 132 |
-
|
| 133 |
}, 300);
|
| 134 |
-
} else {
|
| 135 |
-
infoBtn.disabled = true;
|
| 136 |
-
floatingLabel.classList.remove('show-label');
|
| 137 |
-
selectedDisplay.classList.add('hidden');
|
| 138 |
}
|
| 139 |
-
}
|
| 140 |
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
if (!currentModel) return;
|
| 144 |
-
|
| 145 |
-
const model = modelData[currentModel];
|
| 146 |
if (!model) return;
|
| 147 |
|
| 148 |
// Populate modal
|
|
@@ -163,8 +226,7 @@ infoBtn.addEventListener('click', () => {
|
|
| 163 |
|
| 164 |
// Show modal
|
| 165 |
openModal();
|
| 166 |
-
}
|
| 167 |
-
|
| 168 |
// Modal functions
|
| 169 |
function openModal() {
|
| 170 |
modal.classList.remove('hidden');
|
|
@@ -222,14 +284,3 @@ document.getElementById('docsBtn').addEventListener('click', () => {
|
|
| 222 |
window.open(urls[currentModel], '_blank');
|
| 223 |
}
|
| 224 |
});
|
| 225 |
-
|
| 226 |
-
// Add hover effect to info button
|
| 227 |
-
infoBtn.addEventListener('mouseenter', () => {
|
| 228 |
-
if (!infoBtn.disabled) {
|
| 229 |
-
infoBtn.classList.add('btn-glow');
|
| 230 |
-
}
|
| 231 |
-
});
|
| 232 |
-
|
| 233 |
-
infoBtn.addEventListener('mouseleave', () => {
|
| 234 |
-
infoBtn.classList.remove('btn-glow');
|
| 235 |
-
});
|
|
|
|
| 61 |
tags: ['Gaming', 'Assets', 'Fine-tune', 'Community']
|
| 62 |
}
|
| 63 |
};
|
|
|
|
| 64 |
// DOM Elements
|
| 65 |
+
const dropdownTrigger = document.getElementById('dropdownTrigger');
|
| 66 |
+
const dropdownMenu = document.getElementById('dropdownMenu');
|
| 67 |
+
const dropdownArrow = document.getElementById('dropdownArrow');
|
| 68 |
+
const dropdownSelectedText = document.getElementById('dropdownSelectedText');
|
| 69 |
+
const customDropdown = document.getElementById('customDropdown');
|
| 70 |
const modal = document.getElementById('modelModal');
|
| 71 |
const modalBackdrop = document.getElementById('modalBackdrop');
|
| 72 |
const modalContent = document.getElementById('modalContent');
|
|
|
|
| 75 |
const selectedDisplay = document.getElementById('selectedDisplay');
|
| 76 |
const selectedModelName = document.getElementById('selectedModelName');
|
| 77 |
const themeToggle = document.getElementById('themeToggle');
|
|
|
|
| 78 |
// Modal content elements
|
| 79 |
const modalTitle = document.getElementById('modalTitle');
|
| 80 |
const modalVersion = document.getElementById('modalVersion');
|
|
|
|
| 84 |
const modalStyle = document.getElementById('modalStyle');
|
| 85 |
const modalLicense = document.getElementById('modalLicense');
|
| 86 |
const modalTags = document.getElementById('modalTags');
|
|
|
|
| 87 |
// State
|
| 88 |
let currentModel = null;
|
| 89 |
+
let isDropdownOpen = false;
|
| 90 |
|
| 91 |
// Initialize
|
| 92 |
document.addEventListener('DOMContentLoaded', () => {
|
| 93 |
feather.replace();
|
| 94 |
initTheme();
|
| 95 |
+
initDropdown();
|
| 96 |
});
|
|
|
|
| 97 |
// Theme handling
|
| 98 |
function initTheme() {
|
| 99 |
const savedTheme = localStorage.getItem('theme') || 'light';
|
|
|
|
| 108 |
localStorage.setItem('theme', isDark ? 'dark' : 'light');
|
| 109 |
feather.replace();
|
| 110 |
});
|
| 111 |
+
// Dropdown functions
|
| 112 |
+
function initDropdown() {
|
| 113 |
+
// Toggle dropdown on trigger click
|
| 114 |
+
dropdownTrigger.addEventListener('click', (e) => {
|
| 115 |
+
e.stopPropagation();
|
| 116 |
+
toggleDropdown();
|
| 117 |
+
});
|
| 118 |
+
|
| 119 |
+
// Handle dropdown item clicks
|
| 120 |
+
document.querySelectorAll('.dropdown-item').forEach(item => {
|
| 121 |
+
item.addEventListener('click', (e) => {
|
| 122 |
+
// Don't select if info button was clicked
|
| 123 |
+
if (e.target.closest('.info-btn')) {
|
| 124 |
+
e.stopPropagation();
|
| 125 |
+
return;
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
const value = item.dataset.value;
|
| 129 |
+
selectModel(value);
|
| 130 |
+
closeDropdown();
|
| 131 |
+
});
|
| 132 |
+
});
|
| 133 |
+
|
| 134 |
+
// Handle info button clicks
|
| 135 |
+
document.querySelectorAll('.info-btn').forEach(btn => {
|
| 136 |
+
btn.addEventListener('click', (e) => {
|
| 137 |
+
e.stopPropagation();
|
| 138 |
+
const modelKey = btn.dataset.model;
|
| 139 |
+
showModelInfo(modelKey);
|
| 140 |
+
});
|
| 141 |
+
});
|
| 142 |
+
|
| 143 |
+
// Close dropdown when clicking outside
|
| 144 |
+
document.addEventListener('click', (e) => {
|
| 145 |
+
if (isDropdownOpen && !customDropdown.contains(e.target)) {
|
| 146 |
+
closeDropdown();
|
| 147 |
+
}
|
| 148 |
+
});
|
| 149 |
+
|
| 150 |
+
// Close dropdown on escape key
|
| 151 |
+
document.addEventListener('keydown', (e) => {
|
| 152 |
+
if (e.key === 'Escape' && isDropdownOpen) {
|
| 153 |
+
closeDropdown();
|
| 154 |
+
}
|
| 155 |
+
});
|
| 156 |
+
}
|
| 157 |
+
|
| 158 |
+
function toggleDropdown() {
|
| 159 |
+
if (isDropdownOpen) {
|
| 160 |
+
closeDropdown();
|
| 161 |
+
} else {
|
| 162 |
+
openDropdown();
|
| 163 |
+
}
|
| 164 |
+
}
|
| 165 |
+
|
| 166 |
+
function openDropdown() {
|
| 167 |
+
isDropdownOpen = true;
|
| 168 |
+
dropdownMenu.classList.remove('opacity-0', 'invisible', 'scale-95');
|
| 169 |
+
dropdownMenu.classList.add('opacity-100', 'visible', 'scale-100');
|
| 170 |
+
dropdownArrow.classList.add('rotate-180');
|
| 171 |
+
dropdownTrigger.classList.add('ring-2', 'ring-primary-500', 'border-transparent');
|
| 172 |
+
}
|
| 173 |
+
|
| 174 |
+
function closeDropdown() {
|
| 175 |
+
isDropdownOpen = false;
|
| 176 |
+
dropdownMenu.classList.add('opacity-0', 'invisible', 'scale-95');
|
| 177 |
+
dropdownMenu.classList.remove('opacity-100', 'visible', 'scale-100');
|
| 178 |
+
dropdownArrow.classList.remove('rotate-180');
|
| 179 |
+
dropdownTrigger.classList.remove('ring-2', 'ring-primary-500', 'border-transparent');
|
| 180 |
+
}
|
| 181 |
|
| 182 |
+
function selectModel(value) {
|
|
|
|
|
|
|
| 183 |
currentModel = value;
|
| 184 |
|
| 185 |
if (value) {
|
|
|
|
|
|
|
|
|
|
| 186 |
// Show floating label
|
| 187 |
floatingLabel.classList.add('show-label');
|
| 188 |
|
| 189 |
+
// Update trigger text
|
| 190 |
const model = modelData[value];
|
| 191 |
+
dropdownSelectedText.textContent = model.name;
|
| 192 |
+
dropdownSelectedText.classList.add('text-gray-800', 'dark:text-white');
|
| 193 |
+
|
| 194 |
+
// Show selected display
|
| 195 |
selectedModelName.textContent = model.name;
|
| 196 |
selectedDisplay.classList.remove('hidden');
|
| 197 |
selectedDisplay.classList.add('selected-show');
|
| 198 |
|
| 199 |
// Add focus ring animation
|
| 200 |
+
dropdownTrigger.classList.add('focus-ring-animate');
|
| 201 |
setTimeout(() => {
|
| 202 |
+
dropdownTrigger.classList.remove('focus-ring-animate');
|
| 203 |
}, 300);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 204 |
}
|
| 205 |
+
}
|
| 206 |
|
| 207 |
+
function showModelInfo(modelKey) {
|
| 208 |
+
const model = modelData[modelKey];
|
|
|
|
|
|
|
|
|
|
| 209 |
if (!model) return;
|
| 210 |
|
| 211 |
// Populate modal
|
|
|
|
| 226 |
|
| 227 |
// Show modal
|
| 228 |
openModal();
|
| 229 |
+
}
|
|
|
|
| 230 |
// Modal functions
|
| 231 |
function openModal() {
|
| 232 |
modal.classList.remove('hidden');
|
|
|
|
| 284 |
window.open(urls[currentModel], '_blank');
|
| 285 |
}
|
| 286 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
style.css
CHANGED
|
@@ -119,12 +119,78 @@ select option {
|
|
| 119 |
padding: 12px;
|
| 120 |
font-size: 14px;
|
| 121 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 122 |
|
| 123 |
-
|
| 124 |
-
|
|
|
|
|
|
|
|
|
|
| 125 |
transform: scale(0.95);
|
| 126 |
}
|
| 127 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 128 |
/* Floating label show */
|
| 129 |
.show-label {
|
| 130 |
opacity: 1 !important;
|
|
|
|
| 119 |
padding: 12px;
|
| 120 |
font-size: 14px;
|
| 121 |
}
|
| 122 |
+
/* Dropdown menu animations */
|
| 123 |
+
#dropdownMenu {
|
| 124 |
+
transform-origin: top;
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
/* Info button in dropdown */
|
| 128 |
+
.info-btn {
|
| 129 |
+
transition: all 0.2s ease;
|
| 130 |
+
}
|
| 131 |
|
| 132 |
+
.info-btn:hover {
|
| 133 |
+
transform: scale(1.1);
|
| 134 |
+
}
|
| 135 |
+
|
| 136 |
+
.info-btn:active {
|
| 137 |
transform: scale(0.95);
|
| 138 |
}
|
| 139 |
|
| 140 |
+
/* Dropdown item hover effects */
|
| 141 |
+
.dropdown-item {
|
| 142 |
+
position: relative;
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
.dropdown-item::before {
|
| 146 |
+
content: '';
|
| 147 |
+
position: absolute;
|
| 148 |
+
left: 0;
|
| 149 |
+
top: 0;
|
| 150 |
+
bottom: 0;
|
| 151 |
+
width: 3px;
|
| 152 |
+
background: linear-gradient(to bottom, #0ea5e9, #d946ef);
|
| 153 |
+
opacity: 0;
|
| 154 |
+
transition: opacity 0.2s ease;
|
| 155 |
+
}
|
| 156 |
+
|
| 157 |
+
.dropdown-item:hover::before {
|
| 158 |
+
opacity: 1;
|
| 159 |
+
}
|
| 160 |
+
|
| 161 |
+
/* Dropdown arrow rotation */
|
| 162 |
+
#dropdownArrow {
|
| 163 |
+
transition: transform 0.2s ease;
|
| 164 |
+
}
|
| 165 |
+
|
| 166 |
+
#dropdownArrow.rotate-180 {
|
| 167 |
+
transform: rotate(180deg);
|
| 168 |
+
}
|
| 169 |
+
|
| 170 |
+
/* Custom scrollbar for dropdown */
|
| 171 |
+
#dropdownMenu::-webkit-scrollbar {
|
| 172 |
+
width: 6px;
|
| 173 |
+
}
|
| 174 |
+
|
| 175 |
+
#dropdownMenu::-webkit-scrollbar-track {
|
| 176 |
+
background: transparent;
|
| 177 |
+
border-radius: 0 8px 8px 0;
|
| 178 |
+
}
|
| 179 |
+
|
| 180 |
+
#dropdownMenu::-webkit-scrollbar-thumb {
|
| 181 |
+
background: #cbd5e1;
|
| 182 |
+
border-radius: 3px;
|
| 183 |
+
}
|
| 184 |
+
|
| 185 |
+
.dark #dropdownMenu::-webkit-scrollbar-thumb {
|
| 186 |
+
background: #475569;
|
| 187 |
+
}
|
| 188 |
+
|
| 189 |
+
/* Dropdown trigger focus state */
|
| 190 |
+
#dropdownTrigger:focus,
|
| 191 |
+
#dropdownTrigger.ring-2 {
|
| 192 |
+
border-color: transparent;
|
| 193 |
+
}
|
| 194 |
/* Floating label show */
|
| 195 |
.show-label {
|
| 196 |
opacity: 1 !important;
|