Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(CustomScrollView): add resize container handler #7060

Merged
merged 9 commits into from
Jun 24, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
position: relative;
}

.CustomScrollView__box-content {
position: relative;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@EldarMuhamethanov а добавьте

  inline-size: 100%;
  block-size: 100%;

как у родителей, а то "растянутость" на контейнер теряется.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Semigradsky задумка была, такая что этот элемент, растягивается на реальные размеры контента, а не на размеры родителя. Мне кажется так сломается изначальный кейс. Можешь рассказать какой кейс сейчас ломается? если такой есть

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Например, растягиваем контейнер на всю страницу, у содержимого min-height: 100%. До этих исправлений отображался кастомный скролл, если содержимое занимает бОльшее пространство.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#7097 - PR с правкой

}

inomdzhon marked this conversation as resolved.
Show resolved Hide resolved
.CustomScrollView__barY:active + .CustomScrollView__box {
pointer-events: none;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { classNames } from '@vkontakte/vkjs';
import { useAdaptivity } from '../../hooks/useAdaptivity';
import { useEventListener } from '../../hooks/useEventListener';
import { useExternRef } from '../../hooks/useExternRef';
import { useResizeObserver } from '../../hooks/useResizeObserver';
import { useDOM } from '../../lib/dom';
import { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect';
import { stopPropagation } from '../../lib/utils';
Expand Down Expand Up @@ -57,6 +58,7 @@ export const CustomScrollView = ({
const trackerTop = React.useRef(0);

const boxRef = useExternRef(externalBoxRef);
const boxContentRef = React.useRef<HTMLDivElement>(null);

const barY = React.useRef<HTMLDivElement>(null);
const trackerY = React.useRef<HTMLDivElement>(null);
Expand Down Expand Up @@ -104,6 +106,8 @@ export const CustomScrollView = ({
}
}, [windowResize, window]);

useResizeObserver(boxContentRef, resize);

useIsomorphicLayoutEffect(() => {
let style = trackerY.current?.style;
let prop = '';
Expand Down Expand Up @@ -200,7 +204,9 @@ export const CustomScrollView = ({
{...restProps}
>
<div className={styles['CustomScrollView__box']} tabIndex={-1} ref={boxRef} onScroll={scroll}>
{children}
<div ref={boxContentRef} className={styles['CustomScrollView__box-content']}>
{children}
</div>
</div>

<div className={styles['CustomScrollView__barY']} ref={barY} onClick={stopPropagation}>
Expand Down
29 changes: 29 additions & 0 deletions packages/vkui/src/hooks/useResizeObserver.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { act, useRef } from 'react';
import { render, screen } from '@testing-library/react';
import { useResizeObserver } from './useResizeObserver';

describe('test useResizeObserver', () => {
it('should call callback when add block', async () => {
const callback = jest.fn();
const Fixture = (props: { mockedBlocksIds: string[] }) => {
const ref = useRef(null);
useResizeObserver(ref, callback);
return (
<div ref={ref} style={{ position: 'static' }}>
{props.mockedBlocksIds.map((id) => (
<div key={id} data-testid={id} style={{ height: 50 }}></div>
))}
</div>
);
};

const result = render(<Fixture mockedBlocksIds={['block-1']} />);

await act(async () => {
result.rerender(<Fixture mockedBlocksIds={['block-1', 'block-2']} />);
});

expect(callback).toHaveBeenCalledTimes(1);
expect(screen.getByTestId('block-2')).toBeInTheDocument();
});
});
31 changes: 31 additions & 0 deletions packages/vkui/src/hooks/useResizeObserver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as React from 'react';
import { CustomResizeObserver } from '../lib/floating/customResizeObserver';
import { useIsomorphicLayoutEffect } from '../lib/useIsomorphicLayoutEffect';
import { useStableCallback } from './useStableCallback';

/**
* Хук вызывает переданный коллбэк при изменении размеров элемента.
*/
export function useResizeObserver(
ref: React.MutableRefObject<HTMLElement | null>,
callback: (rect: DOMRect) => void,
) {
const stableCallback = useStableCallback(callback);

useIsomorphicLayoutEffect(
function addResizeObserverHandler() {
if (!ref.current) {
EldarMuhamethanov marked this conversation as resolved.
Show resolved Hide resolved
return;

Check warning on line 18 in packages/vkui/src/hooks/useResizeObserver.ts

View check run for this annotation

Codecov / codecov/patch

packages/vkui/src/hooks/useResizeObserver.ts#L18

Added line #L18 was not covered by tests
}
const element = ref.current;
const observer = new CustomResizeObserver(() => {
stableCallback(element.getBoundingClientRect());
EldarMuhamethanov marked this conversation as resolved.
Show resolved Hide resolved
});
observer.observe(element);
observer.appendToTheDOM();

return () => observer.disconnect();
},
[ref],
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ describe(CustomResizeObserver, () => {
height: '100%',
pointerEvents: 'none',
opacity: '0',
border: '0',
});

// скрытым от скринридеров
Expand Down
11 changes: 10 additions & 1 deletion packages/vkui/src/lib/floating/customResizeObserver.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
const defaultIframeStyles: Pick<
CSSStyleDeclaration,
'position' | 'left' | 'top' | 'zIndex' | 'width' | 'height' | 'pointerEvents' | 'opacity'
| 'position'
| 'left'
| 'top'
| 'zIndex'
| 'width'
| 'height'
| 'pointerEvents'
| 'opacity'
| 'border'
> = {
position: 'absolute',
left: '0',
Expand All @@ -10,6 +18,7 @@ const defaultIframeStyles: Pick<
height: '100%',
pointerEvents: 'none',
opacity: '0',
border: '0',
mendrew marked this conversation as resolved.
Show resolved Hide resolved
};

/*
Expand Down