Skip to content

Make overlay scrollbar thumbs draggable, with hover/active styling#462

Closed
UMCEKO wants to merge 3 commits into
DioxusLabs:mainfrom
UMCEKO:pr/scrollbar-drag
Closed

Make overlay scrollbar thumbs draggable, with hover/active styling#462
UMCEKO wants to merge 3 commits into
DioxusLabs:mainfrom
UMCEKO:pr/scrollbar-drag

Conversation

@UMCEKO

@UMCEKO UMCEKO commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Stacked on #461 (contains its commit; will rebase once it lands).

Makes the overlay scrollbar thumbs from #461 interactive:

  • Thumb geometry moves from blitz-paint into a shared helper on Node (scrollbar_thumb / wants_scrollbar / scrollbar_drag_ratio) so painting and hit testing cannot drift; blitz-paint consumes it.
  • Pointer handling gains a DragMode::ScrollbarDrag state: on pointerdown the layout ancestor chain of the hit node is walked for a scroll container whose thumb contains the pointer (the hit test returns the content under the overlay thumb; the helper is shared with hover tracking). While dragging, pointer movement maps thumb px to content px via the track ratio and scrolls through the existing clamped scroll_by path. Scrollbar drags are not dispatched to the page, and the existing DragMode handling suppresses the synthetic click on release.
  • The document tracks which thumb the pointer is over (hovered_scrollbar, repainting on change), and the painter renders three thumb states: normal, hovered, dragged — a dragged thumb also stays visible if the pointer leaves the container mid-drag.

Tests in packages/blitz-html/tests/scrollbar_drag.rs drive the EventDriver with synthetic pointer events: thumb drags scroll proportionally and clamp at the track end; content drags don't scroll; hover and drag visibly restyle the thumb.

UMCEKO added 3 commits June 13, 2026 01:47
…ree order

Two paint-order fixes in flush_styles_to_layout's paint_children sort:

1. position_to_order put relative/sticky at the in-flow level (0) and
   absolute/fixed above it (2), so an earlier abspos sibling painted above
   a later relative sibling. Per CSS 2.1 Appendix E step 8 all positioned
   descendants with z-index: auto share one paint level and paint in tree
   order among themselves, above in-flow content. The hero-banner pattern
   (abspos inset-0 image layer + relative content overlay) rendered only
   the image.

2. Flex/grid items ignored position entirely (the sort key was just
   `order`), and z-index was only honored for non-static children — but
   z-index applies to static flex/grid items too (css-flexbox-1
   "painting", css-grid-1 "z-order"). The sort key is now (paint level,
   order-modified position) and static flex/grid items with z-index are
   hoisted into the stacking context.

Pixel-level tests in packages/blitz-html/tests/paint_order.rs (render via
anyrender_vello_cpu, assert center pixel).

WPT css-grid + css-flexbox: 0 regressions, new passes:
flexbox-items-as-stacking-contexts-002 (its REFERENCE page depends on
fix 1; it previously passed because both pages rendered identically
wrong), flex-item-z-ordering-001/002, grid-z-axis-ordering-001/002/003,
positioned-grid-items-020/021, positioned-grid-items-negative-indices-003.
blitz previously never painted scrollbars: an overflow: auto/scroll
container gave no visual indication that it scrolls or where within the
content the viewport sits.

Draw an overlay thumb (no reserved gutter, so no layout change) per
overflowing axis: always for overflow: scroll, only when the content
overflows for overflow: auto, never for hidden/clip (programmatic-only
scrolling). Geometry derives from Layout::scroll_width/scroll_height and
node.scroll_offset; the thumb is drawn unscrolled, above the clipped
content, inside the opacity/filter layer.

Like other overlay scrollbar UIs (macOS, Firefox on Linux), thumbs only
appear while the scroll container is hovered or scrolled away from the
origin. Beyond matching platform conventions this keeps thumbs out of
static reftest screenshots: an always-visible variant regressed 10 WPT
overflow reftests whose reference pages cannot scroll; the hover/scroll
rule regresses none.

Pixel-level tests in packages/blitz-html/tests/scrollbars.rs.

Not yet implemented: thumb hit-testing/dragging, css-scrollbars-1
styling (scrollbar-width/scrollbar-color), and show/hide fade
animations.
Thumb geometry moves from blitz-paint into a shared helper on Node
(scrollbar_thumb / wants_scrollbar / scrollbar_drag_ratio) so painting
and hit testing cannot drift; blitz-paint now consumes it.

Pointer handling gains a DragMode::ScrollbarDrag state: on pointerdown
the layout ancestor chain of the hit node is walked for a scroll
container whose thumb contains the pointer (the hit test returns the
content under the overlay thumb; helper shared with hover tracking).
While dragging, pointer movement maps thumb px to content px via the
track ratio and scrolls through the existing clamped scroll_by path
(negated: scroll_by uses wheel-delta semantics). Scrollbar drags are not
dispatched to the page, and the existing DragMode handling suppresses
the synthetic click on release.

The document also tracks which thumb the pointer is over
(hovered_scrollbar, repainting on change), and the painter renders three
thumb states: normal, hovered, and dragged — a dragged thumb also stays
visible if the pointer leaves the container mid-drag.

Tests in packages/blitz-html/tests/scrollbar_drag.rs drive the
EventDriver with synthetic pointer events: thumb drags scroll
proportionally and clamp at the track end; content drags don't scroll;
hover and drag visibly restyle the thumb.
@UMCEKO

UMCEKO commented Jun 13, 2026

Copy link
Copy Markdown
Contributor Author

Folded into #461 — painting and dragging are one feature; keeping them as two commits in a single PR instead of a 3-deep stack.

@UMCEKO UMCEKO closed this Jun 13, 2026
@UMCEKO UMCEKO deleted the pr/scrollbar-drag branch June 13, 2026 00:24
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