diff --git a/packages/@react-spectrum/s2/src/Card.tsx b/packages/@react-spectrum/s2/src/Card.tsx index d1901befab8..1c7b1265657 100644 --- a/packages/@react-spectrum/s2/src/Card.tsx +++ b/packages/@react-spectrum/s2/src/Card.tsx @@ -215,7 +215,7 @@ let selectionIndicator = style({ }, // Quiet cards with no checkbox have an extra inner stroke // to distinguish the selection indicator from the preview. - outlineColor: 'gray-25', + outlineColor: lightDark('transparent-white-600', 'transparent-black-600'), outlineOffset: -4, outlineStyle: { default: 'none', @@ -331,6 +331,13 @@ let content = style({ } }); +let actionMenu = style({ + gridArea: 'menu', + // Don't cause the row to expand, preserve gap between title and description text. + // Would use -100% here but it doesn't work in Firefox. + marginY: '[calc(-1 * self(height))]' +}); + let footer = style({ display: 'flex', flexDirection: 'row', @@ -397,7 +404,7 @@ export const Card = forwardRef(function Card(props: CardProps, ref: DOMRef diff --git a/packages/@react-spectrum/s2/src/CardView.tsx b/packages/@react-spectrum/s2/src/CardView.tsx index 430a41a634d..41f35ad237e 100644 --- a/packages/@react-spectrum/s2/src/CardView.tsx +++ b/packages/@react-spectrum/s2/src/CardView.tsx @@ -194,9 +194,20 @@ class FlexibleGridLayout extends Layout, GridLayoutOpt } } +class WaterfallLayoutInfo extends LayoutInfo { + column = 0; + + copy(): WaterfallLayoutInfo { + let res = super.copy() as WaterfallLayoutInfo; + res.column = this.column; + return res; + } +} + class WaterfallLayout extends Layout, GridLayoutOptions> implements LayoutDelegate { protected contentSize: Size = new Size(); - protected layoutInfos: Map = new Map(); + protected layoutInfos: Map = new Map(); + protected numColumns = 0; update(invalidationContext: InvalidationContext): void { let { @@ -246,15 +257,18 @@ class WaterfallLayout extends Layout, GridLayoutOption } // Figure out which column to place the item in, and compute its position. - let column = columnHeights.reduce((minIndex, h, i) => h < columnHeights[minIndex] ? i : minIndex, 0); + // Preserve the previous column index so items don't jump around during resizing unless the number of columns changed. + let prevColumn = numColumns === this.numColumns ? oldLayoutInfo?.column : undefined; + let column = prevColumn ?? columnHeights.reduce((minIndex, h, i) => h < columnHeights[minIndex] ? i : minIndex, 0); let x = horizontalSpacing + column * (itemWidth + horizontalSpacing); let y = columnHeights[column]; let rect = new Rect(x, y, itemWidth, height); - let layoutInfo = new LayoutInfo(node.type, key, rect); + let layoutInfo = new WaterfallLayoutInfo(node.type, key, rect); layoutInfo.estimatedSize = estimatedSize; layoutInfo.allowOverflow = true; layoutInfo.content = node; + layoutInfo.column = column; newLayoutInfos.set(key, layoutInfo); columnHeights[column] += layoutInfo.rect.height + minSpace.height; @@ -283,6 +297,7 @@ class WaterfallLayout extends Layout, GridLayoutOption let maxHeight = Math.max(...columnHeights); this.contentSize = new Size(this.virtualizer.visibleRect.width, maxHeight); this.layoutInfos = newLayoutInfos; + this.numColumns = numColumns; } getLayoutInfo(key: Key): LayoutInfo {