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"