= {
+ current: null,
+ };
+ render(
+
+
+
+
+ ,
+ );
+
+ const mockedData = setup(ref.current!);
+ expect(mockedData.scrollLeft).toBe(0);
+
+ fireEvent.mouseEnter(screen.getByTestId('horizontal-scroll'));
+
+ const arrowNext = screen.getByTestId('next-scroll-arrow');
+ fireEvent.click(arrowNext);
+ fireEvent.click(arrowNext);
+
+ await waitFor(() => {
+ expect(mockedData.scrollLeft).toBe(-300);
+ });
+
+ fireEvent.mouseEnter(screen.getByTestId('horizontal-scroll'));
+
+ const arrowPrev = screen.getByTestId('prev-scroll-arrow');
+ fireEvent.click(arrowPrev);
+ fireEvent.click(arrowPrev);
+
+ await waitFor(() => {
+ expect(mockedData.scrollLeft).toBe(0);
+ });
+ });
+ });
});
function mockRef(element: HTMLDivElement) {
diff --git a/packages/vkui/src/components/HorizontalScroll/HorizontalScroll.tsx b/packages/vkui/src/components/HorizontalScroll/HorizontalScroll.tsx
index 8bb09f364f..0f188c3061 100644
--- a/packages/vkui/src/components/HorizontalScroll/HorizontalScroll.tsx
+++ b/packages/vkui/src/components/HorizontalScroll/HorizontalScroll.tsx
@@ -132,8 +132,15 @@ function doScroll({
const extremeScrollLeft =
(textDirection === 'ltr' ? 1 : -1) * (initialScrollWidth - scrollElement.offsetWidth);
- let startScrollLeft = roundUpElementScrollLeft(scrollElement);
- let endScrollLeft = getScrollPosition(startScrollLeft);
+ const startScrollLeft = roundUpElementScrollLeft(scrollElement);
+ const remappedStartScrollLeft = startScrollLeft * (textDirection === 'rtl' ? -1 : 1);
+
+ let endScrollLeft = getScrollPosition(remappedStartScrollLeft);
+
+ const diff = endScrollLeft - remappedStartScrollLeft;
+ if (textDirection === 'rtl') {
+ endScrollLeft = startScrollLeft - diff;
+ }
onScrollStart();
@@ -196,11 +203,10 @@ export const HorizontalScroll = ({
contentWrapperClassName,
...restProps
}: HorizontalScrollProps): React.ReactNode => {
- const [canScrollLeft, setCanScrollLeft] = React.useState(false);
- const [canScrollRight, setCanScrollRight] = React.useState(false);
+ const [canScrollStart, setCanScrollStart] = React.useState(false);
+ const [canScrollEnd, setCanScrollEnd] = React.useState(false);
const direction = useConfigDirection();
- const setCanScrollStart = direction === 'ltr' ? setCanScrollLeft : setCanScrollRight;
- const setCanScrollEnd = direction === 'ltr' ? setCanScrollRight : setCanScrollLeft;
+ const isRtl = direction === 'rtl';
const isCustomScrollingRef = React.useRef(false);
@@ -234,13 +240,13 @@ export const HorizontalScroll = ({
[scrollerRef, scrollAnimationDuration, direction, setCanScrollEnd],
);
- const scrollToLeft = React.useCallback(() => {
+ const scrollToStart = React.useCallback(() => {
const getScrollPosition =
getScrollToLeft ?? ((i: number) => i - scrollerRef.current!.offsetWidth);
scrollTo(getScrollPosition);
}, [getScrollToLeft, scrollTo, scrollerRef]);
- const scrollToRight = React.useCallback(() => {
+ const scrollToEnd = React.useCallback(() => {
const getScrollPosition =
getScrollToRight ?? ((i: number) => i + scrollerRef.current!.offsetWidth);
scrollTo(getScrollPosition);
@@ -249,14 +255,15 @@ export const HorizontalScroll = ({
const calculateArrowsVisibility = React.useCallback(() => {
if (showArrows && hasPointer && scrollerRef.current && !isCustomScrollingRef.current) {
const scrollElement = scrollerRef.current;
+ const scrollLeft = scrollElement.scrollLeft;
- setCanScrollStart(scrollElement.scrollLeft !== 0);
+ setCanScrollStart(isRtl ? scrollLeft < 0 : scrollLeft > 0);
setCanScrollEnd(
Math.abs(roundUpElementScrollLeft(scrollElement)) + scrollElement.offsetWidth <
scrollElement.scrollWidth,
);
}
- }, [showArrows, hasPointer, scrollerRef, setCanScrollStart, setCanScrollEnd]);
+ }, [showArrows, hasPointer, scrollerRef, isRtl]);
React.useEffect(calculateArrowsVisibility, [calculateArrowsVisibility, children]);
@@ -300,10 +307,11 @@ export const HorizontalScroll = ({
styles.host,
'vkuiInternalHorizontalScroll',
showArrows === 'always' && styles.withConstArrows,
+ isRtl && styles.rtl,
)}
onMouseEnter={calculateArrowsVisibility}
>
- {showArrows && (hasPointer || hasPointer === undefined) && canScrollLeft && (
+ {showArrows && (hasPointer || hasPointer === undefined) && canScrollStart && (
)}
- {showArrows && (hasPointer || hasPointer === undefined) && canScrollRight && (
+ {showArrows && (hasPointer || hasPointer === undefined) && canScrollEnd && (
)}
diff --git a/packages/vkui/src/components/HorizontalScroll/__image_snapshots__/horizontalscroll-viewwidth-mobile-haspointer-false-android-chromium-dark-1-snap.png b/packages/vkui/src/components/HorizontalScroll/__image_snapshots__/horizontalscroll-viewwidth-mobile-haspointer-false-android-chromium-dark-1-snap.png
index d72b3c9de5..419188d37f 100644
--- a/packages/vkui/src/components/HorizontalScroll/__image_snapshots__/horizontalscroll-viewwidth-mobile-haspointer-false-android-chromium-dark-1-snap.png
+++ b/packages/vkui/src/components/HorizontalScroll/__image_snapshots__/horizontalscroll-viewwidth-mobile-haspointer-false-android-chromium-dark-1-snap.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:25ed522e95d972a1932dbb746a09ef48183e8bd90c372183fac5f34786cd1e58
-size 14271
+oid sha256:33666e4bce09a5b3e02ef7a5a3e89c8eff9bf859813dda9a2316892fb76e951c
+size 20701
diff --git a/packages/vkui/src/components/HorizontalScroll/__image_snapshots__/horizontalscroll-viewwidth-mobile-haspointer-false-android-chromium-light-1-snap.png b/packages/vkui/src/components/HorizontalScroll/__image_snapshots__/horizontalscroll-viewwidth-mobile-haspointer-false-android-chromium-light-1-snap.png
index 5e5cae6b8b..1527c8ef08 100644
--- a/packages/vkui/src/components/HorizontalScroll/__image_snapshots__/horizontalscroll-viewwidth-mobile-haspointer-false-android-chromium-light-1-snap.png
+++ b/packages/vkui/src/components/HorizontalScroll/__image_snapshots__/horizontalscroll-viewwidth-mobile-haspointer-false-android-chromium-light-1-snap.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:307ea2ad4b2856b0f74bd896785507197e42c9357cda4db304563b7423e097b1
-size 13377
+oid sha256:82d705249d789d8685aed158615b1b763ec35ad706ec5fa063a5d6298b17d488
+size 19432
diff --git a/packages/vkui/src/components/HorizontalScroll/__image_snapshots__/horizontalscroll-viewwidth-small-tablet-haspointer-true-android-chromium-dark-1-snap.png b/packages/vkui/src/components/HorizontalScroll/__image_snapshots__/horizontalscroll-viewwidth-small-tablet-haspointer-true-android-chromium-dark-1-snap.png
index 29910604fe..372a3fdd45 100644
--- a/packages/vkui/src/components/HorizontalScroll/__image_snapshots__/horizontalscroll-viewwidth-small-tablet-haspointer-true-android-chromium-dark-1-snap.png
+++ b/packages/vkui/src/components/HorizontalScroll/__image_snapshots__/horizontalscroll-viewwidth-small-tablet-haspointer-true-android-chromium-dark-1-snap.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:eaf0b39c4a9b5e3db07ca9e108131cdec5eddb1795891801fbb43203b47b5e6b
-size 42673
+oid sha256:0b6eed74d8789c69a691827afa34e75a319fa5bc7007cbe2fb6b83776818a00c
+size 53264
diff --git a/packages/vkui/src/components/HorizontalScroll/__image_snapshots__/horizontalscroll-viewwidth-small-tablet-haspointer-true-android-chromium-light-1-snap.png b/packages/vkui/src/components/HorizontalScroll/__image_snapshots__/horizontalscroll-viewwidth-small-tablet-haspointer-true-android-chromium-light-1-snap.png
index 97f58af078..42344775b1 100644
--- a/packages/vkui/src/components/HorizontalScroll/__image_snapshots__/horizontalscroll-viewwidth-small-tablet-haspointer-true-android-chromium-light-1-snap.png
+++ b/packages/vkui/src/components/HorizontalScroll/__image_snapshots__/horizontalscroll-viewwidth-small-tablet-haspointer-true-android-chromium-light-1-snap.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:e0c7a3fa2bda7039206ae625fc85da652654d704b31338b4c900fb003733f6a6
-size 41511
+oid sha256:7f5a2a29f78d03508e009921a8438030fb1cf8fee4e49f8453dd8bfab7625fc8
+size 51832