Skip to content

Tooltip clipped by overflow/scroll ancestors instead of viewport. #278

Description

Describe the bug

<Tooltip>'s default Floating UI boundary is its nearest scroll/overflow ancestor, not the viewport. Tooltips inside scrolling containers (tables, dialogs, sidebars, any element with overflow: auto/scroll/hidden) get visually clipped when they would otherwise extend past the container's edge — even when there is plenty of room in the viewport itself.

The fix on the consumer side is to manually pass positioning={{ boundary: () => document.body }} at every call site, but that's easy to forget and produces silent visual regressions when missed.

To Reproduce

  1. Render any container with overflow: auto or overflow: hidden that's smaller than the tooltip would occupy when fully visible.
  2. Place a <Tooltip> inside it whose trigger is near the container's edge.
  3. Hover the trigger.

The tooltip is clipped at the container's edge instead of overflowing into the viewport.

Reproduction

import { Tooltip } from '@qualcomm-ui/react/tooltip'

export function TooltipClippingRepro() {
  return (
    <div style={{ width: 200, height: 80, overflow: 'auto', border: '1px solid #ccc', padding: 8 }}>
      <Tooltip trigger={<button type="button">Hover me</button>}>
        This tooltip's content gets clipped at the edge of the surrounding scroll container, even
        though the viewport has plenty of space.
      </Tooltip>
    </div>
  )
}

Compare with the same <Tooltip> rendered with the workaround:

<Tooltip
  positioning={{ boundary: () => document.body }}
  trigger={<button type="button">Hover me</button>}
></Tooltip>

The workaround version renders correctly — proof the fix is just a default change.

Expected behavior

The tooltip should be bounded by the viewport by default, not by the nearest scrolling ancestor. This matches how Tooltips work in MUI, Radix, Mantine, Chakra, and Floating UI's own examples — and matches what the component is conceptually for (an overlay that escapes its container).

If clip-to-ancestor is a desired alternative for some cases, expose it as a prop rather than the default.

Environment

  • OS: macOS 15
  • Browser: Chrome 132
  • Version: @qualcomm-ui/react@1.22.0, @qualcomm-ui/qds-core@1.28.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    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