diff --git a/neode-ui/index.html b/neode-ui/index.html index a486583f..c0e2ceb1 100644 --- a/neode-ui/index.html +++ b/neode-ui/index.html @@ -14,6 +14,8 @@ + + diff --git a/neode-ui/src/components/AppSwitcher.vue b/neode-ui/src/components/AppSwitcher.vue index 0bf5d32a..a3db347b 100644 --- a/neode-ui/src/components/AppSwitcher.vue +++ b/neode-ui/src/components/AppSwitcher.vue @@ -104,11 +104,11 @@ function handleClickOutside(e: MouseEvent) { } onMounted(() => { - document.addEventListener('click', handleClickOutside) + document.addEventListener('pointerdown', handleClickOutside) }) onBeforeUnmount(() => { - document.removeEventListener('click', handleClickOutside) + document.removeEventListener('pointerdown', handleClickOutside) }) diff --git a/neode-ui/src/components/IdentityPicker.vue b/neode-ui/src/components/IdentityPicker.vue index 4fdc892e..d42e8411 100644 --- a/neode-ui/src/components/IdentityPicker.vue +++ b/neode-ui/src/components/IdentityPicker.vue @@ -131,10 +131,10 @@ async function loadIdentities() { onMounted(() => { loadIdentities() - document.addEventListener('click', onClickOutside) + document.addEventListener('pointerdown', onClickOutside) }) onBeforeUnmount(() => { - document.removeEventListener('click', onClickOutside) + document.removeEventListener('pointerdown', onClickOutside) }) diff --git a/neode-ui/src/style.css b/neode-ui/src/style.css index d17b1302..eaa2ceb8 100644 --- a/neode-ui/src/style.css +++ b/neode-ui/src/style.css @@ -2,6 +2,22 @@ @tailwind components; @tailwind utilities; +/* The app is dark-only — NEVER let the OS/browser theme leak into native + controls. Without this, select popups / scrollbars / date pickers follow + the user's OS setting (a light-mode ThinkPad rendered white dropdown + lists inside the dark UI, 2026-07-22). color-scheme pins Chromium's + native select popup dark; the explicit select/option rules cover + Firefox and the closed control itself. */ +:root { + color-scheme: dark; +} +select, +select option, +select optgroup { + background-color: #16181d; + color: #fff; +} + /* Montserrat - header font (used in neode present) */ @font-face { font-family: 'Montserrat'; diff --git a/neode-ui/src/views/Mesh.vue b/neode-ui/src/views/Mesh.vue index 10bdac71..64902469 100644 --- a/neode-ui/src/views/Mesh.vue +++ b/neode-ui/src/views/Mesh.vue @@ -350,7 +350,7 @@ function updateKeyboardInset() { onMounted(async () => { window.addEventListener('resize', handleResize) - document.addEventListener('click', handleDocClickForMenu) + document.addEventListener('pointerdown', handleDocClickForMenu) window.addEventListener('archipelago:share-to-mesh', loadPendingFromSession) if (window.visualViewport) { window.visualViewport.addEventListener('resize', updateKeyboardInset) @@ -403,7 +403,7 @@ onMounted(async () => { onUnmounted(() => { window.removeEventListener('resize', handleResize) - document.removeEventListener('click', handleDocClickForMenu) + document.removeEventListener('pointerdown', handleDocClickForMenu) window.removeEventListener('archipelago:share-to-mesh', loadPendingFromSession) if (window.visualViewport) { window.visualViewport.removeEventListener('resize', updateKeyboardInset) @@ -1337,8 +1337,8 @@ function closeAttachMenuOnOutsideClick(ev: MouseEvent) { const target = ev.target as HTMLElement if (!target.closest('.mesh-attach-menu-anchor')) showAttachMenu.value = false } -onMounted(() => document.addEventListener('click', closeAttachMenuOnOutsideClick)) -onUnmounted(() => document.removeEventListener('click', closeAttachMenuOnOutsideClick)) +onMounted(() => document.addEventListener('pointerdown', closeAttachMenuOnOutsideClick)) +onUnmounted(() => document.removeEventListener('pointerdown', closeAttachMenuOnOutsideClick)) const attachError = ref(null) const fetchingCids = ref>(new Set()) const fetchedUrls = ref>(new Map())