Amplify UI

Collection

Collection provides a way to display items from a data source.

Demo

Usage

Import the Collection component and provide your own repeating component as a function. Here's an example using the list collection type.

Fiordland National Park

This national park includes the famous fjords of Milford, Dusky and Doubtful Sounds.

Bay of Islands, North Island

Three hours north of Auckland, this area features over 144 islands to explore.

Queenstown, South Island

This hopping town is New Zealand's adventure capital and is located right on Lake Wakatipu.

import { Collection, Card, Heading, Text } from '@aws-amplify/ui-react';

export const DefaultCollectionExample = () => {
  return (
    <Collection
      type="list"
      items={[
        {
          title: 'Fiordland National Park',
          description:
            'This national park includes the famous fjords of Milford, Dusky and Doubtful Sounds.',
        },
        {
          title: 'Bay of Islands, North Island',
          description:
            'Three hours north of Auckland, this area features over 144 islands to explore.',
        },
        {
          title: 'Queenstown, South Island',
          description:
            "This hopping town is New Zealand's adventure capital and is located right on Lake Wakatipu.",
        },
      ]}
      gap="1.5rem"
    >
      {(item, index) => (
        <Card key={index} padding="1rem">
          <Heading level={4}>{item.title}</Heading>
          <Text>{item.description}</Text>
        </Card>
      )}
    </Collection>
  );
};

Collection types

Collection type options include list and grid.

List

The list collection type can be customized with any of following Flex props: alignItems, alignContent, direction, gap, justifyContent, wrap.

Fiordland National Park

This national park includes the famous fjords of Milford, Dusky and Doubtful Sounds.

Bay of Islands, North Island

Three hours north of Auckland, this area features over 144 islands to explore.

Queenstown, South Island

This hopping town is New Zealand's adventure capital and is located right on Lake Wakatipu.

import {
  Collection,
  Card,
  Heading,
  Text,
  useTheme,
} from '@aws-amplify/ui-react';

export const ListCollectionExample = () => {
  const { tokens } = useTheme();
  const items = [
    {
      title: 'Fiordland National Park',
      description:
        'This national park includes the famous fjords of Milford, Dusky and Doubtful Sounds.',
    },
    {
      title: 'Bay of Islands, North Island',
      description:
        'Three hours north of Auckland, this area features over 144 islands to explore.',
    },
    {
      title: 'Queenstown, South Island',
      description:
        "This hopping town is New Zealand's adventure capital and is located right on Lake Wakatipu.",
    },
  ];

  return (
    <Collection
      type="list"
      items={items}
      direction="row"
      justifyContent="space-between"
      wrap="wrap"
    >
      {(item, index) => (
        <Card
          key={index}
          padding={tokens.space.medium}
          maxWidth="180px"
          fontSize={tokens.fontSizes.xs}
        >
          <Heading level={4}>{item.title}</Heading>
          <Text>{item.description}</Text>
        </Card>
      )}
    </Collection>
  );
};

Grid

The grid collection type can be customized with the following Grid props: templateColumns and templateRows. Then the Collection children can use the Grid props to control their size and placement such as row and column.

Fiordland National Park

This national park includes the famous fjords of Milford, Dusky and Doubtful Sounds.

Bay of Islands

Three hours north of Auckland, this area features over 144 islands to explore.

Queenstown, South Island

This hopping town is New Zealand's adventure capital and is located right on Lake Wakatipu.

import {
  Collection,
  Card,
  Heading,
  Text,
  useTheme,
} from '@aws-amplify/ui-react';

export const GridCollectionExample = () => {
  const { tokens } = useTheme();
  const items = [
    {
      title: 'Fiordland National Park',
      description:
        'This national park includes the famous fjords of Milford, Dusky and Doubtful Sounds.',
    },
    {
      title: 'Bay of Islands',
      description:
        'Three hours north of Auckland, this area features over 144 islands to explore.',
    },
    {
      title: 'Queenstown, South Island',
      description:
        "This hopping town is New Zealand's adventure capital and is located right on Lake Wakatipu.",
    },
  ];

  return (
    <Collection
      type="grid"
      items={items}
      templateColumns="1fr 1fr 1fr"
      templateRows="12rem 12rem 12rem"
    >
      {(item, index) => {
        return (
          <Card
            key={index}
            padding={tokens.space.medium}
            maxWidth="180px"
            fontSize={tokens.fontSizes.xs}
            backgroundColor={tokens.colors.background.secondary}
            row={index + 1}
            column={index + 1}
          >
            <Heading level={4}>{item.title}</Heading>
            <Text>{item.description}</Text>
          </Card>
        );
      }}
    </Collection>
  );
};

Pagination

A Collection can be paginated by adding a special isPaginated property. Change the page size by passing a itemsPerPage property (default: 10).

import { Collection, Button } from '@aws-amplify/ui-react';
import { countries } from 'countries-list';

export const PaginationCollectionExample = () => {
  return (
    <Collection
      type="list"
      direction="row"
      wrap="wrap"
      items={Object.values(countries).map(({ name, emoji }) => ({
        name,
        emoji,
      }))}
      isPaginated
      itemsPerPage={12}
    >
      {(regions, index) => (
        <Button grow="1" key={index}>
          {regions.emoji} {regions.name}
        </Button>
      )}
    </Collection>
  );
};

Collections can also be filtered, adding a isSearchable property. Pass a custom searchFilter function to enhance your search experience (default search filter looks for any string-like property inside of items)

import { Collection, Button } from '@aws-amplify/ui-react';
import { countries } from 'countries-list';

export const SearchCollectionExample = () => {
  return (
    <Collection
      type="grid"
      templateColumns="1fr 1fr 1fr"
      gap="15px"
      items={Object.values(countries).map(({ name, emoji }) => ({
        name,
        emoji,
      }))}
      isSearchable
      isPaginated
      itemsPerPage={9}
      searchPlaceholder="Type to search..."
      searchFilter={(regions, keyword) =>
        (regions as any).name.toLowerCase().startsWith(keyword.toLowerCase())
      }
    >
      {(regions, index) => (
        <Button grow="1" key={index}>
          {regions.emoji} {regions.name}
        </Button>
      )}
    </Collection>
  );
};

No Results Found

To handle the case when no results are found from the search, you can pass a custom ReactNode (includes string) to the searchNoResultsFound prop. By default, Collection renders the text "No results found".

import { Collection, Button, Text, Flex } from '@aws-amplify/ui-react';
import { countries } from 'countries-list';

export const SearchNoResultsFoundCollectionExample = () => {
  return (
    <Collection
      type="grid"
      templateColumns="1fr 1fr 1fr"
      gap="15px"
      items={Object.values(countries).map(({ name, emoji }) => ({
        name,
        emoji,
      }))}
      isSearchable
      isPaginated
      itemsPerPage={9}
      searchNoResultsFound={
        <Flex justifyContent="center">
          <Text color="purple.80" fontSize="1rem">
            Nothing found, please try again
          </Text>
        </Flex>
      }
      searchPlaceholder="Type to search..."
      searchFilter={(regions, keyword) =>
        (regions as any).name.toLowerCase().startsWith(keyword.toLowerCase())
      }
    >
      {(regions, index) => (
        <Button grow="1" key={index}>
          {regions.emoji} {regions.name}
        </Button>
      )}
    </Collection>
  );
};

Customization

Theme

You can customize the appearance of all Collection components in your application with a Theme.

Collection Theme Source

import {
  Button,
  Collection,
  ThemeProvider,
  Theme,
} from '@aws-amplify/ui-react';
import { countries } from 'countries-list';

const theme: Theme = {
  name: 'collection-theme',
  tokens: {
    components: {
      collection: {
        pagination: {
          current: {
            color: { value: 'white' },
            backgroundColor: {
              value: '{colors.blue.80}',
            },
          },
          button: {
            color: { value: '{colors.blue.60}' },
            _hover: {
              backgroundColor: {
                value: '{colors.blue.10}',
              },
              color: { value: '{colors.blue.60}' },
            },
          },
        },
        search: {
          input: {
            color: { value: '{colors.blue.60}' },
          },
          button: {
            color: { value: '{colors.blue.60}' },
            _focus: {
              backgroundColor: {
                value: '{colors.blue.60}',
              },
              color: {
                value: 'white',
              },
            },
            _hover: {
              backgroundColor: {
                value: '{colors.blue.80}',
              },
              color: {
                value: 'white',
              },
            },
          },
        },
      },
    },
  },
};

export const CollectionThemeExample = () => {
  return (
    <ThemeProvider theme={theme} colorMode="light">
      <Collection
        type="grid"
        templateColumns="1fr 1fr 1fr"
        gap="15px"
        items={Object.values(countries).map(({ name, emoji }) => ({
          name,
          emoji,
        }))}
        isSearchable
        isPaginated
        itemsPerPage={9}
        searchPlaceholder="Type to search..."
        searchFilter={(regions, keyword) =>
          (regions as any).name.toLowerCase().startsWith(keyword.toLowerCase())
        }
      >
        {(regions, index) => (
          <Button grow="1" key={index}>
            {regions.emoji} {regions.name}
          </Button>
        )}
      </Collection>
    </ThemeProvider>
  );
};

Target classes

ClassDescription
amplify-collectionTop level element that wraps the Collection primitive
amplify-collection-itemsClass applied to the element that wraps all the items in a collection
amplify-collection-searchClass applied to the element that wraps the collection search box
amplify-collection-paginationClass applied to the element that wraps the pagination component in a collection
  • --amplify-components-collection-pagination-button-color
  • --amplify-components-collection-pagination-button-disabled-color
  • --amplify-components-collection-pagination-button-hover-background-color
  • --amplify-components-collection-pagination-button-hover-color
  • --amplify-components-collection-pagination-current-background-color
  • --amplify-components-collection-pagination-current-color
  • --amplify-components-collection-search-button-active-background-color
  • --amplify-components-collection-search-button-active-border-color
  • --amplify-components-collection-search-button-active-color
  • --amplify-components-collection-search-button-color
  • --amplify-components-collection-search-button-disabled-background-color
  • --amplify-components-collection-search-button-disabled-border-color
  • --amplify-components-collection-search-button-disabled-color
  • --amplify-components-collection-search-button-focus-background-color
  • --amplify-components-collection-search-button-focus-border-color
  • --amplify-components-collection-search-button-focus-color
  • --amplify-components-collection-search-button-hover-background-color
  • --amplify-components-collection-search-button-hover-border-color
  • --amplify-components-collection-search-button-hover-color
  • --amplify-components-collection-search-input-color

Global Styling

To override the styling on all Collections you can use the built in .amplify-collection class.

.amplify-collection {
  --amplify-components-collection-pagination-current-color: var(
    --amplify-colors-secondary-20
  );
  --amplify-components-collection-pagination-current-background-color: var(
    --amplify-colors-teal-80
  );
}

Local Styling

To override styling on a specific Collection, you can use a class selector or style props.

Using a class selector:

import { Collection, Button } from '@aws-amplify/ui-react';
import { countries } from 'countries-list';

export const LocalCollectionClassExample = () => {
  const items = Object.values(countries)
    .map(({ name, emoji }) => ({
      name,
      emoji,
    }))
    .splice(0, 20);
  return (
    <Collection
      type="list"
      className="collection-local-styling-example"
      direction="row"
      items={items}
    >
      {(regions, index) => (
        <Button grow="1" key={index}>
          {regions.emoji}
        </Button>
      )}
    </Collection>
  );
};
.collection-local-styling-example {
  flex-wrap: wrap;
  gap: 20px;
  padding: 5px;
}

.collection-local-styling-example .amplify-collection-items {
  flex-wrap: wrap;
  gap: 20px;
}

.collection-local-styling-example .amplify-button {
  background-color: var(--amplify-colors-neutral-60);
}

Using style props:

import { Collection, Button, useTheme } from '@aws-amplify/ui-react';
import { countries } from 'countries-list';

export const CollectionStylePropExample = () => {
  const { tokens } = useTheme();
  const items = Object.values(countries)
    .map(({ name, emoji }) => ({
      name,
      emoji,
    }))
    .splice(0, 20);
  return (
    <Collection
      type="list"
      border={`${tokens.borderWidths.medium} solid ${tokens.colors.red[60]}`}
      direction="row"
      wrap="wrap"
      padding="5px"
      gap="20px"
      items={items}
    >
      {(regions, index) => (
        <Button grow="1" key={index}>
          {regions.emoji}
        </Button>
      )}
    </Collection>
  );
};

Amplify open source software, documentation and community are supported by Amazon Web Services.

© 2024 Amazon Web Services, Inc. and its affiliates. All rights reserved. View the site terms and privacy policy.

Flutter and the related logo are trademarks of Google LLC. We are not endorsed by or affiliated with Google LLC.