solidjs / solid

A declarative, efficient, and flexible JavaScript library for building user interfaces.
https://solidjs.com
MIT License
32.08k stars 914 forks source link

Support 'passive' option on event listeners #2210

Open goswinr opened 2 months ago

goswinr commented 2 months ago

Describe the bug

Most DOM events are not passive by default, but some are ( wheel, scroll, ..) . see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#passive And it is not consistent among major Browsers. Should Solids JSX support explicit passive options for event listeners ? See how React addressed this issue: https://github.com/facebook/react/issues/6436 and the resolution: https://github.com/facebook/react/pull/19654

Steps to Reproduce the Bug or Issue

see example on SolidJS Playground and below: (update Sep 2024: on chrome the playground doesn't show the bug anymore)

import { render } from "solid-js/web";
import { onMount } from "solid-js";

function Counter() {  
  const wheel = (e:MouseEvent) => {
    e.preventDefault() // only works on not passive events
    e.stopPropagation()  
    console.log("wheel stopped?")
  }

  let div ;
  onMount(() => div.addEventListener("wheel", wheel, {passive:false}) ) // most events are not passive by default but "wheel" is in Chrome

  return (
    <>
    <div oncapture:wheel={wheel} style={{"background-color":"lightgreen","height":"26vh"}} />
    <div ref={div} style={{"background-color":"lightgray"  ,"height":"26vh"}} > In Chrome this gray div is the only div that prevents scrolling</div>
    <div on:wheel={wheel} style={{"background-color":"lightblue","height":"26vh"}} />
    <div onWheel={wheel} style={{"background-color":"crimson"  ,"height":"26vh"}} />
    </>
  );
}

render(() => <Counter />, document.getElementById("app")!);

Expected behavior

Like on:* and oncapture:* There could be a JSX syntax to specify the passive option for events. Maybe onpassive:* and onnotpassive: * or onWheelNotPassive and onScrollNotPassive

ryansolid commented 1 month ago

Great suggestion. How are other frameworks handling it. Love to see some inspiration for this feature.

codenimble commented 1 month ago

+1

chaosprint commented 1 month ago

This is very important. Otherwise, do we have to use addEventListener temporarily?

goswinr commented 1 month ago

@chaosprint yes, currently you have to use el.addEventListener("wheel", handler, {passive:false}) so that preventDefault() works in the handler.

titoBouzout commented 4 weeks ago

Opened this PR to solve this capture/once/passive/signal
https://github.com/ryansolid/dom-expressions/pull/341