Skip to content

Commit 2854210

Browse files
fix(ui): dnd autoscroll on elements w/ custom scrollbar
Have to do a bit of fanagling to get it to work and get `pragmatic-drag-and-drop` to not complain.
1 parent 5545b98 commit 2854210

File tree

3 files changed

+44
-7
lines changed

3 files changed

+44
-7
lines changed

invokeai/frontend/web/src/common/components/OverlayScrollbars/ScrollableContent.tsx

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,52 @@
1+
import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';
2+
import { autoScrollForElements } from '@atlaskit/pragmatic-drag-and-drop-auto-scroll/element';
3+
import { autoScrollForExternal } from '@atlaskit/pragmatic-drag-and-drop-auto-scroll/external';
14
import type { ChakraProps } from '@invoke-ai/ui-library';
25
import { Box, Flex } from '@invoke-ai/ui-library';
36
import { getOverlayScrollbarsParams } from 'common/components/OverlayScrollbars/constants';
7+
import type { OverlayScrollbarsComponentRef } from 'overlayscrollbars-react';
48
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
59
import type { CSSProperties, PropsWithChildren } from 'react';
6-
import { memo, useMemo } from 'react';
10+
import { memo, useEffect, useMemo, useState } from 'react';
711

812
type Props = PropsWithChildren & {
913
maxHeight?: ChakraProps['maxHeight'];
1014
overflowX?: 'hidden' | 'scroll';
1115
overflowY?: 'hidden' | 'scroll';
1216
};
1317

14-
const styles: CSSProperties = { height: '100%', width: '100%' };
18+
const styles: CSSProperties = { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 };
1519

1620
const ScrollableContent = ({ children, maxHeight, overflowX = 'hidden', overflowY = 'scroll' }: Props) => {
1721
const overlayscrollbarsOptions = useMemo(
1822
() => getOverlayScrollbarsParams(overflowX, overflowY).options,
1923
[overflowX, overflowY]
2024
);
25+
const [os, osRef] = useState<OverlayScrollbarsComponentRef | null>(null);
26+
useEffect(() => {
27+
const osInstance = os?.osInstance();
28+
29+
if (!osInstance) {
30+
return;
31+
}
32+
33+
const element = osInstance.elements().viewport;
34+
35+
// `pragmatic-drag-and-drop-auto-scroll` requires the element to have `overflow-y: scroll` or `overflow-y: auto`
36+
// else it logs an ugly warning. In our case, using a custom scrollbar library, it will be 'hidden' by default.
37+
// To prevent the erroneous warning, we temporarily set the overflow-y to 'scroll' and then revert it back.
38+
const overflowY = element.style.overflowY; // starts 'hidden'
39+
element.style.setProperty('overflow-y', 'scroll', 'important');
40+
const cleanup = combine(autoScrollForElements({ element }), autoScrollForExternal({ element }));
41+
element.style.setProperty('overflow-y', overflowY);
42+
43+
return cleanup;
44+
}, [os]);
45+
2146
return (
2247
<Flex w="full" h="full" maxHeight={maxHeight} position="relative">
2348
<Box position="absolute" top={0} left={0} right={0} bottom={0}>
24-
<OverlayScrollbarsComponent defer style={styles} options={overlayscrollbarsOptions}>
49+
<OverlayScrollbarsComponent ref={osRef} style={styles} options={overlayscrollbarsOptions}>
2550
{children}
2651
</OverlayScrollbarsComponent>
2752
</Box>

invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/BoardsListWrapper.tsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,23 @@ const BoardsListWrapper = () => {
2121
const allowPrivateBoards = useAppSelector(selectAllowPrivateBoards);
2222
const [os, osRef] = useState<OverlayScrollbarsComponentRef | null>(null);
2323
useEffect(() => {
24-
const element = os?.osInstance()?.elements().viewport;
25-
if (!element) {
24+
const osInstance = os?.osInstance();
25+
26+
if (!osInstance) {
2627
return;
2728
}
28-
return combine(autoScrollForElements({ element }), autoScrollForExternal({ element }));
29+
30+
const element = osInstance.elements().viewport;
31+
32+
// `pragmatic-drag-and-drop-auto-scroll` requires the element to have `overflow-y: scroll` or `overflow-y: auto`
33+
// else it logs an ugly warning. In our case, using a custom scrollbar library, it will be 'hidden' by default.
34+
// To prevent the erroneous warning, we temporarily set the overflow-y to 'scroll' and then revert it back.
35+
const overflowY = element.style.overflowY; // starts 'hidden'
36+
element.style.setProperty('overflow-y', 'scroll', 'important');
37+
const cleanup = combine(autoScrollForElements({ element }), autoScrollForExternal({ element }));
38+
element.style.setProperty('overflow-y', overflowY);
39+
40+
return cleanup;
2941
}, [os]);
3042

3143
return (

invokeai/frontend/web/src/features/nodes/components/sidePanel/workflow/WorkflowLinearTab.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const WorkflowLinearTab = () => {
2525
return (
2626
<Box position="relative" w="full" h="full">
2727
<ScrollableContent>
28-
<Flex position="relative" flexDir="column" alignItems="flex-start" p={1} gap={2} h="full" w="full">
28+
<Flex position="relative" flexDir="column" alignItems="flex-start" p={1} py={2} gap={2} h="full" w="full">
2929
<FieldListContent />
3030
</Flex>
3131
</ScrollableContent>

0 commit comments

Comments
 (0)