Beta Preview

GridList

A grid list displays a list of interactive items, with support for keyboard navigation, single or multiple selection, and row actions.

Charizard
Blastoise
Venusaur
Pikachu
selectionMode 
Example
GridList.tsx
GridList.css
import {GridList, GridListItem} from './GridList';
import {Button} from './Button';

<GridList
  aria-label="Favorite pokemon"
  selectionMode="multiple">
  <GridListItem textValue="Charizard">
    Charizard
    <Button aria-label="Info">ⓘ</Button>
  </GridListItem>
  <GridListItem textValue="Blastoise">
    Blastoise
    <Button aria-label="Info">ⓘ</Button>
  </GridListItem>
  <GridListItem textValue="Venusaur">
    Venusaur
    <Button aria-label="Info">ⓘ</Button>
  </GridListItem>
  <GridListItem textValue="Pikachu">
    Pikachu
    <Button aria-label="Info">ⓘ</Button>
  </GridListItem>
</GridList>

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.

Aardvark
Cat
Dog
Kangaroo
Koala
Penguin
Snake
Turtle
Wombat
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>
  );
}

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.

Adobe
Apple
Google
Microsoft
selectionBehavior 
import {GridList, GridListItem} from './GridList';

<GridList
  aria-label="Links"
  selectionMode="multiple">
  <GridListItem href="https://adobe.com/" target="_blank">Adobe</GridListItem>
  <GridListItem href="https://apple.com/" target="_blank">Apple</GridListItem>
  <GridListItem href="https://google.com/" target="_blank">Google</GridListItem>
  <GridListItem href="https://microsoft.com/" target="_blank">Microsoft</GridListItem>
</GridList>

Empty state

No results found.
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.

Lettuce
Tomato
Cheese
Tuna Salad
Egg Salad
Ham

Current selection:

selectionMode 
selectionBehavior 
disabledBehavior 
disallowEmptySelection 
import type {Selection} from 'react-aria-components';
import {GridList, GridListItem} from './GridList';
import {useState} from 'react';

function Example(props) {
  let [selected, setSelected] = useState<Selection>(new Set());

  return (
    <div>
      <GridList
        {...props}
        aria-label="Sandwich contents"
        selectionMode="multiple"
        selectedKeys={selected}
        onSelectionChange={setSelected}
        onAction={key => alert(`Clicked ${key}`)}
      >
        <GridListItem id="lettuce">Lettuce</GridListItem>
        <GridListItem id="tomato">Tomato</GridListItem>
        <GridListItem id="cheese">Cheese</GridListItem>
        <GridListItem id="tuna" isDisabled>Tuna Salad</GridListItem>
        <GridListItem id="egg">Egg Salad</GridListItem>
        <GridListItem id="ham">Ham</GridListItem>
      </GridList>
      <p>Current selection: {selected === 'all' ? 'all' : [...selected].join(', ')}</p>
    </div>
  );
}

Drag and drop

GridList supports drag and drop interactions when the dragAndDropHooks prop is provided using the 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.

Adobe Photoshop
Adobe XD
Adobe Dreamweaver
Adobe InDesign
Adobe Connect
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>
  );
}

API

DocumentsItemSelectioncheckboxDragbutton12 itemsOnboardingPDFBudgetXLSSales PitchPPTDragbutton