Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fix-scrollable-vertical-drag.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@storefront-ui/shared': patch
---

**[FIXED]** `SfScrollable` / `useScrollable` with `direction="vertical"` and `drag={{ containerWidth: true }}` now scrolls by one container height when dragged. The vertical branch wrote to `scrollLeft` (starting from the horizontal drag origin) instead of `scrollTop`, so a vertical drag never moved the content.
4 changes: 2 additions & 2 deletions packages/sfui/shared/scrollable/scrollable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,8 @@ export default class Scrollable {
if (scrollByOneWidth) {
// if user just touched not dragged at least 10px - do nothing
if (Math.abs(this.dragDistance) < 10) return;
container.scrollLeft =
this.dragScrollLeft -
container.scrollTop =
this.dragScrollTop -
(this.dragDistance < 0 ? container.clientHeight - buffor : -container.clientHeight + buffor);
} else {
container.scrollTop = this.dragScrollTop - scrolling;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { BasePage } from '../../utils/BasePage';

const mouseOptions = { eventConstructor: 'MouseEvent', force: true } as const;

export default class SfScrollablePageObject extends BasePage {
// listeners are attached after mount; the next button turns enabled once the first scroll state is computed
isReady() {
this.container.parent().find('button[aria-label="Next"]').should('not.be.disabled');
return this;
}

dragVertically(fromY: number, toY: number) {
this.container
.trigger('mousedown', 50, fromY, mouseOptions)
.trigger('mousemove', 50, toY, mouseOptions)
.trigger('mouseup', 50, toY, mouseOptions);
return this;
}

hasScrollTopGreaterThan(value: number) {
this.container.should(($container) => {
expect($container[0].scrollTop).to.be.greaterThan(value);
});
return this;
}

hasScrollLeft(value: number) {
this.container.should(($container) => {
expect($container[0].scrollLeft).to.equal(value);
});
return this;
}
}
57 changes: 57 additions & 0 deletions packages/tests/components/SfScrollable/SfScrollable.cy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React from 'react';
import { h } from 'vue';
import { mount, useComponent } from '../../utils/mount';
import SfScrollablePageObject from './SfScrollable.PageObject';

const { vue: SfScrollableVue, react: SfScrollableReact } = useComponent('SfScrollable');

describe('SfScrollable', () => {
const page = () => new SfScrollablePageObject('scrollable');
// inline so the scroll box does not depend on the test app's stylesheet
const containerStyle = { height: '100px', width: '100px', overflowY: 'auto', scrollBehavior: 'auto' } as const;
const itemStyle = { height: '80px', flexShrink: 0, pointerEvents: 'none' } as const;
const items = [...Array(10).keys()];

const initializeComponent = ({ drag }: { drag: { containerWidth?: boolean; sensitivity?: number } | boolean }) => {
return mount({
vue: {
component: SfScrollableVue,
props: {
direction: 'vertical',
reduceMotion: true,
drag,
},
attrs: {
'data-testid': 'scrollable',
style: containerStyle,
},
slots: {
default: () => items.map((item) => h('div', { key: item, style: itemStyle }, `${item}`)),
},
},
react: (
<SfScrollableReact
direction="vertical"
reduceMotion
drag={drag}
data-testid="scrollable"
style={containerStyle}
>
{items.map((item) => (
<div key={item} style={itemStyle}>
{item}
</div>
))}
</SfScrollableReact>
),
});
};

describe('when direction is vertical and drag scrolls by one container height', () => {
it('should scroll down when the user drags up', () => {
initializeComponent({ drag: { containerWidth: true } });

page().isReady().dragVertically(90, 10).hasScrollTopGreaterThan(0).hasScrollLeft(0);
});
});
});