Skip to content

fix(video-player): seek when SeekSlider parts are drawn with render - #600

Draft
kianbazza wants to merge 1 commit into
canaryfrom
fix-seek-slider-render-props-seek
Draft

kianbazza wants to merge 1 commit into
canaryfrom
fix-seek-slider-render-props-seek

Conversation

@kianbazza

@kianbazza kianbazza commented Oct 24, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

With render on SeekSliderThumb, the seek slider ignored clicks and drags. The thumb's render branch replaced Base UI's thumb ref with the forwarded ref, so the slider never registered the thumb. On a press, Base UI looks for the thumb closest to the pointer, finds none, and drops the press:

 SeekSliderThumb render={(thumb) => <div {...thumb} />}
-  render({ ...baseProps, ref: forwardedRef, … })   // drops Base UI's [forwardedRef, listItemRef, thumbRef]
+  <Slider.Thumb ref={forwardedRef} render={(baseProps) => render({ ...baseProps, … })}>

 Slider.Control onPointerDown
   startPressing
-    thumbRefs is empty → no pressed thumb → getFingerState returns null → no value change
+    closest thumb found → value set from the pointer

Keyboard seeking still worked, because the thumb's hidden input handles arrow keys itself.

SeekSliderTrack and SeekSliderProgress had the same ref override. It was harmless there, because Base UI's track and indicator only take the forwarded ref, but they now use the same shape as the thumb.

Writing the test showed a second problem in the same branches. SeekSlider, SeekSliderTrack, SeekSliderProgress, SeekSliderThumb and VolumeSlider dropped their JSX children when given render, so <SeekSlider render={…}><SeekSliderControl>…</SeekSliderControl></SeekSlider> drew an empty slider. They now pass children through to Base UI, which also places the thumb's children next to its hidden input.

The ref in SeekSliderTrack.RenderProps, SeekSliderProgress.RenderProps and SeekSliderThumb.RenderProps is now optional. That matches what Base UI passes, since it leaves ref unset during server rendering.

Evidence

New browser test, seek-slider.browser.test.tsx. It draws the slider three ways: without render; with every part's children inside its render callback (the shape that failed in Ship); and with render plus JSX children. For each, it presses at 75%, drags from 20% to 50%, and presses ArrowRight.

  • Before: 7 of 11 fail. Click and drag fail for both render shapes. Every check fails for render plus JSX children, because the parts never mount. Ref forwarding and the VolumeSlider click also fail.
    SeekSlider with nested render props > seeks to the pressed point
    AssertionError: expected undefined to be close to 75
    
  • After: 12 of 12 pass, including a new check that Thumb and Progress keep their JSX children. bun run test for @bazza-ui/react passes in full: 66 files, 1541 tests. type-check and check are clean.

Merge Danger

Door: two-way

Blast Radius: small

The change only touches the render-prop branches of the seek and volume sliders. Their default branches are unchanged. One case changes on purpose: a consumer who passed both render and JSX children used to get the children dropped, and now sees them rendered.

@vercel

vercel Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
ui-canary Ready Ready Preview Oct 24, 2026 8:29pm UTC

Request Review

This branch was successfully deployed

1 active deployment
Preview – ui-canary — e2095403 Deployed Oct 24, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant