@@ -246,14 +246,124 @@ class Browser(parent: Disposable, private val mynahAsset: Path, val project: Pro
246246 box-shadow: none !important;
247247 border-radius: 0 !important;
248248 }
249+ /* Hide native select - will be replaced with custom dropdown */
249250 select.mynah-form-input {
250251 -webkit-appearance: menulist !important;
251252 appearance: menulist !important;
252253 padding: 0 !important;
253254 }
255+ select.mynah-form-input[data-jb-replaced="true"] {
256+ position: absolute !important;
257+ width: 1px !important;
258+ height: 1px !important;
259+ opacity: 0 !important;
260+ pointer-events: none !important;
261+ }
254262 .mynah-select-handle {
255263 visibility: hidden;
256264 }
265+
266+ /* Custom dropdown styles with modal overlay */
267+ .jb-custom-select {
268+ position: absolute !important;
269+ width: 100%% !important;
270+ top: 0 !important;
271+ left: 0 !important;
272+ right: 0 !important;
273+ font-family: var(--mynah-font-family) !important;
274+ }
275+
276+ /* Ensure the parent wrapper has fixed width and relative positioning */
277+ .mynah-form-input-wrapper {
278+ position: relative !important;
279+ width: 100%% !important;
280+ min-height: 40px !important;
281+ }
282+
283+ .jb-custom-select-trigger {
284+ display: flex !important;
285+ align-items: center !important;
286+ justify-content: space-between !important;
287+ padding: 8px 8px 8px 6px !important;
288+ background: var(--mynah-color-bg) !important;
289+ border: 1px solid var(--mynah-color-border-default) !important;
290+ border-radius: 4px !important;
291+ cursor: pointer !important;
292+ color: var(--mynah-color-text-default) !important;
293+ width: 100%% !important;
294+ box-sizing: border-box !important;
295+ }
296+
297+ .jb-custom-select-trigger > span:first-child {
298+ white-space: nowrap !important;
299+ }
300+
301+ .jb-custom-select-trigger:hover {
302+ border-color: var(--mynah-color-border-hover, var(--mynah-color-border-default)) !important;
303+ }
304+
305+ .jb-custom-select-arrow {
306+ flex-shrink: 0 !important;
307+ width: 0 !important;
308+ height: 0 !important;
309+ border-left: 4px solid transparent !important;
310+ border-right: 4px solid transparent !important;
311+ border-top: 4px solid var(--mynah-color-text-default) !important;
312+ margin-left: 6px !important;
313+ transition: transform 0.2s !important;
314+ }
315+
316+ .jb-custom-select-arrow.open {
317+ transform: rotate(180deg) !important;
318+ }
319+
320+ /* Dropdown menu - floats with high z-index */
321+ .jb-custom-select-dropdown {
322+ position: fixed !important;
323+ background: var(--mynah-card-bg) !important;
324+ border: 1px solid var(--mynah-color-border-default) !important;
325+ border-radius: 6px !important;
326+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4) !important;
327+ min-width: 200px !important;
328+ max-width: 300px !important;
329+ overflow: hidden !important;
330+ z-index: 2147483647 !important;
331+ display: none !important;
332+ }
333+
334+ .jb-custom-select-dropdown.open {
335+ display: block !important;
336+ }
337+
338+ .jb-custom-select-option {
339+ padding: 6px 14px !important;
340+ cursor: pointer !important;
341+ font-size: 11px !important;
342+ color: var(--mynah-color-text-default) !important;
343+ background: var(--mynah-card-bg) !important;
344+ border-bottom: 1px solid var(--mynah-color-border-default) !important;
345+ transition: background 0.15s !important;
346+ }
347+
348+ .jb-custom-select-option:last-child {
349+ border-bottom: none !important;
350+ }
351+
352+ .jb-custom-select-option:hover {
353+ background: var(--mynah-card-bg-alternate) !important;
354+ color: var(--mynah-color-text-strong) !important;
355+ }
356+
357+ .jb-custom-select-option.selected {
358+ background: var(--mynah-color-button) !important;
359+ color: var(--mynah-color-button-reverse) !important;
360+ font-weight: 500 !important;
361+ }
362+
363+ .jb-custom-select-option.selected:hover {
364+ background: var(--mynah-color-button) !important;
365+ filter: brightness(1.1) !important;
366+ }
257367 .mynah-ui-spinner-container > span.mynah-ui-spinner-logo-part > .mynah-ui-spinner-logo-mask.text {
258368 will-change: transform !important;
259369 transform: translateZ(0) !important;
@@ -269,6 +379,192 @@ class Browser(parent: Disposable, private val mynahAsset: Path, val project: Pro
269379 <script type="text/javascript">
270380 ${ThemeBrowserAdapter ().buildJsCodeToUpdateTheme(EditorThemeAdapter .getThemeFromIde())}
271381 </script>
382+ <script type="text/javascript">
383+ // Custom dropdown for JetBrains
384+ (function() {
385+ let currentOpenDropdown = null;
386+
387+ function replaceSelectWithCustomDropdown() {
388+ const selectElements = document.querySelectorAll('select.mynah-form-input');
389+
390+ selectElements.forEach(function(select) {
391+ // Skip if already replaced
392+ if (select.hasAttribute('data-jb-replaced')) {
393+ return;
394+ }
395+
396+ select.setAttribute('data-jb-replaced', 'true');
397+
398+ // Create custom dropdown container
399+ const container = document.createElement('div');
400+ container.className = 'jb-custom-select';
401+
402+ // Create trigger button
403+ const trigger = document.createElement('div');
404+ trigger.className = 'jb-custom-select-trigger';
405+
406+ const selectedText = document.createElement('span');
407+ selectedText.textContent = select.options[select.selectedIndex]?.text || '';
408+
409+ function adjustFontSize(text, element) {
410+ element.style.fontSize = '11px';
411+ }
412+
413+ // Set initial font size
414+ adjustFontSize(selectedText.textContent, trigger);
415+
416+ const arrow = document.createElement('span');
417+ arrow.className = 'jb-custom-select-arrow';
418+
419+ trigger.appendChild(selectedText);
420+ trigger.appendChild(arrow);
421+
422+ // Create dropdown menu
423+ const dropdown = document.createElement('div');
424+ dropdown.className = 'jb-custom-select-dropdown';
425+
426+ // Add options
427+ if (select.options.length === 0) {
428+ const debugOption = document.createElement('div');
429+ debugOption.className = 'jb-custom-select-option';
430+ debugOption.textContent = 'No models available';
431+ debugOption.style.color = '#ff6b6b';
432+ dropdown.appendChild(debugOption);
433+ }
434+
435+ for (let i = 0; i < select.options.length; i++) {
436+ const option = document.createElement('div');
437+ option.className = 'jb-custom-select-option';
438+ option.textContent = select.options[i].text || ('Option ' + i);
439+ option.setAttribute('data-value', select.options[i].value);
440+
441+ if (i === select.selectedIndex) {
442+ option.classList.add('selected');
443+ }
444+
445+ option.addEventListener('click', function(e) {
446+ e.stopPropagation();
447+
448+ // Update selected value
449+ select.selectedIndex = i;
450+
451+ // Trigger change event on original select
452+ const event = new Event('change', { bubbles: true });
453+ select.dispatchEvent(event);
454+
455+ // Update UI
456+ selectedText.textContent = this.textContent;
457+
458+ // Adjust font size for new text
459+ adjustFontSize(this.textContent, trigger);
460+
461+ // Update selected class
462+ dropdown.querySelectorAll('.jb-custom-select-option').forEach(function(opt) {
463+ opt.classList.remove('selected');
464+ });
465+ this.classList.add('selected');
466+
467+ // Close dropdown
468+ dropdown.classList.remove('open');
469+ arrow.classList.remove('open');
470+ currentOpenDropdown = null;
471+ });
472+
473+ dropdown.appendChild(option);
474+ }
475+
476+ // Toggle dropdown on trigger click
477+ trigger.addEventListener('click', function(e) {
478+ e.stopPropagation();
479+
480+ // Close any other open dropdown
481+ if (currentOpenDropdown && currentOpenDropdown !== dropdown) {
482+ currentOpenDropdown.classList.remove('open');
483+ }
484+
485+ // Toggle this dropdown
486+ const isOpening = !dropdown.classList.contains('open');
487+
488+ if (isOpening) {
489+ // Position dropdown near trigger (smart positioning)
490+ const rect = trigger.getBoundingClientRect();
491+ dropdown.style.left = rect.left + 'px';
492+
493+ // Check if more space above or below
494+ const spaceAbove = rect.top;
495+ const spaceBelow = window.innerHeight - rect.bottom;
496+
497+ if (spaceAbove > spaceBelow) {
498+ // More space above - position above trigger
499+ dropdown.style.bottom = (window.innerHeight - rect.top) + 'px';
500+ dropdown.style.top = 'auto';
501+ } else {
502+ // More space below - position below trigger
503+ dropdown.style.top = rect.bottom + 'px';
504+ dropdown.style.bottom = 'auto';
505+ }
506+
507+ // Show dropdown
508+ dropdown.classList.add('open');
509+ arrow.classList.add('open');
510+ currentOpenDropdown = dropdown;
511+ } else {
512+ // Close dropdown
513+ dropdown.classList.remove('open');
514+ arrow.classList.remove('open');
515+ currentOpenDropdown = null;
516+ }
517+ });
518+
519+ // Build custom dropdown
520+ container.appendChild(trigger);
521+
522+ // Append dropdown to body for proper positioning
523+ document.body.appendChild(dropdown);
524+
525+ // Hide original select and insert custom dropdown trigger
526+ select.style.display = 'none';
527+ select.parentElement.insertBefore(container, select);
528+ });
529+ }
530+
531+ // Close dropdown when clicking outside
532+ document.addEventListener('click', function(e) {
533+ if (currentOpenDropdown) {
534+ currentOpenDropdown.classList.remove('open');
535+ // Also update arrow state
536+ const arrows = document.querySelectorAll('.jb-custom-select-arrow.open');
537+ arrows.forEach(function(arrow) {
538+ arrow.classList.remove('open');
539+ });
540+ currentOpenDropdown = null;
541+ }
542+ });
543+
544+ // Try to replace immediately
545+ replaceSelectWithCustomDropdown();
546+
547+ // Also watch for new selects being added (mynah-ui might add them dynamically)
548+ const observer = new MutationObserver(function() {
549+ replaceSelectWithCustomDropdown();
550+ });
551+
552+ // Start observing once DOM is ready
553+ if (document.body) {
554+ observer.observe(document.body, {
555+ childList: true,
556+ subtree: true
557+ });
558+ } else {
559+ document.addEventListener('DOMContentLoaded', function() {
560+ observer.observe(document.body, {
561+ childList: true,
562+ subtree: true
563+ });
564+ });
565+ }
566+ })();
567+ </script>
272568 </body>
273569 </html>
274570 """ .trimIndent()
0 commit comments