Skip to content

Single Select dropdown closes on scroll #514

@dankeboy36

Description

@dankeboy36

When I use <vscode-single-select>, the dropdown closes whenever the surrounding content scrolls.

In my app I have a terminal (xterm.js) under a toolbar. The select is in the toolbar and stays visible, but when the terminal prints new lines and scrolls, the dropdown closes.


The attached code is a minimal repro without xterm: it just appends lines to a div and scrolls the page. The result is the same; the dropdown closes by itself when scrolling happens.

vscode-elements-single-select-closes-on-scroll.mov
import {
  VscodeOption,
  VscodeSingleSelect,
} from '@vscode-elements/react-elements'
import { useEffect, useRef } from 'react'
import { createRoot } from 'react-dom/client'

function Repro() {
  const contentRef = useRef(/** @type {HTMLDivElement | null} */ (null))

  useEffect(() => {
    const el = contentRef.current
    if (!el) return

    // seed
    for (let i = 0; i < 30; i++) {
      const d = document.createElement('div')
      d.textContent = `line ${i + 1} — seed`
      el.appendChild(d)
    }

    const id = setInterval(() => {
      const div = document.createElement('div')
      div.textContent = `line ${el.children.length + 1}${new Date().toLocaleTimeString()}`
      el.appendChild(div)

      window.scrollTo({ top: document.documentElement.scrollHeight })

      const selectEl = document.getElementById('demo-select')
      const open = !!(
        selectEl &&
        (selectEl.hasAttribute('open') || selectEl.open === true)
      )
      console.log('[append]', { open })
    }, 700)
    return () => clearInterval(id)
  }, [])

  useEffect(() => {
    const el = document.getElementById('demo-select')
    if (!el) return
    const log = () =>
      console.log(
        '[select] open =',
        el.hasAttribute('open') || el.open === true
      )
    const mo = new MutationObserver(log)
    mo.observe(el, { attributes: true, attributeFilter: ['open'] })
    log()
    return () => mo.disconnect()
  }, [])

  return (
    <div>
      <div style={{ position: 'sticky', top: 0 }}>
        <VscodeSingleSelect id="demo-select" name="demo">
          <VscodeOption value="">Pick one…</VscodeOption>
          <VscodeOption value="1">Option 1</VscodeOption>
          <VscodeOption value="2">Option 2</VscodeOption>
          <VscodeOption value="3">Option 3</VscodeOption>
        </VscodeSingleSelect>
      </div>
      <div ref={contentRef} />
    </div>
  )
}

const root = document.getElementById('root')
createRoot(root).render(<Repro />)

Expected: Dropdown stays open until I close it.
Actual: Dropdown closes automatically on scroll.


Update:
Maybe related #453?


Update2:

As a comparison, native <select> disables the scroll when the popover is visible (on macOS):

native-select.mov

react-select lets the page scroll with an open popover:

react-select.mov

<vscode-single-select> closes the popover on page scroll:

single-select.mov

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions