Skip to content

Commit

Permalink
scrollbar transition improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
KingSora committed May 24, 2024
1 parent 2cf0233 commit c36c9a6
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 34 deletions.
16 changes: 8 additions & 8 deletions packages/overlayscrollbars/src/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,11 @@ const createEnvironment = (): Env => {
triggerEvent('r', []);
});

if (isFunction(wnd.matchMedia)) {
if (
isFunction(wnd.matchMedia) &&
!nativeScrollbarsHiding &&
(!nativeScrollbarsOverlaid.x || !nativeScrollbarsOverlaid.y)
) {
const addZoomListener = (onZoom: () => void) => {
const media = wnd.matchMedia(`(resolution: ${wnd.devicePixelRatio}dppx)`);
addEventListener(
Expand All @@ -169,14 +173,10 @@ const createEnvironment = (): Env => {
);
};
addZoomListener(() => {
let updatedNativeScrollbarSize, nativeScrollbarSizeChanged;

// updating scrollbar size is only needed if there is no `nativeScrollbarsHiding` support and the native scrollbars are not overlaid
if (!nativeScrollbarsHiding && (!nativeScrollbarsOverlaid.x || !nativeScrollbarsOverlaid.y)) {
[updatedNativeScrollbarSize, nativeScrollbarSizeChanged] = updateNativeScrollbarSizeCache();
assignDeep(env._nativeScrollbarsSize, updatedNativeScrollbarSize); // keep the object and just re-assign!
}
const [updatedNativeScrollbarSize, nativeScrollbarSizeChanged] =
updateNativeScrollbarSizeCache();

assignDeep(env._nativeScrollbarsSize, updatedNativeScrollbarSize); // keep the object and just re-assign!
triggerEvent('r', [nativeScrollbarSizeChanged]);
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,11 +316,7 @@ export const createObserversSetup = (
const destroyHostMutationObserver = constructHostMutationObserver();
const removeResizeListener = env._addResizeListener((_scrollbarSizeChanged) => {
if (_scrollbarSizeChanged) {
// only need `contentMutation: true`, `sizeChanged: true` is updated by the size observer
onObserversUpdatedDebounced({
_scrollbarSizeChanged,
_contentMutation: true,
});
onObserversUpdatedDebounced({ _scrollbarSizeChanged });
} else {
onWindowResizeDebounced();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,6 @@ export const createScrollbarsSetupEvents = (
const [wheelTimeout, clearWheelTimeout] = selfClearTimeout(333);
const [scrollSnapScrollTransitionTimeout, clearScrollSnapScrollTransitionTimeout] =
selfClearTimeout(444);
const [requestHandleTransitionAnimationFrame, clearHandleTransitionTimeout] =
selfClearTimeout();
const refreshHandleOffsetTransition = bind(
refreshScrollbarStructuresHandleOffset,
[scrollbarStructure],
Expand Down Expand Up @@ -211,8 +209,39 @@ export const createScrollbarsSetupEvents = (
};

let wheelScrollBy = true;
const isAffectingTransition = (event: TransitionEvent) =>
event.propertyName.indexOf(widthHeightKey) > -1;

const addTransitionAnimation = (
target: HTMLElement,
isAffecting?: (event: TransitionEvent) => boolean
) => {
const [requestTransitionAnimationFrame, cancelTransitionAnimationFrame] = selfClearTimeout();
const isTransitionTarget = (event: TransitionEvent) => event.target === target;
const transitionStartAnimation = () => {
const animateHandleOffset = () => {
refreshHandleOffsetTransition();
requestTransitionAnimationFrame(animateHandleOffset);
};
animateHandleOffset();
};
const transitionEndAnimation = () => {
cancelTransitionAnimationFrame();
refreshHandleOffsetTransition();
};

return bind(runEachAndClear, [
cancelTransitionAnimationFrame,
addEventListener(target, 'transitionstart', (event: TransitionEvent) => {
if (isTransitionTarget(event) && (isAffecting ? isAffecting(event) : true)) {
transitionStartAnimation();
}
}),
addEventListener(target, 'transitionend transitioncancel', (event: TransitionEvent) => {
if (isTransitionTarget(event)) {
transitionEndAnimation();
}
}),
]);
};

return bind(runEachAndClear, [
addEventListener(_handle, 'pointermove pointerleave', scrollbarHandlePointerInteraction),
Expand Down Expand Up @@ -261,21 +290,12 @@ export const createScrollbarsSetupEvents = (
{ _passive: false, _capture: true }
),
// when the handle has a size transition, update the handle offset each frame for the time of the transition
addEventListener(_handle, 'transitionstart', (event: TransitionEvent) => {
if (isAffectingTransition(event)) {
const animateHandleOffset = () => {
refreshHandleOffsetTransition();
requestHandleTransitionAnimationFrame(animateHandleOffset);
};
animateHandleOffset();
}
}),
addEventListener(_handle, 'transitionend transitioncancel', (event: TransitionEvent) => {
if (isAffectingTransition(event)) {
clearHandleTransitionTimeout();
refreshHandleOffsetTransition();
}
}),
addTransitionAnimation(
_handle,
(event: TransitionEvent) => event.propertyName.indexOf(widthHeightKey) > -1
),
// when the scrollbar has a size transition, update the handle offset each frame for the time of the transition
addTransitionAnimation(_scrollbar),
// solve problem of interaction causing click events
addEventListener(
_scrollbar,
Expand All @@ -292,7 +312,6 @@ export const createScrollbarsSetupEvents = (
createInteractiveScrollEvents(),
clearWheelTimeout,
clearScrollSnapScrollTransitionTimeout,
clearHandleTransitionTimeout,
]);
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,8 @@ export const createScrollbarsSetup = (
_scrollbarsAddRemoveClass(classNameScrollbarTrackInteractive, clickScroll);
}

// always update scrollbar visibility before scrollbar size
// the scrollbar size is influenced whether both or just one scrollbar is visible (because of the corner element)
if (updateVisibility) {
const xVisible = setScrollbarVisibility(overflow.x, _overflowStyle.x, true);
const yVisible = setScrollbarVisibility(overflow.y, _overflowStyle.y, false);
Expand All @@ -268,6 +270,7 @@ export const createScrollbarsSetup = (
_scrollbarsAddRemoveClass(classNameScrollbarCornerless, !hasCorner);
}

// always update scrollbar sizes after the visibility
if (updateScrollbars) {
// order is matter! length has to be refreshed before offset
_refreshScrollbarsHandleLength();
Expand Down
2 changes: 1 addition & 1 deletion packages/overlayscrollbars/src/styles/scrollbars.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ body > .os-scrollbar {
z-index: 99999;
}
.os-scrollbar-transitionless {
transition: none;
transition: none !important;
}
.os-scrollbar-track {
position: relative;
Expand Down

0 comments on commit c36c9a6

Please sign in to comment.