Back to React Spectrum

Image Grid

packages/react-aria-components/docs/examples/image-grid.mdx

2022-12-165.3 KB
Original Source

{/* Copyright 2023 Adobe. All rights reserved. This file is licensed to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */}

import {ExampleLayout} from '@react-spectrum/docs'; export default ExampleLayout;

import docs from 'docs:react-aria-components'; import {TypeLink} from '@react-spectrum/docs'; import styles from '@react-spectrum/docs/src/docs.css'; import ListBox from '@react-spectrum/docs/pages/assets/component-illustrations/ListBox.svg'; import ProgressCircle from '@react-spectrum/docs/pages/assets/component-illustrations/ProgressCircle.svg'; import {ExampleCard} from '@react-spectrum/docs/src/ExampleCard'; import ChevronRight from '@spectrum-icons/workflow/ChevronRight';


Image Grid

An async-loaded image gallery with selectable items built with the ListBox component, and styled with Tailwind CSS.

Example

tsx
import './tailwind.global.css';
tsx
import {ListBox, ListBoxItem, Text, ProgressBar} from 'react-aria-components';
import {useAsyncList} from 'react-stately';
import {CheckCircle2} from 'lucide-react';

type Item = {
  user: { name: string },
  urls: { regular: string },
  alt_description: string
};

function ImageGridExample() {
  let list = useAsyncList<Item, number>({
    async load({ signal, cursor }) {
      let page = cursor || 1;
      let res = await fetch(
        `https://api.unsplash.com/photos?page=${page}&per_page=25&client_id=AJuU-FPh11hn7RuumUllp4ppT8kgiLS7LtOHp_sp4nc`,
        { signal }
      );
      let items = await res.json();
      return { items, cursor: page + 1 };
    }
  });

  let renderEmptyState = () => {
    if (list.isLoading) {
      return <ProgressCircle />;
    }
  };

  return (
    <div className="bg-linear-to-r from-sky-500 to-teal-500 p-2 sm:p-8 rounded-lg flex justify-center">
      <ListBox aria-label="Images" items={list.items} selectionMode="multiple" layout="grid" renderEmptyState={renderEmptyState} className="overflow-auto outline-hidden bg-white rounded-lg shadow-sm p-2 h-[350px] w-full max-w-[372px] grid grid-cols-3 gap-3 empty:flex">
        {item => (
          <ListBoxItem textValue={item.user.name} className="relative rounded-sm outline-hidden group cursor-default">
            
            <Text slot="label" className="text-[11px] text-gray-700 font-semibold overflow-hidden text-ellipsis whitespace-nowrap max-w-full block mt-1">{item.user.name}</Text>
            <div className="absolute top-2 left-2 text-sky-800 rounded-full leading-0 bg-white border border-white border-solid hidden group-selected:block">
              <CheckCircle2 className="h-6 w-6" />
            </div>
          </ListBoxItem>
        )}
      </ListBox>
    </div>
  );
}

function ProgressCircle() {
  return (
    <ProgressBar aria-label="Loading…" isIndeterminate className="flex items-center justify-center w-full">
      <svg className="animate-spin h-5 w-5 text-sky-800" fill="none" viewBox="0 0 24 24">
        <circle className="opacity-25 stroke-current stroke-[4px]" cx="12" cy="12" r="10" />
        <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
      </svg>
    </ProgressBar>
  );
}

Tailwind config

This example uses the tailwindcss-react-aria-components plugin. When using Tailwind v4, add it to your CSS:

css
@import "tailwindcss";
@plugin "tailwindcss-react-aria-components";
<details> <summary style={{fontWeight: 'bold'}}><ChevronRight size="S" /> Tailwind v3</summary>

When using Tailwind v3, add the plugin to your tailwind.config.js instead:

tsx
module.exports = {
  // ...
  plugins: [
    require('tailwindcss-react-aria-components')
  ]
};

Note: When using Tailwind v3, install tailwindcss-react-aria-components version 1.x instead of 2.x.

</details>

Components

<section className={styles.cardGroup} data-size="small">

<ExampleCard url="../ListBox.html" title="ListBox" description="A listbox displays a list of options, and allows a user to select one or more of them."> <ListBox style={{background: 'var(--anatomy-gray-100)', width: 'calc(100% - 20px)', padding: 10, maxHeight: 132}} /> </ExampleCard>

<ExampleCard url="../ProgressBar.html" title="ProgressBar" description="A progress bar shows progress of an operation over time."> <ProgressCircle /> </ExampleCard>

</section>