Skip to content

Combobox with Chips locks body scroll even with modal={false} #4506

@ryanrhee

Description

@ryanrhee

Description

When using Combobox.Chips / Combobox.ChipsInput (instead of Combobox.Input), the body gets overflow: hidden on mount even when modal={false} is set on the Root.

Using Combobox.Input with the same configuration does not exhibit this behavior.

Minimal reproduction

"use client";

import { Combobox } from "@base-ui/react/combobox";

export default function Repro() {
  return (
    <div style={{ height: "200vh", padding: 20 }}>
      <h1>Scroll test</h1>

      <Combobox.Root multiple modal={false}>
        <Combobox.Chips>
          <Combobox.ChipsInput placeholder="Type here..." />
        </Combobox.Chips>
        <Combobox.Portal>
          <Combobox.Positioner>
            <Combobox.Popup>
              <Combobox.List>
                <Combobox.Item value="a">Alpha</Combobox.Item>
              </Combobox.List>
            </Combobox.Popup>
          </Combobox.Positioner>
        </Combobox.Portal>
      </Combobox.Root>

      <div style={{ height: "100vh", background: "#eee", marginTop: 20 }}>
        You should be able to scroll to see this.
      </div>
    </div>
  );
}

Expected behavior

Page should be scrollable. modal={false} should prevent scroll locking.

Actual behavior

document.body gets style="overflow: hidden;" on mount, preventing all page scrolling.

Root cause analysis

The ComboboxPositioner passes open && modal && openMethod !== 'touch' to useScrollLock(). When using Combobox.Chips/ChipsInput, the store's open value is undefined on initial render (rather than false as with Combobox.Input).

The && chain undefined && false evaluates to undefined (not false). The useScrollLock function signature is:

function useScrollLock(enabled = true, referenceElement = null)

Since undefined triggers the default parameter, enabled becomes true, and the scroll lock is acquired on mount.

Workaround

Setting defaultOpen={false} on the Root forces the store to initialize open as false:

<Combobox.Root multiple modal={false} defaultOpen={false}>

Possible fixes

  1. Initialize the combobox store's open to false when using Chips (same as Input path)
  2. Coerce the expression in ComboboxPositioner: useScrollLock(!!(open && modal && openMethod !== 'touch'), triggerElement)
  3. Change useScrollLock signature to not use a default parameter: function useScrollLock(enabled, ...) { if (!enabled) return; ... }

Environment

  • @base-ui/react: 1.3.0
  • next: 16.2.2
  • react: 19.2.4
  • macOS (overlay scrollbars)

Metadata

Metadata

Assignees

No one assigned

    Labels

    component: comboboxChanges related to the combobox component.
    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