Skip to content

Single Select dropdown closes on scroll #514

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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions