Skip to content

Commit 4a1bba0

Browse files
committed
update ListLayoutOptions to clearer names and document horizontal orientation
1 parent 01b5d84 commit 4a1bba0

File tree

4 files changed

+123
-38
lines changed

4 files changed

+123
-38
lines changed

packages/dev/s2-docs/pages/react-aria/Virtualizer.mdx

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export const description = 'Renders a scrollable collection of data using custom
1212

1313
<PageDescription>{docs.exports.Virtualizer.description}</PageDescription>
1414

15-
```tsx render docs={docs.exports.ListLayoutOptions} links={docs.links} props={['rowHeight', 'gap', 'padding']} initialProps={{rowHeight: 32, gap: 4, padding: 4}} propsObject="layoutOptions" wide
15+
```tsx render docs={docs.exports.ListLayoutOptions} links={docs.links} props={['rowSize', 'gap', 'padding']} initialProps={{rowSize: 32, gap: 4, padding: 4}} propsObject="layoutOptions" wide
1616
"use client";
1717
import {Virtualizer, ListLayout} from 'react-aria-components';
1818
import {ListBox, ListBoxItem} from 'vanilla-starter/ListBox';
@@ -49,9 +49,9 @@ Virtualizer uses <TypeLink links={docs.links} type={docs.exports.Layout} /> obje
4949

5050
### List
5151

52-
`ListLayout` supports layout of items in a vertical stack. Rows can be fixed or variable height. When using variable heights, set the `estimatedRowHeight` to a reasonable guess for how tall the rows will be on average. This allows the size of the scrollbar to be calculated.
52+
`ListLayout` places items along its orientation. Rows can be fixed or variable size. When using variable size, set the `estimatedRowSize` to a reasonable guess for how tall or wide the rows will be on average. This allows the size of the scrollbar to be calculated.
5353

54-
```tsx render docs={docs.exports.ListLayoutOptions} links={docs.links} props={['gap', 'padding']} initialProps={{estimatedRowHeight: 75, gap: 4, padding: 4}} propsObject="layoutOptions" wide
54+
```tsx render docs={docs.exports.ListLayoutOptions} links={docs.links} props={['gap', 'padding']} initialProps={{estimatedRowSize: 75, gap: 4, padding: 4}} propsObject="layoutOptions" wide
5555
"use client";
5656
import {Virtualizer, ListLayout} from 'react-aria-components';
5757
import {ListBox, ListBoxItem} from 'vanilla-starter/ListBox';
@@ -80,6 +80,41 @@ for (let i = 0; i < 5000; i++) {
8080
</Virtualizer>
8181
```
8282

83+
84+
Use the `orientation` option to arrange items horizontally or vertically. Provide the same `orientation` on the collection component so keyboard navigation matches the layout.
85+
86+
```tsx render docs={docs.exports.ListLayoutOptions} links={docs.links} props={['gap', 'padding']} initialProps={{estimatedRowSize: 100, gap: 4, padding: 4, orientation: 'horizontal'}} propsObject="layoutOptions" wide
87+
"use client";
88+
import {Virtualizer, ListLayout} from 'react-aria-components';
89+
import {ListBox, ListBoxItem} from 'vanilla-starter/ListBox';
90+
91+
let lorem = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin sit amet tristique risus. In sit amet suscipit lorem. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In condimentum imperdiet metus non condimentum. Duis eu velit et quam accumsan tempus at id velit. Duis elementum elementum purus, id tempus mauris posuere a. Nunc vestibulum sapien pellentesque lectus commodo ornare.'.split(' ');
92+
let items: {id: number, name: string}[] = [];
93+
for (let i = 0; i < 5000; i++) {
94+
let words = Math.max(2, Math.floor(Math.random() * 10));
95+
let name = lorem.slice(0, words).join(' ');
96+
items.push({id: i, name});
97+
}
98+
99+
<Virtualizer
100+
/*- begin highlight -*/
101+
layout={ListLayout}
102+
/* PROPS */
103+
>
104+
{/*- end highlight -*/}
105+
<ListBox
106+
/*- begin highlight -*/
107+
orientation="horizontal"
108+
/*- end highlight -*/
109+
aria-label="Horizontal virtualized list"
110+
selectionMode="multiple"
111+
items={items}
112+
style={{display: 'block', padding: 0, height: 150}}>
113+
{(item) => <ListBoxItem style={{height: '100%'}}>{item.name}</ListBoxItem>}
114+
</ListBox>
115+
</Virtualizer>
116+
```
117+
83118
### Grid
84119

85120
`GridLayout` supports layout of items in an equal size grid. The items are sized between a minimum and maximum size depending on the width of the container. Make sure to set `layout="grid"` on the `ListBox` or `GridList` component as well so that keyboard navigation behavior is correct.
@@ -426,7 +461,7 @@ for (let i = 0; images.length < 500; i++) {
426461

427462
`TableLayout` provides layout of items in rows and columns, supporting virtualization of both horizontal and vertical scrolling. It should be used with the [Table](Table) component. Rows can be fixed or variable height. When using variable heights, set the `estimatedRowHeight` to a reasonable guess for how tall the rows will be on average. This allows the size of the scrollbar to be calculated.
428463

429-
```tsx render docs={docs.exports.ListLayoutOptions} links={docs.links} props={['rowHeight', 'headingHeight', 'padding', 'gap']} initialProps={{rowHeight: 32, headingHeight: 32, padding: 4, gap: 4}} propsObject="layoutOptions" wide
464+
```tsx render docs={docs.exports.TableLayoutProps} links={docs.links} props={['rowHeight', 'headingHeight', 'padding', 'gap']} initialProps={{rowHeight: 32, headingHeight: 32, padding: 4, gap: 4}} propsObject="layoutOptions" wide
430465
"use client";
431466
import {Virtualizer, TableLayout} from 'react-aria-components';
432467
import {Cell, Column, Row, Table, TableBody, TableHeader} from 'vanilla-starter/Table';
@@ -501,4 +536,4 @@ for (let i = 0; i < 1000; i++) {
501536

502537
### TableLayout
503538

504-
<GroupedPropTable {...docs.exports.ListLayoutOptions} links={docs.links} />
539+
<GroupedPropTable {...docs.exports.TableLayoutProps} links={docs.links} />

packages/react-aria-components/exports/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,4 +207,5 @@ export type {AutocompleteState} from 'react-stately/private/autocomplete/useAuto
207207
export type {ListLayoutOptions} from 'react-stately/private/layout/ListLayout';
208208
export type {GridLayoutOptions} from 'react-stately/private/layout/GridLayout';
209209
export type {WaterfallLayoutOptions} from 'react-stately/private/layout/WaterfallLayout';
210+
export type {TableLayoutProps} from 'react-stately/private/layout/TableLayout';
210211
export type {RangeValue, ValidationResult, RouterConfig} from '@react-types/shared';

packages/react-stately/src/layout/ListLayout.ts

Lines changed: 58 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -25,25 +25,25 @@ export interface ListLayoutOptions {
2525
*/
2626
orientation?: Orientation,
2727
/**
28-
* The fixed height of a row in px.
28+
* The fixed size of a row in px with respect to the applied orientation.
2929
* @default 48
3030
*/
31-
rowHeight?: number,
32-
/** The estimated height of a row, when row heights are variable. */
33-
estimatedRowHeight?: number,
31+
rowSize?: number,
32+
/** The estimated size of a row in px with respect to the applied orientation, when row sizes are variable. */
33+
estimatedRowSize?: number,
3434
/**
35-
* The fixed height of a section header in px.
35+
* The fixed size of a section header in px with respect to the applied orientation.
3636
* @default 48
3737
*/
38-
headingHeight?: number,
39-
/** The estimated height of a section header, when the height is variable. */
40-
estimatedHeadingHeight?: number,
38+
headingSize?: number,
39+
/** The estimated size of a section header in px with respect to the applied orientation, when heading sizes are variable. */
40+
estimatedHeadingSize?: number,
4141
/**
42-
* The fixed height of a loader element in px. This loader is specifically for
42+
* The fixed size of a loader element in px with respect to the applied orientation. This loader is specifically for
4343
* "load more" elements rendered when loading more rows at the root level or inside nested row/sections.
4444
* @default 48
4545
*/
46-
loaderHeight?: number,
46+
loaderSize?: number,
4747
/**
4848
* The thickness of the drop indicator.
4949
* @default 2
@@ -58,7 +58,34 @@ export interface ListLayoutOptions {
5858
* The padding around the list.
5959
* @default 0
6060
*/
61-
padding?: number
61+
padding?: number,
62+
/**
63+
* The fixed height of a row in px.
64+
* @default 48
65+
* @deprecated Use `rowSize` instead.
66+
*/
67+
rowHeight?: number,
68+
/** The estimated height of a row, when row heights are variable.
69+
* @deprecated Use `estimatedRowSize` instead.
70+
*/
71+
estimatedRowHeight?: number,
72+
/**
73+
* The fixed height of a section header in px.
74+
* @default 48
75+
* @deprecated Use `headingSize` instead.
76+
*/
77+
headingHeight?: number,
78+
/** The estimated height of a section header, when the height is variable.
79+
* @deprecated Use `estimatedHeadingSize` instead.
80+
*/
81+
estimatedHeadingHeight?: number,
82+
/**
83+
* The fixed height of a loader element in px. This loader is specifically for
84+
* "load more" elements rendered when loading more rows at the root level or inside nested row/sections.
85+
* @default 48
86+
* @deprecated Use `loaderSize` instead.
87+
*/
88+
loaderHeight?: number
6289
}
6390

6491
// A wrapper around LayoutInfo that supports hierarchy
@@ -74,8 +101,8 @@ const DEFAULT_HEIGHT = 48;
74101

75102
/**
76103
* ListLayout is a virtualizer Layout implementation
77-
* that arranges its items in a vertical stack. It supports both fixed
78-
* and variable height items.
104+
* that arranges its items in a stack along its applied orientation.
105+
* It supports both fixed and variable size items.
79106
*/
80107
export class ListLayout<T, O extends ListLayoutOptions = ListLayoutOptions> extends Layout<Node<T>, O> implements DropTargetDelegate {
81108
protected rowHeight: number | null;
@@ -103,12 +130,12 @@ export class ListLayout<T, O extends ListLayoutOptions = ListLayoutOptions> exte
103130
*/
104131
constructor(options: ListLayoutOptions = {}) {
105132
super();
106-
this.rowHeight = options.rowHeight ?? null;
133+
this.rowHeight = options?.rowSize ?? options?.rowHeight ?? null;
107134
this.orientation = options.orientation ?? 'vertical';
108-
this.estimatedRowHeight = options.estimatedRowHeight ?? null;
109-
this.headingHeight = options.headingHeight ?? null;
110-
this.estimatedHeadingHeight = options.estimatedHeadingHeight ?? null;
111-
this.loaderHeight = options.loaderHeight ?? null;
135+
this.estimatedRowHeight = options?.estimatedRowSize ?? options?.estimatedRowHeight ?? null;
136+
this.headingHeight = options?.headingSize ?? options?.headingHeight ?? null;
137+
this.estimatedHeadingHeight = options?.estimatedHeadingSize ?? options?.estimatedHeadingHeight ?? null;
138+
this.loaderHeight = options?.loaderSize ?? options?.loaderHeight ?? null;
112139
this.dropIndicatorThickness = options.dropIndicatorThickness || 2;
113140
this.gap = options.gap || 0;
114141
this.padding = options.padding || 0;
@@ -208,21 +235,21 @@ export class ListLayout<T, O extends ListLayoutOptions = ListLayoutOptions> exte
208235
// Also invalidate if fixed sizes/gaps change.
209236
let options = invalidationContext.layoutOptions;
210237
return invalidationContext.sizeChanged
211-
|| this.rowHeight !== (options?.rowHeight ?? this.rowHeight)
238+
|| this.rowHeight !== (options?.rowSize ?? options?.rowHeight ?? this.rowHeight)
212239
|| this.orientation !== (options?.orientation ?? this.orientation)
213-
|| this.headingHeight !== (options?.headingHeight ?? this.headingHeight)
214-
|| this.loaderHeight !== (options?.loaderHeight ?? this.loaderHeight)
240+
|| this.headingHeight !== (options?.headingSize ?? options?.headingHeight ?? this.headingHeight)
241+
|| this.loaderHeight !== (options?.loaderSize ?? options?.loaderHeight ?? this.loaderHeight)
215242
|| this.gap !== (options?.gap ?? this.gap)
216243
|| this.padding !== (options?.padding ?? this.padding);
217244
}
218245

219246
shouldInvalidateLayoutOptions(newOptions: O, oldOptions: O): boolean {
220-
return newOptions.rowHeight !== oldOptions.rowHeight
247+
return (newOptions?.rowSize ?? newOptions?.rowHeight) !== (oldOptions?.rowSize ?? oldOptions?.rowHeight)
221248
|| newOptions.orientation !== oldOptions.orientation
222-
|| newOptions.estimatedRowHeight !== oldOptions.estimatedRowHeight
223-
|| newOptions.headingHeight !== oldOptions.headingHeight
224-
|| newOptions.estimatedHeadingHeight !== oldOptions.estimatedHeadingHeight
225-
|| newOptions.loaderHeight !== oldOptions.loaderHeight
249+
|| (newOptions?.estimatedRowSize ?? newOptions?.estimatedRowHeight) !== (oldOptions?.estimatedRowSize ?? oldOptions?.estimatedRowHeight)
250+
|| (newOptions?.headingSize ?? newOptions?.headingHeight) !== (oldOptions?.headingSize ?? oldOptions?.headingHeight)
251+
|| (newOptions?.estimatedHeadingSize ?? newOptions?.estimatedHeadingHeight) !== (oldOptions?.estimatedHeadingSize ?? oldOptions?.estimatedHeadingHeight)
252+
|| (newOptions?.loaderSize ?? newOptions?.loaderHeight) !== (oldOptions?.loaderSize ?? oldOptions?.loaderHeight)
226253
|| newOptions.dropIndicatorThickness !== oldOptions.dropIndicatorThickness
227254
|| newOptions.gap !== oldOptions.gap
228255
|| newOptions.padding !== oldOptions.padding;
@@ -240,12 +267,12 @@ export class ListLayout<T, O extends ListLayoutOptions = ListLayoutOptions> exte
240267
}
241268

242269
let options = invalidationContext.layoutOptions;
243-
this.rowHeight = options?.rowHeight ?? this.rowHeight;
270+
this.rowHeight = options?.rowSize ?? options?.rowHeight ?? this.rowHeight;
244271
this.orientation = options?.orientation ?? this.orientation;
245-
this.estimatedRowHeight = options?.estimatedRowHeight ?? this.estimatedRowHeight;
246-
this.headingHeight = options?.headingHeight ?? this.headingHeight;
247-
this.estimatedHeadingHeight = options?.estimatedHeadingHeight ?? this.estimatedHeadingHeight;
248-
this.loaderHeight = options?.loaderHeight ?? this.loaderHeight;
272+
this.estimatedRowHeight = options?.estimatedRowSize ?? options?.estimatedRowHeight ?? this.estimatedRowHeight;
273+
this.headingHeight = options?.headingSize ?? options?.headingHeight ?? this.headingHeight;
274+
this.estimatedHeadingHeight = options?.estimatedHeadingSize ?? options?.estimatedHeadingHeight ?? this.estimatedHeadingHeight;
275+
this.loaderHeight = options?.loaderSize ?? options?.loaderHeight ?? this.loaderHeight;
249276
this.dropIndicatorThickness = options?.dropIndicatorThickness ?? this.dropIndicatorThickness;
250277
this.gap = options?.gap ?? this.gap;
251278
this.padding = options?.padding ?? this.padding;

packages/react-stately/src/layout/TableLayout.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,29 @@ import {Size} from '../virtualizer/Size';
2222
import {ITableCollection as TableCollection} from '../table/TableCollection';
2323
import {TableColumnLayout} from '../table/TableColumnLayout';
2424

25-
export interface TableLayoutProps extends ListLayoutOptions {
25+
export interface TableLayoutProps extends Omit<ListLayoutOptions, 'orientation' | 'rowSize' | 'estimatedRowSize' | 'headingSize' | 'estimatedHeadingSize' | 'loaderSize'> {
26+
/**
27+
* The fixed height of a row in px.
28+
* @default 48
29+
*/
30+
rowHeight?: number,
31+
/** The estimated height of a row, when row heights are variable.
32+
*/
33+
estimatedRowHeight?: number,
34+
/**
35+
* The fixed height of a section header in px.
36+
* @default 48
37+
*/
38+
headingHeight?: number,
39+
/** The estimated height of a section header, when the height is variable.
40+
*/
41+
estimatedHeadingHeight?: number,
42+
/**
43+
* The fixed height of a loader element in px. This loader is specifically for
44+
* "load more" elements rendered when loading more rows at the root level or inside nested row/sections.
45+
* @default 48
46+
*/
47+
loaderHeight?: number,
2648
columnWidths?: Map<Key, number>
2749
}
2850

@@ -39,7 +61,7 @@ export class TableLayout<T, O extends TableLayoutProps = TableLayoutProps> exten
3961
private lastPersistedKeys: Set<Key> | null = null;
4062
private persistedIndices: Map<Key, number[]> = new Map();
4163

42-
constructor(options?: ListLayoutOptions) {
64+
constructor(options?: TableLayoutProps) {
4365
super(options);
4466
this.stickyColumnIndices = [];
4567
}

0 commit comments

Comments
 (0)