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' +};