diff --git a/.changeset/tonic-ui-938.md b/.changeset/tonic-ui-938.md
new file mode 100644
index 0000000000..4f263da92c
--- /dev/null
+++ b/.changeset/tonic-ui-938.md
@@ -0,0 +1,5 @@
+---
+"@tonic-ui/react": minor
+---
+
+feat(`react/scrollbar`): add `scrollViewProps` to enable passing custom props to the `ScrollView` component
diff --git a/packages/react-docs/package.json b/packages/react-docs/package.json
index bf736d1d61..baac9dff9a 100644
--- a/packages/react-docs/package.json
+++ b/packages/react-docs/package.json
@@ -78,6 +78,7 @@
"react-movable": "^3.0.4",
"react-table": "^7.8.0",
"react-virtualized-auto-sizer": "^1.0.15",
+ "react-virtuoso": "^4.12.0",
"rehype-autolink-headings": "^6.1.1",
"rehype-slug": "^5.1.0",
"remark-emoji": "^4.0.0",
diff --git a/packages/react-docs/pages/components/scrollbar/faq-react-virtuoso.js b/packages/react-docs/pages/components/scrollbar/faq-react-virtuoso.js
new file mode 100644
index 0000000000..c993592385
--- /dev/null
+++ b/packages/react-docs/pages/components/scrollbar/faq-react-virtuoso.js
@@ -0,0 +1,38 @@
+import { Box, Scrollbar } from '@tonic-ui/react';
+import { Virtuoso } from 'react-virtuoso';
+import React, { forwardRef } from 'react';
+
+const CustomScrollbar = forwardRef((inProps, ref) => {
+ const { children, ...props } = inProps;
+
+ return (
+
+ {children}
+
+ );
+});
+
+CustomScrollbar.displayName = 'CustomScrollbar';
+
+const App = () => {
+ return (
+ (
+ Item {index}
+ )}
+ />
+ );
+};
+
+export default App;
diff --git a/packages/react-docs/pages/components/scrollbar/index.page.mdx b/packages/react-docs/pages/components/scrollbar/index.page.mdx
index f502f01cff..e2b4cccd39 100644
--- a/packages/react-docs/pages/components/scrollbar/index.page.mdx
+++ b/packages/react-docs/pages/components/scrollbar/index.page.mdx
@@ -80,6 +80,47 @@ To see this in action, simply scroll through the content and click the toggle bu
{render('./faq-scroll-position')}
+### How to integrate React Virtuoso with a custom scrollbar?
+
+Check out the demo below to see how you can integrate React Virtuoso with a custom scrollbar:
+
+{render('./faq-react-virtuoso')}
+
+To achieve this, you'll need to create a `CustomScrollbar` component and pass it as the `Scroller` for the `Virtuoso` component.
+
+```jsx disabled
+ (
+ Item {index}
+ )}
+/>
+```
+
+In the `CustomScrollbar` component, pass `props` and `ref` to `scrollViewProps` and `scrollViewRef`, respectively. This ensures that the props coming from React Virtuoso are passed down correctly, allowing its scrolling behavior to integrate seamlessly into the `Scrollbar`.
+
+```jsx disabled
+const CustomScrollbar = forwardRef((inProps, ref) => {
+ const { children, ...props } = inProps;
+
+ return (
+
+ {children}
+
+ );
+});
+```
+
## Props
### Scrollbar
@@ -102,4 +143,5 @@ To see this in action, simply scroll through the content and click the toggle bu
| overflowY | string | | The vertical overflow of the scrollable content. One of: 'auto', 'scroll', 'hidden'. |
| scrollLeft | number | 0 | The horizontal scroll position of the scrollable content. |
| scrollTop | number | 0 | The vertical scroll position of the scrollable content. |
+| scrollViewProps | object | | Additional props to be applied to the `ScrollView` component. |
| scrollViewRef | RefObject | | A `ref` to the `ScrollView` component. |
diff --git a/packages/react/src/scrollbar/Scrollbar.js b/packages/react/src/scrollbar/Scrollbar.js
index eba9bd75f7..90085140c0 100644
--- a/packages/react/src/scrollbar/Scrollbar.js
+++ b/packages/react/src/scrollbar/Scrollbar.js
@@ -1,4 +1,5 @@
import { useHydrated, useMergeRefs } from '@tonic-ui/react-hooks';
+import { callEventHandlers } from '@tonic-ui/utils';
import { ensurePositiveFiniteNumber } from 'ensure-type';
import React, { forwardRef, useCallback, useEffect, useState, useRef } from 'react';
import { Box } from '../box';
@@ -37,6 +38,7 @@ const Scrollbar = forwardRef((inProps, ref) => {
overflowY: overflowYProp,
scrollLeft: scrollLeftProp,
scrollTop: scrollTopProp,
+ scrollViewProps: scrollViewPropsProp,
scrollViewRef: scrollViewRefProp,
...rest
} = useDefaultProps({ props: inProps, name: 'Scrollbar' });
@@ -546,12 +548,13 @@ const Scrollbar = forwardRef((inProps, ref) => {
const getScrollViewProps = () => {
return {
+ children,
...scrollViewStyle,
+ ...scrollViewPropsProp,
ref: combinedScrollViewRef,
- onScroll: handleScrollViewScroll,
- onMouseEnter: handleScrollViewMouseEnter,
- onMouseLeave: handleScrollViewMouseLeave,
- children,
+ onScroll: callEventHandlers(scrollViewPropsProp?.onScroll, handleScrollViewScroll),
+ onMouseEnter: callEventHandlers(scrollViewPropsProp?.onMouseEnter, handleScrollViewMouseEnter),
+ onMouseLeave: callEventHandlers(scrollViewPropsProp?.onMouseLeave, handleScrollViewMouseLeave),
};
};
diff --git a/yarn.lock b/yarn.lock
index 6e28f98db3..bca5313e92 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4395,6 +4395,7 @@ __metadata:
react-movable: ^3.0.4
react-table: ^7.8.0
react-virtualized-auto-sizer: ^1.0.15
+ react-virtuoso: ^4.12.0
rehype-autolink-headings: ^6.1.1
rehype-slug: ^5.1.0
remark-emoji: ^4.0.0
@@ -14872,6 +14873,16 @@ __metadata:
languageName: node
linkType: hard
+"react-virtuoso@npm:^4.12.0":
+ version: 4.12.0
+ resolution: "react-virtuoso@npm:4.12.0"
+ peerDependencies:
+ react: ">=16 || >=17 || >= 18"
+ react-dom: ">=16 || >=17 || >= 18"
+ checksum: 23e802f3e4c58b94f70179fd6f3768ebc2e28c46bbf27f8d48f94627f27ae84111e6291ac817bab91302cabc376db67b8aa99f9cd674941448cc7752d6c9ae76
+ languageName: node
+ linkType: hard
+
"react@npm:^16.14.0 || ^17 || ^18, react@npm:latest":
version: 18.2.0
resolution: "react@npm:18.2.0"