Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions packages/dev/s2-docs/pages/react-aria/GridList.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import vanillaDocs from 'docs:vanilla-starter/GridList';
import '../../tailwind/tailwind.css';
import Anatomy from 'react-aria-components/docs/GridListAnatomy.svg';
import {InlineAlert, Heading, Content} from '@react-spectrum/s2'
import {VersionBadge} from '../../src/VersionBadge';

export const tags = ['list view'];
export const relatedPages = [
Expand Down Expand Up @@ -532,6 +533,57 @@ import {GridList} from 'vanilla-starter/GridList';
</GridList>
```

### Sections <VersionBadge version="alpha" />

Use the `<GridListSection>` component to group options. A `<GridListHeader>` element may also be included to label the section. Sections without a header must have an `aria-label`.

```tsx render
"use client";
import {GridList, GridListItem} from 'vanilla-starter/GridList';
import {GridListHeader, GridListSection, Text} from 'react-aria-components';

<GridList
layout="grid"
aria-label="Photos">
<GridListSection>
<GridListHeader>Fruit</GridListHeader>
<GridListItem textValue="Apple">
<img src="https://images.unsplash.com/photo-1630563451961-ac2ff27616ab?q=80&w=687&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" width={600} height={400} />
<Text>Apple</Text>
<Text slot="description">PNG • 9/2/2021</Text>
</GridListItem>
<GridListItem textValue="Peach">
<img src="https://images.unsplash.com/photo-1642372849486-f88b963cb734?q=80&w=2858&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" width={600} height={900} />
<Text>Peach</Text>
<Text slot="description">JPEG • 1/16/2022</Text>
</GridListItem>
<GridListItem textValue="Blueberry">
<img src="https://images.unsplash.com/photo-1606757389667-45c2024f9fa4?q=80&w=1740&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" width={600} height={900} />
<Text>Blueberry</Text>
<Text slot="description">JPEG • 11/30/2020</Text>
</GridListItem>
</GridListSection>
<GridListSection>
<GridListHeader>Vegetables</GridListHeader>
<GridListItem textValue="Broccoli">
<img src="https://images.unsplash.com/photo-1685504445355-0e7bdf90d415?q=80&w=928&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" width={600} height={900} />
<Text>Broccoli</Text>
<Text slot="description">PNG • 5/30/2023</Text>
</GridListItem>
<GridListItem textValue="Brussels Sprouts">
<img src="https://images.unsplash.com/photo-1685504507286-dc290728c01a?q=80&w=1740&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" width={600} height={900} />
<Text>Brussels Sprouts</Text>
<Text slot="description">PNG • 7/3/2021</Text>
</GridListItem>
<GridListItem textValue="Peas">
<img src="https://images.unsplash.com/photo-1587411768345-867e228218c8?q=80&w=1160&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" width={600} height={900} />
<Text>Peas</Text>
<Text slot="description">PNG • 4/20/2020</Text>
</GridListItem>
</GridListSection>
</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](selection?component=GridList) for more details.
Expand Down Expand Up @@ -931,6 +983,14 @@ function Example() {

<PropTable component={docs.exports.GridList} links={docs.links} showDescription />

### GridListSection

<PropTable component={docs.exports.GridListSection} links={docs.links} showDescription />

### GridListHeader

`<GridListHeader>` labels the section within a GridList. It accepts all HTML attributes.

### GridListItem

<PropTable component={docs.exports.GridListItem} links={docs.links} showDescription />
Expand Down
53 changes: 51 additions & 2 deletions starters/docs/src/GridList.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
@import "./theme.css";

.react-aria-GridList {
display: grid;
justify-content: center;
gap: var(--spacing-4);
padding: var(--spacing-2);
Expand All @@ -17,23 +16,42 @@
box-sizing: border-box;
--grid-item-size: 200px;

&[data-layout=grid] {
&[data-layout=grid]:not(:has(.react-aria-GridListSection)) {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(100px, var(--grid-item-size)));
grid-auto-rows: min-content;
}

&[data-layout=grid] > .react-aria-GridListSection {
grid-template-columns: repeat(auto-fit, minmax(100px, var(--grid-item-size)));
grid-auto-rows: min-content;
}

.react-aria-GridListSection:not(:first-child) {
margin-top: var(--spacing-4);
}

&[data-layout=stack] > .react-aria-GridListSection {
grid-template-columns: auto;
align-items: center;
}

&[data-size=small] {
--grid-item-size: 150px;
}

@media (width < 500px) {
&[data-layout=grid] {
--grid-item-size: 150px;
}

&[data-layout=grid]:not(:has(.react-aria-GridListSection)) {
grid-template-columns: 1fr 1fr;
}
}

&[data-layout=stack] {
display: grid;
grid-template-columns: auto;
align-items: center;
}
Expand Down Expand Up @@ -228,3 +246,34 @@
height: 24px;
width: 100%;
}

.react-aria-GridListSection {
display: grid;
justify-content: center;
gap: var(--spacing-4);
color: var(--text-color);
width: 100%;

> .react-aria-GridListHeader {
grid-column: 1 / -1;
}
}

.react-aria-GridListHeader {
position: sticky;
z-index: 2;
top: -8px;
font-size: var(--font-size-lg);
font-weight: 500;
background: var(--gray-100);
border-block: 0.5px solid var(--gray-400);
cursor: default;
user-select: none;
box-shadow: inset 0px 1px 0px white, inset 0px -4px 8px var(--gray-200);
border-radius: var(--radius);
padding: var(--spacing-1) var(--spacing-4);

@media (prefers-color-scheme: dark) {
box-shadow: inset 0px 4px 8px var(--gray-200);
}
}
53 changes: 52 additions & 1 deletion starters/docs/stories/GridList.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {GridList, GridListItem} from '../src/GridList';
import {Text} from 'react-aria-components';
import {Text, GridListSection, GridListHeader} from 'react-aria-components';

import type {Meta, StoryFn} from '@storybook/react';

Expand Down Expand Up @@ -77,3 +77,54 @@ Example.args = {
selectionMode: 'multiple',
layout: 'grid'
};


export const Sections: Story = (args) => (
<GridList
{...args}
style={{width: 800, maxWidth: 'calc(100vw - 80px)'}}
aria-label="Photos">
<GridListSection>
<GridListHeader>Fruit</GridListHeader>
<GridListItem textValue="Apple">
<img src="https://images.unsplash.com/photo-1630563451961-ac2ff27616ab?q=80&w=687&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" width={600} height={400} />
<Text>Apple</Text>
<Text slot="description">PNG • 9/2/2021</Text>
</GridListItem>
<GridListItem textValue="Peach">
<img src="https://images.unsplash.com/photo-1642372849486-f88b963cb734?q=80&w=2858&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" width={600} height={900} />
<Text>Peach</Text>
<Text slot="description">JPEG • 1/16/2022</Text>
</GridListItem>
<GridListItem textValue="Blueberry">
<img src="https://images.unsplash.com/photo-1606757389667-45c2024f9fa4?q=80&w=1740&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" width={600} height={900} />
<Text>Blueberry</Text>
<Text slot="description">JPEG • 11/30/2020</Text>
</GridListItem>
</GridListSection>
<GridListSection>
<GridListHeader>Vegetables</GridListHeader>
<GridListItem textValue="Broccoli">
<img src="https://images.unsplash.com/photo-1685504445355-0e7bdf90d415?q=80&w=928&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" width={600} height={900} />
<Text>Broccoli</Text>
<Text slot="description">PNG • 5/30/2023</Text>
</GridListItem>
<GridListItem textValue="Brussels Sprouts">
<img src="https://images.unsplash.com/photo-1685504507286-dc290728c01a?q=80&w=1740&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" width={600} height={900} />
<Text>Brussels Sprouts</Text>
<Text slot="description">PNG • 7/3/2021</Text>
</GridListItem>
<GridListItem textValue="Peas">
<img src="https://images.unsplash.com/photo-1587411768345-867e228218c8?q=80&w=1160&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" width={600} height={900} />
<Text>Peas</Text>
<Text slot="description">PNG • 4/20/2020</Text>
</GridListItem>
</GridListSection>
</GridList>
);

Sections.args = {
onAction: undefined,
selectionMode: 'multiple',
layout: 'grid'
};
9 changes: 9 additions & 0 deletions starters/tailwind/src/GridList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React from 'react';
import {
GridList as AriaGridList,
GridListItem as AriaGridListItem,
GridListHeader as AriaGridListHeader,
Button,
composeRenderProps,
GridListItemProps,
Expand All @@ -11,6 +12,8 @@ import {
import { tv } from 'tailwind-variants';
import { Checkbox } from './Checkbox';
import { composeTailwindRenderProps, focusRing } from './utils';
import {HTMLAttributes} from 'react';
import { twMerge } from 'tailwind-merge';

export function GridList<T extends object>(
{ children, ...props }: GridListProps<T>
Expand Down Expand Up @@ -53,3 +56,9 @@ export function GridListItem({ children, ...props }: GridListItemProps) {
</AriaGridListItem>
);
}

export function GridListHeader({children, ...props}: HTMLAttributes<HTMLElement>) {
return (
<AriaGridListHeader {...props} className={twMerge("text-sm font-semibold text-neutral-500 dark:text-neutral-300 px-4 py-1 -mt-px z-10 bg-neutral-100/60 dark:bg-neutral-700/60 backdrop-blur-md supports-[-moz-appearance:none]:bg-neutral-100 border-y border-y-neutral-200 dark:border-y-neutral-700", props.className)}>{children}</AriaGridListHeader>
)
}
27 changes: 26 additions & 1 deletion starters/tailwind/stories/GridList.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Meta } from '@storybook/react';
import { GridList, GridListItem } from '../src/GridList';
import { GridList, GridListHeader, GridListItem} from '../src/GridList';
import { GridListSection } from 'react-aria-components';
import React from 'react';

const meta: Meta<typeof GridList> = {
Expand Down Expand Up @@ -31,3 +32,27 @@ DisabledItems.args = {
...Example.args,
disabledKeys: ['mint']
};

export const Sections = (args: any) => (
<GridList aria-label="Food" {...args}>
<GridListSection>
<GridListHeader>Fruits</GridListHeader>
<GridListItem id="Apple">Apple</GridListItem>
<GridListItem id="Grape">Grape</GridListItem>
<GridListItem id="Peach">Peach</GridListItem>
<GridListItem id="Melon">Melon</GridListItem>
</GridListSection>
<GridListSection>
<GridListHeader>Vegetables</GridListHeader>
<GridListItem id="brocoli">Broccoli</GridListItem>
<GridListItem id="peas">Peas</GridListItem>
<GridListItem id="brussels-sprouts">Brussels Sprouts</GridListItem>
<GridListItem id="zucchini">Zucchini</GridListItem>
</GridListSection>
</GridList>
);

Sections.args = {
onAction: null,
selectionMode: 'multiple'
};
Loading