diff --git a/packages/dev/s2-docs/pages/react-aria/GridList.mdx b/packages/dev/s2-docs/pages/react-aria/GridList.mdx
index 0e8ea1f2325..7dad11de248 100644
--- a/packages/dev/s2-docs/pages/react-aria/GridList.mdx
+++ b/packages/dev/s2-docs/pages/react-aria/GridList.mdx
@@ -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 = [
@@ -532,6 +533,57 @@ import {GridList} from 'vanilla-starter/GridList';
```
+### Sections
+
+Use the `` component to group options. A `` 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';
+
+
+
+ Fruit
+
+
+ Apple
+ PNG • 9/2/2021
+
+
+
+ Peach
+ JPEG • 1/16/2022
+
+
+
+ Blueberry
+ JPEG • 11/30/2020
+
+
+
+ Vegetables
+
+
+ Broccoli
+ PNG • 5/30/2023
+
+
+
+ Brussels Sprouts
+ PNG • 7/3/2021
+
+
+
+ Peas
+ PNG • 4/20/2020
+
+
+
+```
+
## 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.
@@ -931,6 +983,14 @@ function Example() {
+### GridListSection
+
+
+
+### GridListHeader
+
+`` labels the section within a GridList. It accepts all HTML attributes.
+
### GridListItem
diff --git a/starters/docs/src/GridList.css b/starters/docs/src/GridList.css
index bc07c1a43c1..91d8f407e79 100644
--- a/starters/docs/src/GridList.css
+++ b/starters/docs/src/GridList.css
@@ -1,7 +1,6 @@
@import "./theme.css";
.react-aria-GridList {
- display: grid;
justify-content: center;
gap: var(--spacing-4);
padding: var(--spacing-2);
@@ -17,11 +16,26 @@
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;
}
@@ -29,11 +43,15 @@
@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;
}
@@ -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);
+ }
+}
diff --git a/starters/docs/stories/GridList.stories.tsx b/starters/docs/stories/GridList.stories.tsx
index 5daa48af8c4..84666d0a489 100644
--- a/starters/docs/stories/GridList.stories.tsx
+++ b/starters/docs/stories/GridList.stories.tsx
@@ -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';
@@ -77,3 +77,54 @@ Example.args = {
selectionMode: 'multiple',
layout: 'grid'
};
+
+
+export const Sections: Story = (args) => (
+
+
+ Fruit
+
+
+ Apple
+ PNG • 9/2/2021
+
+
+
+ Peach
+ JPEG • 1/16/2022
+
+
+
+ Blueberry
+ JPEG • 11/30/2020
+
+
+
+ Vegetables
+
+
+ Broccoli
+ PNG • 5/30/2023
+
+
+
+ Brussels Sprouts
+ PNG • 7/3/2021
+
+
+
+ Peas
+ PNG • 4/20/2020
+
+
+
+);
+
+Sections.args = {
+ onAction: undefined,
+ selectionMode: 'multiple',
+ layout: 'grid'
+};
diff --git a/starters/tailwind/src/GridList.tsx b/starters/tailwind/src/GridList.tsx
index 436ecee7abd..e80c9d345ed 100644
--- a/starters/tailwind/src/GridList.tsx
+++ b/starters/tailwind/src/GridList.tsx
@@ -3,6 +3,7 @@ import React from 'react';
import {
GridList as AriaGridList,
GridListItem as AriaGridListItem,
+ GridListHeader as AriaGridListHeader,
Button,
composeRenderProps,
GridListItemProps,
@@ -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(
{ children, ...props }: GridListProps
@@ -53,3 +56,9 @@ export function GridListItem({ children, ...props }: GridListItemProps) {
);
}
+
+export function GridListHeader({children, ...props}: HTMLAttributes) {
+ return (
+ {children}
+ )
+}
diff --git a/starters/tailwind/stories/GridList.stories.tsx b/starters/tailwind/stories/GridList.stories.tsx
index f07dc992c38..fbb287b1702 100644
--- a/starters/tailwind/stories/GridList.stories.tsx
+++ b/starters/tailwind/stories/GridList.stories.tsx
@@ -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 = {
@@ -31,3 +32,27 @@ DisabledItems.args = {
...Example.args,
disabledKeys: ['mint']
};
+
+export const Sections = (args: any) => (
+
+
+ Fruits
+ Apple
+ Grape
+ Peach
+ Melon
+
+
+ Vegetables
+ Broccoli
+ Peas
+ Brussels Sprouts
+ Zucchini
+
+
+);
+
+Sections.args = {
+ onAction: null,
+ selectionMode: 'multiple'
+};