Skip to content

Commit c96a5f3

Browse files
committed
try setting overflow-x: hidden instead
1 parent 14a4cd3 commit c96a5f3

File tree

5 files changed

+13
-35
lines changed

5 files changed

+13
-35
lines changed

packages/@react-aria/virtualizer/src/ScrollView.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,18 +159,18 @@ function ScrollView(props: ScrollViewProps, ref: RefObject<HTMLDivElement>) {
159159
if (scrollDirection === 'horizontal') {
160160
style.overflowX = 'auto';
161161
style.overflowY = 'hidden';
162-
} else if (scrollDirection === 'vertical') {
162+
} else if (scrollDirection === 'vertical' || contentSize.width === state.width) {
163+
// Set overflow-x: hidden if content size is equal to the width of the scroll view.
164+
// This prevents horizontal scrollbars from flickering during resizing due to resize observer
165+
// firing slower than the frame rate, which may cause an infinite re-render loop.
163166
style.overflowY = 'auto';
164167
style.overflowX = 'hidden';
165168
} else {
166169
style.overflow = 'auto';
167170
}
168171

169172
innerStyle = {
170-
// Omit width on inner element if it is equal to the width of the outer element.
171-
// Since this is a block element, the browser will automatically make it full width.
172-
// This prevents horizontal scrollbars from flickering when not needed.
173-
width: contentSize.width === state.width ? undefined : contentSize.width,
173+
width: contentSize.width,
174174
height: contentSize.height,
175175
pointerEvents: isScrolling ? 'none' : 'auto',
176176
position: 'relative',

packages/@react-aria/virtualizer/src/VirtualizerItem.tsx

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*/
1212

1313
import {Direction} from '@react-types/shared';
14-
import {LayoutInfo, Size} from '@react-stately/virtualizer';
14+
import {LayoutInfo} from '@react-stately/virtualizer';
1515
import React, {CSSProperties, ReactNode, useRef} from 'react';
1616
import {useLocale} from '@react-aria/i18n';
1717
import {useVirtualizerItem, VirtualizerItemOptions} from './useVirtualizerItem';
@@ -33,19 +33,14 @@ export function VirtualizerItem(props: VirtualizerItemProps) {
3333
});
3434

3535
return (
36-
<div role="presentation" ref={ref} className={className} style={layoutInfoToStyle(layoutInfo, direction, parent, virtualizer.contentSize)}>
36+
<div role="presentation" ref={ref} className={className} style={layoutInfoToStyle(layoutInfo, direction, parent)}>
3737
{children}
3838
</div>
3939
);
4040
}
4141

4242
let cache = new WeakMap();
43-
export function layoutInfoToStyle(
44-
layoutInfo: LayoutInfo,
45-
dir: Direction,
46-
parent?: LayoutInfo | null,
47-
contentSize?: Size
48-
): CSSProperties {
43+
export function layoutInfoToStyle(layoutInfo: LayoutInfo, dir: Direction, parent?: LayoutInfo | null): CSSProperties {
4944
let xProperty = dir === 'rtl' ? 'right' : 'left';
5045
let cached = cache.get(layoutInfo);
5146
if (cached && cached[xProperty] != null) {
@@ -61,13 +56,6 @@ export function layoutInfoToStyle(
6156
}
6257
}
6358

64-
// Determine if the layoutInfo is the full width of its parent.
65-
// In this case, we use 100% as the width rather than a pixel value,
66-
// which avoids issues with flickering scrollbars.
67-
let isFullWidth = parent
68-
? layoutInfo.rect.x === parent.rect.x && layoutInfo.rect.width === parent.rect.width
69-
: contentSize && layoutInfo.rect.x === 0 && layoutInfo.rect.width === contentSize.width;
70-
7159
let style: CSSProperties = {
7260
position: layoutInfo.isSticky ? 'sticky' : 'absolute',
7361
// Sticky elements are positioned in normal document flow. Display inline-block so that they don't push other sticky columns onto the following rows.
@@ -79,7 +67,7 @@ export function layoutInfoToStyle(
7967
WebkitTransition: 'all',
8068
WebkitTransitionDuration: 'inherit',
8169
transitionDuration: 'inherit',
82-
width: isFullWidth ? '100%' : layoutInfo.rect.width,
70+
width: layoutInfo.rect.width,
8371
height: layoutInfo.rect.height,
8472
opacity: layoutInfo.opacity,
8573
zIndex: layoutInfo.zIndex,

packages/@react-aria/virtualizer/src/useVirtualizerItem.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import {RefObject, useCallback} from 'react';
1616
import {useLayoutEffect} from '@react-aria/utils';
1717

1818
interface IVirtualizer {
19-
contentSize: Size,
2019
updateItemSize(key: Key, size: Size): void
2120
}
2221

packages/@react-spectrum/table/src/TableViewBase.tsx

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ function TableViewBase<T extends object>(props: TableBaseProps<T>, ref: DOMRef<H
286286
// This overrides collection view's renderWrapper to support DOM hierarchy.
287287
type View = ReusableView<GridNode<T>, ReactNode>;
288288
let renderWrapper = (parent: View, reusableView: View, children: View[], renderChildren: (views: View[]) => ReactElement[]) => {
289-
let style = layoutInfoToStyle(reusableView.layoutInfo, direction, parent?.layoutInfo, reusableView.virtualizer.visibleRect);
289+
let style = layoutInfoToStyle(reusableView.layoutInfo, direction, parent && parent.layoutInfo);
290290
if (style.overflow === 'hidden') {
291291
style.overflow = 'visible'; // needed to support position: sticky
292292
}
@@ -620,11 +620,10 @@ function TableVirtualizer(props) {
620620

621621
let resizerPosition = layout.getResizerPosition() - 2;
622622

623-
let visibleRect = state.virtualizer.visibleRect;
624-
let resizerAtEdge = resizerPosition > Math.max(state.virtualizer.contentSize.width, visibleRect.width) - 3;
623+
let resizerAtEdge = resizerPosition > Math.max(state.virtualizer.contentSize.width, state.virtualizer.visibleRect.width) - 3;
625624
// this should be fine, every movement of the resizer causes a rerender
626625
// scrolling can cause it to lag for a moment, but it's always updated
627-
let resizerInVisibleRegion = resizerPosition < visibleRect.maxX;
626+
let resizerInVisibleRegion = resizerPosition < state.virtualizer.visibleRect.maxX;
628627
let shouldHardCornerResizeCorner = resizerAtEdge && resizerInVisibleRegion;
629628

630629
// minimize re-render caused on Resizers by memoing this
@@ -656,14 +655,7 @@ function TableVirtualizer(props) {
656655
transition: state.isAnimating ? `none ${state.virtualizer.transitionDuration}ms` : undefined
657656
}}
658657
ref={headerRef}>
659-
<div
660-
role="presentation"
661-
style={{
662-
width: state.contentSize.width === visibleRect.width ? undefined : state.contentSize.width,
663-
height: headerHeight
664-
}}>
665-
{state.visibleViews[0]}
666-
</div>
658+
{state.visibleViews[0]}
667659
</div>
668660
<ScrollView
669661
role="presentation"

packages/@react-types/sidenav/src/index.d.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ export interface SpectrumSideNavItemProps<T> extends HTMLAttributes<HTMLElement>
2828
}
2929

3030
interface IVirtualizer {
31-
contentSize: Size,
3231
updateItemSize(key: Key, size: Size): void
3332
}
3433

0 commit comments

Comments
 (0)