diff --git a/invokeai/frontend/web/src/common/components/OverlayScrollbars/ScrollableContent.tsx b/invokeai/frontend/web/src/common/components/OverlayScrollbars/ScrollableContent.tsx index c42fb485202..370c85959e0 100644 --- a/invokeai/frontend/web/src/common/components/OverlayScrollbars/ScrollableContent.tsx +++ b/invokeai/frontend/web/src/common/components/OverlayScrollbars/ScrollableContent.tsx @@ -1,9 +1,13 @@ +import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine'; +import { autoScrollForElements } from '@atlaskit/pragmatic-drag-and-drop-auto-scroll/element'; +import { autoScrollForExternal } from '@atlaskit/pragmatic-drag-and-drop-auto-scroll/external'; import type { ChakraProps } from '@invoke-ai/ui-library'; import { Box, Flex } from '@invoke-ai/ui-library'; import { getOverlayScrollbarsParams } from 'common/components/OverlayScrollbars/constants'; +import type { OverlayScrollbarsComponentRef } from 'overlayscrollbars-react'; import { OverlayScrollbarsComponent } from 'overlayscrollbars-react'; import type { CSSProperties, PropsWithChildren } from 'react'; -import { memo, useMemo } from 'react'; +import { memo, useEffect, useMemo, useState } from 'react'; type Props = PropsWithChildren & { maxHeight?: ChakraProps['maxHeight']; @@ -11,17 +15,38 @@ type Props = PropsWithChildren & { overflowY?: 'hidden' | 'scroll'; }; -const styles: CSSProperties = { height: '100%', width: '100%' }; +const styles: CSSProperties = { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }; const ScrollableContent = ({ children, maxHeight, overflowX = 'hidden', overflowY = 'scroll' }: Props) => { const overlayscrollbarsOptions = useMemo( () => getOverlayScrollbarsParams(overflowX, overflowY).options, [overflowX, overflowY] ); + const [os, osRef] = useState(null); + useEffect(() => { + const osInstance = os?.osInstance(); + + if (!osInstance) { + return; + } + + const element = osInstance.elements().viewport; + + // `pragmatic-drag-and-drop-auto-scroll` requires the element to have `overflow-y: scroll` or `overflow-y: auto` + // else it logs an ugly warning. In our case, using a custom scrollbar library, it will be 'hidden' by default. + // To prevent the erroneous warning, we temporarily set the overflow-y to 'scroll' and then revert it back. + const overflowY = element.style.overflowY; // starts 'hidden' + element.style.setProperty('overflow-y', 'scroll', 'important'); + const cleanup = combine(autoScrollForElements({ element }), autoScrollForExternal({ element })); + element.style.setProperty('overflow-y', overflowY); + + return cleanup; + }, [os]); + return ( - + {children} diff --git a/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/BoardsListWrapper.tsx b/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/BoardsListWrapper.tsx index 650f492e8cd..ca944e8981e 100644 --- a/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/BoardsListWrapper.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/BoardsListWrapper.tsx @@ -21,11 +21,23 @@ const BoardsListWrapper = () => { const allowPrivateBoards = useAppSelector(selectAllowPrivateBoards); const [os, osRef] = useState(null); useEffect(() => { - const element = os?.osInstance()?.elements().viewport; - if (!element) { + const osInstance = os?.osInstance(); + + if (!osInstance) { return; } - return combine(autoScrollForElements({ element }), autoScrollForExternal({ element })); + + const element = osInstance.elements().viewport; + + // `pragmatic-drag-and-drop-auto-scroll` requires the element to have `overflow-y: scroll` or `overflow-y: auto` + // else it logs an ugly warning. In our case, using a custom scrollbar library, it will be 'hidden' by default. + // To prevent the erroneous warning, we temporarily set the overflow-y to 'scroll' and then revert it back. + const overflowY = element.style.overflowY; // starts 'hidden' + element.style.setProperty('overflow-y', 'scroll', 'important'); + const cleanup = combine(autoScrollForElements({ element }), autoScrollForExternal({ element })); + element.style.setProperty('overflow-y', overflowY); + + return cleanup; }, [os]); return ( diff --git a/invokeai/frontend/web/src/features/nodes/components/sidePanel/workflow/WorkflowLinearTab.tsx b/invokeai/frontend/web/src/features/nodes/components/sidePanel/workflow/WorkflowLinearTab.tsx index 81e28a232a3..2547b9a7749 100644 --- a/invokeai/frontend/web/src/features/nodes/components/sidePanel/workflow/WorkflowLinearTab.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/sidePanel/workflow/WorkflowLinearTab.tsx @@ -25,7 +25,7 @@ const WorkflowLinearTab = () => { return ( - +