GridList
A grid list displays a list of interactive items, with support for keyboard navigation, single or multiple selection, and row actions.
Content
GridList
follows the Collection Components API, accepting both static and dynamic collections. This example shows a dynamic collection, passing a list of objects to the items
prop, and a function to render the children.
import {GridList, GridListItem} from './GridList';
function Example() {
let options = [
{ id: 1, name: 'Aardvark' },
{ id: 2, name: 'Cat' },
{ id: 3, name: 'Dog' },
{ id: 4, name: 'Kangaroo' },
{ id: 5, name: 'Koala' },
{ id: 6, name: 'Penguin' },
{ id: 7, name: 'Snake' },
{ id: 8, name: 'Turtle' },
{ id: 9, name: 'Wombat' }
];
return (
<GridList aria-label="Animals" items={options} selectionMode="multiple">
{(item) => <GridListItem>{item.name}</GridListItem>}
</GridList>
);
}
Asynchronous loading
Use renderEmptyState to display a spinner during initial load. To enable infinite scrolling, render a <GridListLoadMoreItem>
at the end of the list. Use whatever data fetching library you prefer – this example uses useAsyncList
from react-stately
.
import {Collection, GridListLoadMoreItem} from 'react-aria-components';
import {GridList, GridListItem} from './GridList';
import {ProgressCircle} from './ProgressCircle';
import {useAsyncList} from '@react-stately/data';
interface Character {
name: string
}
function AsyncLoadingExample() {
let list = useAsyncList<Character>({
async load({ signal, cursor }) {
if (cursor) {
cursor = cursor.replace(/^http:\/\//i, 'https://');
}
let res = await fetch(
cursor || `https://swapi.py4e.com/api/people/?search=`,
{ signal }
);
let json = await res.json();
return {
items: json.results,
cursor: json.next
};
}
});
return (
<GridList
aria-label="Star Wars Characters"
selectionMode="multiple"
renderEmptyState={() => (
<ProgressCircle isIndeterminate aria-label="Loading..." />
)}>
<Collection items={list.items}>
{(item) => <GridListItem id={item.name}>{item.name}</GridListItem>}
</Collection>
<GridListLoadMoreItem
onLoadMore={list.loadMore}
isLoading={list.loadingState === 'loadingMore'}>
<ProgressCircle isIndeterminate aria-label="Loading more..." />
</GridListLoadMoreItem>
</GridList>
);
}
Links
Use the href
prop on a <GridListItem>
to create a link. See the client side routing guide to learn how to integrate with your framework. Link interactions vary depending on the selection behavior. See the selection guide for more details.
Empty state
import {GridList} from './GridList';
<GridList
aria-label="Search results"
renderEmptyState={() => 'No results found.'}>
{[]}
</GridList>
Selection and actions
Use the selectionMode
prop to enable single or multiple selection. The selected items can be controlled via the selectedKeys
prop, matching the id
prop of the items. The onAction
event handles item actions. Items can be disabled with the isDisabled
prop. See the selection guide for more details.
Current selection:
Drag and drop
GridList supports drag and drop interactions when the dragAndDropHooks
prop is provided using the useDragAndDrop hook. Users can drop data on the list as a whole, on individual items, insert new items between existing ones, or reorder items. React Aria supports drag and drop via mouse, touch, keyboard, and screen reader interactions. See the drag and drop guide to learn more.
import {useListData} from 'react-stately';
import {GridList, GridListItem} from './GridList';
import {useDragAndDrop} from 'react-aria-components';
function Example() {
let list = useListData({
initialItems: [
{id: 1, name: 'Adobe Photoshop'},
{id: 2, name: 'Adobe XD'},
{id: 3, name: 'Adobe Dreamweaver'},
{id: 4, name: 'Adobe InDesign'},
{id: 5, name: 'Adobe Connect'}
]
});
let {dragAndDropHooks} = useDragAndDrop({
getItems: (keys) => [...keys].map(key => ({'text/plain': list.getItem(key).name})),
onReorder(e) {
if (e.target.dropPosition === 'before') {
list.moveBefore(e.target.key, e.keys);
} else if (e.target.dropPosition === 'after') {
list.moveAfter(e.target.key, e.keys);
}
}
});
return (
<GridList
aria-label="Reorderable list"
selectionMode="multiple"
items={list.items}
dragAndDropHooks={dragAndDropHooks}
>
{item => <GridListItem>{item.name}</GridListItem>}
</GridList>
);
}