Skip to content

Commit edd51d5

Browse files
authored
fix(toolbar): horizontal wheel scrolling support (#1201)
1 parent 2f54f6f commit edd51d5

File tree

3 files changed

+52
-2
lines changed

3 files changed

+52
-2
lines changed

src/features/toolbar/components/ToolbarContent/ToolbarContent.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
1-
import { Fragment } from 'react';
1+
import { Fragment, useRef } from 'react';
22
import { ChevronDown16 } from '@konturio/default-icons';
33
import { useToolbarContent } from '~features/toolbar/hooks/use-toolbar-content';
4+
import { useWheelHorizontalScroll } from '~utils/hooks/useWheelHorizontalScroll';
45
import { ToolbarControl } from '../ToolbarControl/ToolbarControl';
56
import { ToolbarButton } from '../ToolbarButton/ToolbarButton';
67
import s from './ToolbarContent.module.css';
78

89
export const ToolbarContent = () => {
910
const toolbarContent = useToolbarContent();
11+
const scrollRef = useRef<HTMLDivElement>(null);
12+
useWheelHorizontalScroll(scrollRef);
1013

1114
return (
12-
<div className={s.toolbarContent}>
15+
<div className={s.toolbarContent} ref={scrollRef}>
1316
{toolbarContent.map(({ sectionName, buttons }, index) => (
1417
<Fragment key={sectionName}>
1518
{index > 0 && <div className={s.sectionDivider} />}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/**
2+
* @vitest-environment happy-dom
3+
*/
4+
import React, { useRef } from 'react';
5+
import { render } from '@testing-library/react';
6+
import { test, expect } from 'vitest';
7+
import { useWheelHorizontalScroll } from './useWheelHorizontalScroll';
8+
9+
function Demo() {
10+
const ref = useRef<HTMLDivElement>(null);
11+
useWheelHorizontalScroll(ref);
12+
return (
13+
<div ref={ref} data-testid="scroll" style={{ overflowX: 'auto', width: '100px' }}>
14+
<div style={{ width: '300px' }}>content</div>
15+
</div>
16+
);
17+
}
18+
19+
test('scrollLeft changes on vertical wheel events', () => {
20+
const { getByTestId } = render(<Demo />);
21+
const scroll = getByTestId('scroll') as HTMLDivElement;
22+
23+
Object.defineProperty(scroll, 'scrollWidth', { value: 300, configurable: true });
24+
Object.defineProperty(scroll, 'clientWidth', { value: 100, configurable: true });
25+
26+
scroll.dispatchEvent(new WheelEvent('wheel', { deltaY: 50, bubbles: true }));
27+
28+
expect(
29+
scroll.scrollLeft > 0,
30+
`scrollLeft should change after wheel event, got ${scroll.scrollLeft}`,
31+
).toBe(true);
32+
});
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { useEffect } from 'react';
2+
3+
export function useWheelHorizontalScroll(ref: React.RefObject<HTMLElement>) {
4+
useEffect(() => {
5+
const node = ref.current;
6+
if (!node) return;
7+
const onWheel = (e: WheelEvent) => {
8+
if (node.scrollWidth <= node.clientWidth || e.deltaY === 0) return;
9+
e.preventDefault();
10+
node.scrollLeft += e.deltaY;
11+
};
12+
node.addEventListener('wheel', onWheel, { passive: false });
13+
return () => node.removeEventListener('wheel', onWheel);
14+
}, [ref]);
15+
}

0 commit comments

Comments
 (0)