Skip to content

Implement useMove, use it in Slider & SplitView #1106

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Oct 6, 2020
Merged

Implement useMove, use it in Slider & SplitView #1106

merged 12 commits into from
Oct 6, 2020

Conversation

mischnic
Copy link
Contributor

@mischnic mischnic commented Sep 29, 2020

Depends on #1083

Closes #1063, Closes #1018
Closes #1069 (useDrag1D is now unused, I've includes the tests in this PR)

@adobe-bot
Copy link

Build successful! 🎉

@adobe-bot
Copy link

Build successful! 🎉

@adobe-bot
Copy link

Build successful! 🎉


if (typeof PointerEvent === 'undefined') {
let onMouseMove = (e: MouseEvent) => {
move('mouse', e.pageX - state.current.previousPosition.pageX, e.pageY - state.current.previousPosition.pageY);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you may need to ignore emulate mouse events on touch devices here. Haven't tested but my guess is that onMouseMove will be fired after onTouchMove and potentially in other cases. You can set a flag in touch events and ignore the following mouse events like we do in usePress.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd also add a check for e.button === 0 to only support dragging with the left mouse button as well. Same in pointer events below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you may need to ignore emulate mouse events on touch devices here.

Works on Chrome Android, but maybe for iOS?

})
onMouseDown(e: React.MouseEvent<HTMLElement>) { onDownTrack(e, e.clientX); },
onPointerDown(e: React.PointerEvent<HTMLElement>) { onDownTrack(e, e.clientX); },
onTouchStart(e: React.TouchEvent<HTMLElement>) { onDownTrack(e, e.touches[0].clientX); }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this cause onDownTrack to be called more than once on touch devices due to emulated mouse events/support for both touch and pointer events? Should we use usePress here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to use usePress but client/page X/Y aren't passed onto the handlers.

@@ -105,20 +110,22 @@ export function useSliderState(props: Omit<SliderProps, 'direction'>): SliderSta

// Round value to multiple of step, clamp value between min and max
value = clamp(getRoundedValue(value), thisMin, thisMax);
setValues(values => replaceIndex(values, index, value));
valuesRef.current = replaceIndex(valuesRef.current, index, value);
setValues(valuesRef.current);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What wasn't working here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test fails when changing it back:

 FAIL   component and hooks  packages/@react-aria/slider/test/useSliderThumb.test.js
  ● useSliderThumb › interactions on thumbs, where track contains thumbs › using KeyEvents › can be moved with keys

    expect(jest.fn()).toHaveBeenLastCalledWith(...expected)

    - Expected
    + Received

      Array [
    -   11,
    +   10,
      ],

    Number of calls: 1

      358 |         expect(onChangeSpy).toHaveBeenLastCalledWith([11]);
      359 |         expect(onChangeSpy).toHaveBeenCalledTimes(1);
    > 360 |         expect(onChangeEndSpy).toHaveBeenLastCalledWith([11]);
          |                                ^
      361 |         expect(onChangeEndSpy).toHaveBeenCalledTimes(1);
      362 |         expect(stateRef.current.values).toEqual([11]);
      363 |       });

      at Object.toHaveBeenLastCalledWith (packages/@react-aria/slider/test/useSliderThumb.test.js:360:32)

@mischnic mischnic force-pushed the useMove branch 2 times, most recently from 6ffe7f8 to a951c0c Compare October 2, 2020 09:45
@adobe-bot

This comment has been minimized.

@mischnic
Copy link
Contributor Author

mischnic commented Oct 2, 2020

Most of the issues and TODO comments went away automatically after adding preventDefault() and using the touch/pointer id. There is now no global state at all anymore (that currentTarget).

Now multitouch on sliders works, I added two stories 🎉

@adobe-bot
Copy link

Build successful! 🎉

@adobe-bot
Copy link

Build successful! 🎉

@adobe-bot
Copy link

Build successful! 🎉

devongovett
devongovett previously approved these changes Oct 3, 2020
Copy link
Member

@devongovett devongovett left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multi touch looking good!

@adobe-bot
Copy link

Build successful! 🎉

Base automatically changed from mischnic/slider to main October 6, 2020 01:08
@devongovett devongovett dismissed their stale review October 6, 2020 01:08

The base branch was changed.

@adobe-bot
Copy link

Build successful! 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants