From 7d3f499acc6623f37ba561e6404320f7aae45991 Mon Sep 17 00:00:00 2001 From: chirokas <157580465+chirokas@users.noreply.github.com> Date: Mon, 20 Oct 2025 23:12:37 +0800 Subject: [PATCH 1/6] fix: remove obsolete textarea validation workaround (#9019) --- .../@react-aria/textfield/src/useTextField.ts | 21 +------------ .../test/TextField.test.js | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/packages/@react-aria/textfield/src/useTextField.ts b/packages/@react-aria/textfield/src/useTextField.ts index e232514d052..18f2942a90c 100644 --- a/packages/@react-aria/textfield/src/useTextField.ts +++ b/packages/@react-aria/textfield/src/useTextField.ts @@ -12,14 +12,13 @@ import {AriaTextFieldProps} from '@react-types/textfield'; import {DOMAttributes, ValidationResult} from '@react-types/shared'; -import {filterDOMProps, getOwnerWindow, mergeProps, useFormReset} from '@react-aria/utils'; +import {filterDOMProps, mergeProps, useFormReset} from '@react-aria/utils'; import React, { ChangeEvent, HTMLAttributes, type JSX, LabelHTMLAttributes, RefObject, - useEffect, useState } from 'react'; import {useControlledState} from '@react-stately/utils'; @@ -147,24 +146,6 @@ export function useTextField { - // This works around a React/Chrome bug that prevents textarea elements from validating when controlled. - // We prevent React from updating defaultValue (i.e. children) of textarea when `value` changes, - // which causes Chrome to skip validation. Only updating `value` is ok in our case since our - // textareas are always controlled. React is planning on removing this synchronization in a - // future major version. - // https://github.com/facebook/react/issues/19474 - // https://github.com/facebook/react/issues/11896 - if (ref.current instanceof getOwnerWindow(ref.current).HTMLTextAreaElement) { - let input = ref.current; - Object.defineProperty(input, 'defaultValue', { - get: () => input.value, - set: () => {}, - configurable: true - }); - } - }, [ref]); - return { labelProps, inputProps: mergeProps( diff --git a/packages/react-aria-components/test/TextField.test.js b/packages/react-aria-components/test/TextField.test.js index a5d354ee4c7..b89e35f82b1 100644 --- a/packages/react-aria-components/test/TextField.test.js +++ b/packages/react-aria-components/test/TextField.test.js @@ -266,5 +266,35 @@ describe('TextField', () => { let input = getByRole('textbox'); expect(input).toHaveAttribute('form', 'test'); }); + + if (parseInt(React.version, 10) >= 19) { + it('resets to defaultValue when submitting form action', async () => { + const Component = component; + function Test() { + const [value, formAction] = React.useActionState((_, formData) => formData.get('value'), 'initial'); + + return ( +
+ + + + + +
+ ); + } + + const {getByTestId} = render(); + const input = getByTestId('input'); + expect(input).toHaveValue('initial'); + + await user.tab(); + await user.keyboard('Devon'); + + const button = getByTestId('submit'); + await user.click(button); + expect(input).toHaveValue('Devon'); + }); + } }); }); From 4b8c6eb326ddb9461c4fdab8fc9d97f69e4ed635 Mon Sep 17 00:00:00 2001 From: Yihui Liao <44729383+yihuiliao@users.noreply.github.com> Date: Mon, 20 Oct 2025 09:56:23 -0700 Subject: [PATCH 2/6] chore: add cursor rule for release notes (#9033) * chore: add cursor rule for release notes * update cursor rules * add space --- .cursor/rules/add-subheadings.mdc | 22 +++++++++++++++ .cursor/rules/categorize-commits.mdc | 36 ++++++++++++++++++++++++ .cursor/rules/rewrite-commit-message.mdc | 27 ++++++++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 .cursor/rules/add-subheadings.mdc create mode 100644 .cursor/rules/categorize-commits.mdc create mode 100644 .cursor/rules/rewrite-commit-message.mdc diff --git a/.cursor/rules/add-subheadings.mdc b/.cursor/rules/add-subheadings.mdc new file mode 100644 index 00000000000..d723ca3dfd5 --- /dev/null +++ b/.cursor/rules/add-subheadings.mdc @@ -0,0 +1,22 @@ +--- +alwaysApply: false +--- + +# Step 3: Add sub-headings + +Within the Enhancements, Fixes, and Under Construction categories, group commits by UI component under sub-headings. + +### Sub-heading rules: +- Use sub-headings ONLY for: + - Enhancements + - Fixes + - Under Construction +- Do NOT create sub-headings for: + - Documentation + - To Be Categorized + - S2 +- Sub-headings should be in alphabetical order +- Use "Miscellaneous" as a sub-heading for commits that do not belong to a specific component +- Each category can have its own Miscellaneous sub-heading +- Write sub-headings and commits as unordered lists using a hyphen (-) +- Do NOT bold the sub-heading text diff --git a/.cursor/rules/categorize-commits.mdc b/.cursor/rules/categorize-commits.mdc new file mode 100644 index 00000000000..466190cfadf --- /dev/null +++ b/.cursor/rules/categorize-commits.mdc @@ -0,0 +1,36 @@ +--- +alwaysApply: false +--- + +# Step 1: Categorize commits + +Sort ALL commit messages into one of six main categories. The main categories are the following: +- Enhancements +- Fixes +- Documentation +- Under Construction +- To Be Categorized +- S2 + +Before categorizing commits into other groups, check whether each commit should be classified as “Under Construction.” +- Follow the steps below in order: + 1. Identify pre-release packages + - Use a command such as grep to scan the repository for package versions that include prerelease identifiers (e.g., alpha, beta, rc) + 2. Extract component keywords from commit messages + - Parse each commit message to identify possible component names + - Normalize these keywords (e.g., lowercase, remove punctuation) for easier comparison. + 3. Compare extracted keywords with pre-release packages + - If any keyword matches a package in the list, mark the commit as Under Construction. + 4. Check for explicit prerelease keywords in commit text + - If the commit message directly includes alpha, beta, or rc, classify it as Under Construction, regardless of package matches. + +Next, categorize the remaining commits not categorized as "Under Construction". Use the following keywords to determine the category: +| Keyword | Category | +|----------------------------|----------| +| feat | Enhancements| +| fix | Fixes | +| docs | Documentation | +| chore, revert, bump, build | To Be Categorized | +| S2 | S2 | + +Do not duplicate commits. In terms of priority, it should be Under Construction > S2 > To Be Categorized > Enhancements > Fixes > Documentation diff --git a/.cursor/rules/rewrite-commit-message.mdc b/.cursor/rules/rewrite-commit-message.mdc new file mode 100644 index 00000000000..a2d68af8858 --- /dev/null +++ b/.cursor/rules/rewrite-commit-message.mdc @@ -0,0 +1,27 @@ +--- +alwaysApply: false +--- + +You are a expert technical writer for front-end development. + +# Step 2: Rewrite commit messages + +Original format: Type (Scope): Summary of changes - [@username](link to username) - [PR](link to PR) +New Format: Summary of changes - [@username](link to username) - [PR](link to PR) + +### General Guidelines: +- Keep the summary as a single, grammatically correct sentence +- Verbs should be first person present tense but do NOT include the subject (e.g. I) +- The message should be concise and easy to read +- Wrap any camelCase or code-like terms (e.g. onClick, onAction, isDisabled) in backticks (``) + - Do NOT use backticks for component names +- Replace specific terms: + - RAC -> React Aria + - V3 -> React Spectrum +- ALWAYS capitalize UI component names + - Example: + - toast -> Toast + - inline alert -> InlineAlert + +### Component Names to Capitalize: +Accordion, Autocomplete, Badge, Breadcrumbs, Buttons, Calendar, Checkbox, CheckboxGroup, Collections, ColorArea, ColorField, ColorPicker, ColorSlider, ColorSwatch, ColorSwatchPicker, ColorWheel, ComboBox, Date and Time, DateField, DatePicker, DateRangePicker, Dialog, Disclosure, DisclosureGroup, Drag and Drop, DropZone, FileTrigger, Form, InlineAlert, Link, Listbox, ListView, Menu, Meter, Modal, NotificationBadge, NumberField, Picker, ProgressBar, ProgressCircle, RadioGroup, RangeCalendar, SearchField, Select, Slider, StatusLight, Switch, Table, Tabs, TagGroup, TextArea, TextField, TimeField, Toast, ToggleButton, ToggleButtonGroup, Tooltip, Tree, Virtualizer. From 25b305bb52eed3b6709000a8ea8a4db75aab9882 Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Mon, 20 Oct 2025 09:57:24 -0700 Subject: [PATCH 3/6] docs: Update React Aria example styling (#9049) * Add isPressed to table column header render props * docs: Update React Aria example styling * fix * lint * Fixes and improvements * fix ts and test * fix disclosure * more fixes --- .../disclosure/src/useDisclosure.ts | 4 +- .../disclosure/test/useDisclosure.test.ts | 6 +- .../table/src/useTableColumnHeader.ts | 9 +- .../docs/pages/react-aria/home/ExampleApp.tsx | 14 +- .../dev/s2-docs/pages/react-aria/Button.mdx | 9 +- .../dev/s2-docs/pages/react-aria/Calendar.mdx | 31 +- .../dev/s2-docs/pages/react-aria/Checkbox.mdx | 2 +- .../pages/react-aria/CheckboxGroup.mdx | 2 +- .../s2-docs/pages/react-aria/ColorField.mdx | 9 +- .../dev/s2-docs/pages/react-aria/ComboBox.mdx | 30 +- .../s2-docs/pages/react-aria/DateField.mdx | 2 +- .../s2-docs/pages/react-aria/DatePicker.mdx | 2 +- .../pages/react-aria/DateRangePicker.mdx | 2 +- .../s2-docs/pages/react-aria/Disclosure.mdx | 4 +- .../dev/s2-docs/pages/react-aria/Form.mdx | 26 +- .../dev/s2-docs/pages/react-aria/GridList.mdx | 798 ++++++++++++++++-- .../dev/s2-docs/pages/react-aria/ListBox.mdx | 61 +- .../dev/s2-docs/pages/react-aria/Menu.mdx | 140 ++- .../dev/s2-docs/pages/react-aria/Modal.mdx | 28 +- .../pages/react-aria/MonthDropdown.tsx | 2 +- .../s2-docs/pages/react-aria/NumberField.mdx | 2 +- .../pages/react-aria/PokemonGridList.tsx | 10 +- .../dev/s2-docs/pages/react-aria/Popover.mdx | 23 +- .../s2-docs/pages/react-aria/RadioGroup.mdx | 2 +- .../pages/react-aria/RangeCalendar.mdx | 31 +- .../s2-docs/pages/react-aria/SearchField.mdx | 8 +- .../dev/s2-docs/pages/react-aria/Select.mdx | 39 +- .../pages/react-aria/SelectionIndicator.css | 4 +- .../dev/s2-docs/pages/react-aria/Switch.mdx | 2 +- .../dev/s2-docs/pages/react-aria/Table.mdx | 81 +- .../s2-docs/pages/react-aria/TextField.mdx | 12 +- .../s2-docs/pages/react-aria/TimeField.mdx | 2 +- .../pages/react-aria/ToggleButtonGroup.mdx | 11 +- .../dev/s2-docs/pages/react-aria/Toolbar.mdx | 2 +- .../dev/s2-docs/pages/react-aria/Tooltip.mdx | 2 +- .../dev/s2-docs/pages/react-aria/Tree.mdx | 17 +- .../s2-docs/pages/react-aria/Virtualizer.mdx | 36 +- .../s2-docs/pages/react-aria/YearDropdown.tsx | 2 +- packages/dev/s2-docs/pages/react-aria/dnd.mdx | 48 +- .../s2-docs/pages/react-aria/selection.mdx | 191 +++-- packages/dev/s2-docs/pages/s2/ColorField.mdx | 2 +- packages/dev/s2-docs/pages/s2/ComboBox.mdx | 4 +- packages/dev/s2-docs/src/ExampleOutput.tsx | 5 +- packages/dev/s2-docs/src/ExampleSwitcher.tsx | 93 +- packages/dev/s2-docs/tailwind/tailwind.css | 11 + packages/react-aria-components/src/Table.tsx | 15 +- starters/docs/src/Autocomplete.css | 29 +- starters/docs/src/Breadcrumbs.css | 18 +- starters/docs/src/Breadcrumbs.tsx | 2 +- starters/docs/src/Button.css | 45 +- starters/docs/src/Button.tsx | 12 +- starters/docs/src/Calendar.css | 52 +- starters/docs/src/Calendar.tsx | 13 +- starters/docs/src/Checkbox.css | 71 +- starters/docs/src/Checkbox.tsx | 8 +- starters/docs/src/CheckboxGroup.css | 16 +- starters/docs/src/CheckboxGroup.tsx | 20 +- starters/docs/src/ColorArea.css | 2 +- starters/docs/src/ColorField.css | 37 +- starters/docs/src/ColorField.tsx | 6 +- starters/docs/src/ColorPicker.css | 15 +- starters/docs/src/ColorPicker.tsx | 2 +- starters/docs/src/ColorSlider.css | 11 +- starters/docs/src/ColorSwatch.css | 8 +- starters/docs/src/ColorSwatchPicker.css | 3 +- starters/docs/src/ColorThumb.css | 8 +- starters/docs/src/ComboBox.css | 86 +- starters/docs/src/ComboBox.tsx | 39 +- starters/docs/src/DateField.css | 40 +- starters/docs/src/DateField.tsx | 24 +- starters/docs/src/DatePicker.css | 26 +- starters/docs/src/DatePicker.tsx | 36 +- starters/docs/src/DateRangePicker.css | 47 +- starters/docs/src/DateRangePicker.tsx | 44 +- starters/docs/src/Dialog.css | 4 +- starters/docs/src/Disclosure.css | 45 +- starters/docs/src/Disclosure.tsx | 6 +- starters/docs/src/DisclosureGroup.css | 2 +- starters/docs/src/DropZone.css | 2 +- starters/docs/src/Form.css | 66 +- starters/docs/src/Form.tsx | 8 +- starters/docs/src/GridList.css | 288 ++++--- starters/docs/src/GridList.tsx | 17 +- starters/docs/src/InputGroup.css | 24 +- starters/docs/src/InputGroup.tsx | 5 +- starters/docs/src/Link.css | 16 +- starters/docs/src/ListBox.css | 372 +++++--- starters/docs/src/ListBox.tsx | 36 +- starters/docs/src/Menu.css | 193 +++-- starters/docs/src/Menu.tsx | 16 +- starters/docs/src/Meter.css | 29 +- starters/docs/src/Meter.tsx | 9 +- starters/docs/src/Modal.css | 13 +- starters/docs/src/NumberField.css | 79 +- starters/docs/src/NumberField.tsx | 13 +- starters/docs/src/Popover.css | 28 +- starters/docs/src/Popover.tsx | 18 +- starters/docs/src/ProgressBar.css | 77 +- starters/docs/src/ProgressBar.tsx | 4 +- starters/docs/src/ProgressCircle.tsx | 2 +- starters/docs/src/RadioGroup.css | 89 +- starters/docs/src/RadioGroup.tsx | 36 +- starters/docs/src/RangeCalendar.css | 94 ++- starters/docs/src/RangeCalendar.tsx | 31 +- starters/docs/src/SearchField.css | 91 +- starters/docs/src/SearchField.tsx | 12 +- .../docs/src}/SegmentedControl.css | 27 +- starters/docs/src/SegmentedControl.tsx | 18 + starters/docs/src/Select.css | 103 +-- starters/docs/src/Select.tsx | 16 +- starters/docs/src/Sheet.css | 2 +- starters/docs/src/Slider.css | 94 ++- starters/docs/src/Slider.tsx | 16 +- starters/docs/src/Switch.css | 75 +- starters/docs/src/Switch.tsx | 12 +- starters/docs/src/Table.css | 373 ++++---- starters/docs/src/Table.tsx | 59 +- starters/docs/src/Tabs.css | 45 +- starters/docs/src/TagGroup.css | 107 +-- starters/docs/src/TagGroup.tsx | 8 +- starters/docs/src/TextField.css | 61 +- starters/docs/src/TextField.tsx | 18 +- starters/docs/src/TimeField.css | 10 - starters/docs/src/TimeField.tsx | 22 +- starters/docs/src/ToggleButton.css | 50 +- starters/docs/src/ToggleButton.tsx | 18 +- starters/docs/src/ToggleButtonGroup.css | 29 +- starters/docs/src/Toolbar.css | 8 +- starters/docs/src/Tooltip.css | 17 +- starters/docs/src/Tree.css | 240 +++--- starters/docs/src/Tree.tsx | 67 +- starters/docs/src/theme.css | 244 ++++-- starters/docs/src/utilities.css | 277 ++++++ starters/docs/stories/Breadcrumbs.stories.tsx | 12 +- starters/docs/stories/TextField.stories.tsx | 5 +- starters/tailwind/src/Button.tsx | 9 +- starters/tailwind/src/Calendar.tsx | 16 +- starters/tailwind/src/Checkbox.tsx | 10 +- starters/tailwind/src/ColorField.tsx | 4 +- starters/tailwind/src/ColorPicker.tsx | 2 +- starters/tailwind/src/ColorSlider.tsx | 2 +- starters/tailwind/src/ColorSwatch.tsx | 2 +- starters/tailwind/src/ColorSwatchPicker.tsx | 2 +- starters/tailwind/src/ComboBox.tsx | 8 +- starters/tailwind/src/DateField.tsx | 2 +- starters/tailwind/src/DatePicker.tsx | 8 +- starters/tailwind/src/DateRangePicker.tsx | 8 +- starters/tailwind/src/Disclosure.tsx | 4 +- starters/tailwind/src/DropZone.tsx | 2 +- starters/tailwind/src/Field.tsx | 2 +- starters/tailwind/src/FieldButton.tsx | 34 + starters/tailwind/src/GridList.tsx | 9 +- starters/tailwind/src/ListBox.tsx | 4 +- starters/tailwind/src/Menu.tsx | 46 +- starters/tailwind/src/Meter.tsx | 2 +- starters/tailwind/src/NumberField.tsx | 4 +- starters/tailwind/src/Popover.tsx | 3 - starters/tailwind/src/ProgressBar.tsx | 2 +- starters/tailwind/src/RadioGroup.tsx | 10 +- starters/tailwind/src/RangeCalendar.tsx | 6 +- starters/tailwind/src/SearchField.tsx | 8 +- starters/tailwind/src/Select.tsx | 6 +- starters/tailwind/src/Slider.tsx | 8 +- starters/tailwind/src/Switch.tsx | 2 +- starters/tailwind/src/Table.tsx | 18 +- starters/tailwind/src/Tabs.tsx | 2 +- starters/tailwind/src/TagGroup.tsx | 10 +- starters/tailwind/src/TextField.tsx | 4 +- starters/tailwind/src/TimeField.tsx | 3 +- starters/tailwind/src/ToggleButton.tsx | 4 +- starters/tailwind/src/Toolbar.tsx | 2 +- starters/tailwind/src/Tooltip.tsx | 4 +- starters/tailwind/src/Tree.tsx | 2 +- starters/tailwind/stories/Popover.stories.tsx | 2 +- 174 files changed, 4063 insertions(+), 2527 deletions(-) rename {packages/dev/s2-docs/pages/react-aria => starters/docs/src}/SegmentedControl.css (63%) create mode 100644 starters/docs/src/SegmentedControl.tsx create mode 100644 starters/docs/src/utilities.css create mode 100644 starters/tailwind/src/FieldButton.tsx diff --git a/packages/@react-aria/disclosure/src/useDisclosure.ts b/packages/@react-aria/disclosure/src/useDisclosure.ts index ab55538a91f..34b254afce6 100644 --- a/packages/@react-aria/disclosure/src/useDisclosure.ts +++ b/packages/@react-aria/disclosure/src/useDisclosure.ts @@ -73,7 +73,7 @@ export function useDisclosure(props: AriaDisclosureProps, state: DisclosureState if (raf.current) { cancelAnimationFrame(raf.current); } - if (ref.current && !isDisabled && !isSSR) { + if (ref.current && !isSSR) { let panel = ref.current; if (isExpandedRef.current == null || typeof panel.getAnimations !== 'function') { @@ -155,7 +155,7 @@ export function useDisclosure(props: AriaDisclosureProps, state: DisclosureState role: 'group', 'aria-labelledby': triggerId, 'aria-hidden': !state.isExpanded, - hidden: !state.isExpanded || undefined + hidden: isSSR ? !state.isExpanded : undefined } }; } diff --git a/packages/@react-aria/disclosure/test/useDisclosure.test.ts b/packages/@react-aria/disclosure/test/useDisclosure.test.ts index b3bcf38ffe5..9f2932acc93 100644 --- a/packages/@react-aria/disclosure/test/useDisclosure.test.ts +++ b/packages/@react-aria/disclosure/test/useDisclosure.test.ts @@ -91,7 +91,7 @@ describe('useDisclosure', () => { }); it('should keep panel hidden when toggling disabled state', () => { - let {result, rerender} = renderHook(({isDisabled}: {isDisabled: boolean}) => { + let {rerender} = renderHook(({isDisabled}: {isDisabled: boolean}) => { let state = useDisclosureState({}); return useDisclosure({isDisabled}, state, ref); }, {initialProps: {isDisabled: false}}); @@ -100,13 +100,13 @@ describe('useDisclosure', () => { rerender({isDisabled: true}); }); - expect(result.current.panelProps.hidden).toBe(true); + expect(ref.current.hidden).toBe(true); act(() => { rerender({isDisabled: false}); }); - expect(result.current.panelProps.hidden).toBe(true); + expect(ref.current.hidden).toBe(true); }); it('should set correct IDs for accessibility', () => { diff --git a/packages/@react-aria/table/src/useTableColumnHeader.ts b/packages/@react-aria/table/src/useTableColumnHeader.ts index b352ff98c22..e6ac331c1cd 100644 --- a/packages/@react-aria/table/src/useTableColumnHeader.ts +++ b/packages/@react-aria/table/src/useTableColumnHeader.ts @@ -31,7 +31,9 @@ export interface AriaTableColumnHeaderProps { export interface TableColumnHeaderAria { /** Props for the [column header](https://www.w3.org/TR/wai-aria-1.1/#columnheader) element. */ - columnHeaderProps: DOMAttributes + columnHeaderProps: DOMAttributes, + /** Whether the column is currently in a pressed state. */ + isPressed: boolean } /** @@ -48,7 +50,7 @@ export function useTableColumnHeader(props: AriaTableColumnHeaderProps, st let isSelectionCellDisabled = node.props.isSelectionCell && state.selectionManager.selectionMode === 'single'; - let {pressProps} = usePress({ + let {pressProps, isPressed} = usePress({ isDisabled: !allowsSorting || isSelectionCellDisabled, onPress() { state.sort(node.key); @@ -100,6 +102,7 @@ export function useTableColumnHeader(props: AriaTableColumnHeaderProps, st id: getColumnHeaderId(state, node.key), 'aria-colspan': node.colSpan && node.colSpan > 1 ? node.colSpan : undefined, 'aria-sort': ariaSort - } + }, + isPressed }; } diff --git a/packages/dev/docs/pages/react-aria/home/ExampleApp.tsx b/packages/dev/docs/pages/react-aria/home/ExampleApp.tsx index eb2b75a46c0..f835f94e8e1 100644 --- a/packages/dev/docs/pages/react-aria/home/ExampleApp.tsx +++ b/packages/dev/docs/pages/react-aria/home/ExampleApp.tsx @@ -15,13 +15,13 @@ import {Button} from 'tailwind-starter/Button'; import {Cell, Column, Row, TableHeader} from 'tailwind-starter/Table'; import {Checkbox} from 'tailwind-starter/Checkbox'; import {CloudSun, Dessert, Droplet, Droplets, FilterIcon, Mail, MoreHorizontal, PencilIcon, PlusIcon, RefreshCw, ShareIcon, SlidersIcon, StarIcon, Sun, SunDim, TrashIcon, Twitter} from 'lucide-react'; -import {ColumnProps, Dialog, DialogTrigger, DropZone, Form, Heading, isFileDropItem, Key, MenuTrigger, ModalOverlay, ModalOverlayProps, Modal as RACModal, ResizableTableContainer, Selection, SortDescriptor, SubmenuTrigger, Table, TableBody, Text, ToggleButton, ToggleButtonProps, TooltipTrigger} from 'react-aria-components'; +import {ColumnProps, Dialog, DialogTrigger, DropZone, Form, Heading, isFileDropItem, Key, ModalOverlay, ModalOverlayProps, Modal as RACModal, ResizableTableContainer, Selection, SortDescriptor, Table, TableBody, Text, ToggleButton, ToggleButtonProps, TooltipTrigger} from 'react-aria-components'; import {ComboBox, ComboBoxItem} from 'tailwind-starter/ComboBox'; import {DatePicker} from 'tailwind-starter/DatePicker'; import {focusRing} from 'tailwind-starter/utils'; import {getLocalTimeZone, today} from '@internationalized/date'; import {GridList, GridListItem} from 'tailwind-starter/GridList'; -import {Menu, MenuItem} from 'tailwind-starter/Menu'; +import {Menu, MenuItem, MenuTrigger, SubmenuTrigger} from 'tailwind-starter/Menu'; import {Modal} from 'tailwind-starter/Modal'; import plants, {Plant} from './plants'; import {Popover} from 'tailwind-starter/Popover'; @@ -41,7 +41,7 @@ const allColumns: ColumnProps[] = [ {id: 'cycle', children: 'Cycle', defaultWidth: 120, allowsSorting: true}, {id: 'sunlight', children: 'Sunlight', defaultWidth: 120, allowsSorting: true}, {id: 'watering', children: 'Watering', defaultWidth: 120, allowsSorting: true}, - {id: 'actions', children: Actions, width: 44, minWidth: 44} + {id: 'actions', children: Actions, width: 64, minWidth: 64} ]; let hideOnScroll = document.getElementById('hideOnScroll'); @@ -237,9 +237,9 @@ export function ExampleApp(): React.ReactNode { {item.common_name} {item.scientific_name} - - - onAction(item, action)}> + + + onAction(item, action)}> {item.isFavorite ? 'Unfavorite' : 'Favorite'} Edit… Delete… @@ -296,7 +296,7 @@ export function ExampleApp(): React.ReactNode { return ( - onAction(item, action)}> diff --git a/packages/dev/s2-docs/pages/react-aria/Button.mdx b/packages/dev/s2-docs/pages/react-aria/Button.mdx index e9d2f02b200..452dd693ed5 100644 --- a/packages/dev/s2-docs/pages/react-aria/Button.mdx +++ b/packages/dev/s2-docs/pages/react-aria/Button.mdx @@ -6,6 +6,7 @@ import docs from 'docs:react-aria-components'; import {Button as VanillaButton} from 'vanilla-starter/Button'; import {Button as TailwindButton} from 'tailwind-starter/Button'; /* import {Button as MacroButton} from './ButtonExample'; */ +import vanillaDocs from 'docs:vanilla-starter/Button'; import tailwindDocs from 'docs:tailwind-starter/Button'; import '../../tailwind/tailwind.css'; import typesDocs from 'docs:@react-types/shared/src/events.d.ts'; @@ -19,9 +20,9 @@ export const tags = ['btn']; @@ -114,7 +115,7 @@ The `Button` component always represents a button semantically. To create a link "use client"; import {Link} from 'react-aria-components'; - + Adobe ``` diff --git a/packages/dev/s2-docs/pages/react-aria/Calendar.mdx b/packages/dev/s2-docs/pages/react-aria/Calendar.mdx index 560fed91a6b..4325cdc604c 100644 --- a/packages/dev/s2-docs/pages/react-aria/Calendar.mdx +++ b/packages/dev/s2-docs/pages/react-aria/Calendar.mdx @@ -183,8 +183,11 @@ Set the `visibleDuration` prop and render multiple `CalendarGrid` elements to di ```tsx render docs={docs.exports.Calendar} links={docs.links} props={['visibleDuration', 'pageBehavior', 'firstDayOfWeek']} initialProps={{visibleDuration: {months: 2}}} wide "use client"; -import {Calendar, Heading, Button, CalendarGrid, CalendarCell} from 'react-aria-components'; +import {Calendar, Heading} from 'react-aria-components'; +import {CalendarGrid, CalendarCell} from 'vanilla-starter/Calendar'; +import {Button} from 'vanilla-starter/Button'; import {useDateFormatter} from 'react-aria'; +import {ChevronLeft, ChevronRight} from 'lucide-react'; // TODO: move this into the starter example. function Example(props) { @@ -201,18 +204,22 @@ function Example(props) { ///- begin highlight -/// /* PROPS */ ///- end highlight -/// - style={{display: 'flex', gap: 30, overflow: 'auto'}} + style={{display: 'flex', gap: 12, overflow: 'auto'}} > {({state}) => ( [...Array(props.visibleDuration.months).keys()].map(i => (
-
+
{i === 0 && - + } -

{monthFormatter.format(state.visibleRange.start.add({months: i}).toDate('UTC'))}

+ {monthFormatter.format(state.visibleRange.start.add({months: i}).toDate(state.timeZone))} {i === props.visibleDuration.months - 1 && - + }
@@ -265,19 +272,25 @@ You can also control the focused date via `CalendarStateContext`. This example s ```tsx render files={['packages/dev/s2-docs/pages/react-aria/MonthDropdown.tsx', 'packages/dev/s2-docs/pages/react-aria/YearDropdown.tsx']} "use client"; -import {Calendar, CalendarGrid, CalendarCell} from 'react-aria-components'; +import {Calendar} from 'react-aria-components'; +import {CalendarGrid, CalendarCell} from 'vanilla-starter/Calendar'; import {MonthDropdown} from './MonthDropdown'; import {YearDropdown} from './YearDropdown'; import {Button} from 'vanilla-starter/Button'; +import {ChevronLeft, ChevronRight} from 'lucide-react';
- + {/*- begin highlight -*/} {/*- end highlight -*/} - +
{(date) => } diff --git a/packages/dev/s2-docs/pages/react-aria/Checkbox.mdx b/packages/dev/s2-docs/pages/react-aria/Checkbox.mdx index 19ba646d98d..42195a062d2 100644 --- a/packages/dev/s2-docs/pages/react-aria/Checkbox.mdx +++ b/packages/dev/s2-docs/pages/react-aria/Checkbox.mdx @@ -70,7 +70,7 @@ Use the `name` and `value` props to submit the checkbox to the server. Set the ` "use client"; import {Checkbox} from 'vanilla-starter/Checkbox'; import {Button} from 'vanilla-starter/Button'; -import {Form} from 'react-aria-components'; +import {Form} from 'vanilla-starter/Form';;
diff --git a/packages/dev/s2-docs/pages/react-aria/ColorField.mdx b/packages/dev/s2-docs/pages/react-aria/ColorField.mdx index 3db74874820..c4ac7c62928 100644 --- a/packages/dev/s2-docs/pages/react-aria/ColorField.mdx +++ b/packages/dev/s2-docs/pages/react-aria/ColorField.mdx @@ -20,7 +20,7 @@ export const tags = ['input']; docs={vanillaDocs.exports.ColorField} links={vanillaDocs.links} props={['label', 'colorSpace', 'channel', 'description', 'isDisabled']} - initialProps={{label: 'Color', defaultValue: '#ff0000'}} + initialProps={{label: 'Color', defaultValue: '#ff0000', placeholder: 'Enter a color'}} type="vanilla" files={["starters/docs/src/ColorField.tsx", "starters/docs/src/ColorField.css"]} /> @@ -50,9 +50,10 @@ function Example() {
-
Current value: {value.toString('hex')}
+
Current value: {value?.toString('hex')}
); } @@ -75,6 +76,7 @@ function Example() {
diff --git a/packages/dev/s2-docs/pages/react-aria/ComboBox.mdx b/packages/dev/s2-docs/pages/react-aria/ComboBox.mdx index c6091720d43..0efd57fda82 100644 --- a/packages/dev/s2-docs/pages/react-aria/ComboBox.mdx +++ b/packages/dev/s2-docs/pages/react-aria/ComboBox.mdx @@ -14,7 +14,7 @@ export const tags = ['autocomplete', 'search', 'typeahead', 'input']; {docs.exports.ComboBox.description} - ```tsx render docs={vanillaDocs.exports.ComboBox} links={vanillaDocs.links} props={['label', 'isDisabled']} initialProps={{label: 'Favorite Animal'}} type="vanilla" files={["starters/docs/src/ComboBox.tsx", "starters/docs/src/ComboBox.css"]} + ```tsx render docs={vanillaDocs.exports.ComboBox} links={vanillaDocs.links} props={['label', 'isDisabled']} initialProps={{label: 'Favorite Animal', placeholder: 'Select a flavor'}} type="vanilla" files={["starters/docs/src/ComboBox.tsx", "starters/docs/src/ComboBox.css"]} "use client"; import {ComboBox, ComboBoxItem} from 'vanilla-starter/ComboBox'; @@ -28,7 +28,7 @@ export const tags = ['autocomplete', 'search', 'typeahead', 'input']; ``` - ```tsx render docs={vanillaDocs.exports.ComboBox} links={vanillaDocs.links} props={['label', 'isDisabled']} initialProps={{label: 'Favorite Animal'}} type="tailwind" files={["starters/tailwind/src/ComboBox.tsx"]} + ```tsx render docs={vanillaDocs.exports.ComboBox} links={vanillaDocs.links} props={['label', 'isDisabled']} initialProps={{label: 'Favorite Animal', placeholder: 'Select a flavor'}} type="tailwind" files={["starters/tailwind/src/ComboBox.tsx"]} "use client"; import {ComboBox, ComboBoxItem} from 'tailwind-starter/ComboBox'; @@ -52,8 +52,8 @@ The following example shows a dynamic collection of items, grouped into sections ```tsx render "use client"; -import {ComboBox} from 'vanilla-starter/ComboBox'; -import {ListBoxSection, ListBoxItem, Collection, Header} from 'react-aria-components'; +import {ComboBox, ComboBoxItem} from 'vanilla-starter/ComboBox'; +import {ListBoxSection, Collection, Header} from 'react-aria-components'; function Example() { /*- begin collapse -*/ @@ -82,16 +82,21 @@ function Example() { /*- end collapse -*/ return ( - + /*- begin highlight -*/ + {section => (
{section.name}
- {item => {item.name}} + {item => {item.name}}
)}
+ /*- end highlight -*/ ); } ``` @@ -112,7 +117,8 @@ function Example() { return (
@@ -148,6 +154,7 @@ function Example(props) { @@ -278,11 +287,12 @@ Use the `name` prop to submit the `id` of the selected item to the server. Set t "use client"; import {ComboBox, ComboBoxItem} from 'vanilla-starter/ComboBox'; import {Button} from 'vanilla-starter/Button'; -import {Form} from 'react-aria-components'; +import {Form} from 'vanilla-starter/Form';; -
+
{/*- begin highlight -*/} Files - + {/*- end highlight -*/}
Files content diff --git a/packages/dev/s2-docs/pages/react-aria/Form.mdx b/packages/dev/s2-docs/pages/react-aria/Form.mdx index 88a106efb32..c0b65dfd57b 100644 --- a/packages/dev/s2-docs/pages/react-aria/Form.mdx +++ b/packages/dev/s2-docs/pages/react-aria/Form.mdx @@ -18,11 +18,11 @@ export const tags = ['input', 'field']; import {Button} from 'vanilla-starter/Button'; - - + +
- +
``` @@ -34,11 +34,11 @@ export const tags = ['input', 'field']; import {Button} from 'tailwind-starter/Button';
- - + +
- +
``` @@ -64,7 +64,7 @@ import {Button} from 'vanilla-starter/Button'; alert(`Hello, ${name}!`); }}> {/*- end highlight -*/} - + ``` @@ -90,7 +90,7 @@ import {Button} from 'vanilla-starter/Button'; event.target.reset(); }}> {/*- end highlight -*/} - + ``` @@ -110,6 +110,7 @@ import {Button} from 'vanilla-starter/Button';
value === 'admin' ? 'Nice try.' : null} name="username" @@ -136,6 +137,7 @@ import {TextField} from 'vanilla-starter/TextField'; ``` @@ -176,14 +178,16 @@ function Example() { + label="First Name" + placeholder="Enter your first name" /> + label="Last Name" + placeholder="Enter your last name" />
- +
); diff --git a/packages/dev/s2-docs/pages/react-aria/GridList.mdx b/packages/dev/s2-docs/pages/react-aria/GridList.mdx index d03c53afdd6..1f068c35ac3 100644 --- a/packages/dev/s2-docs/pages/react-aria/GridList.mdx +++ b/packages/dev/s2-docs/pages/react-aria/GridList.mdx @@ -14,27 +14,62 @@ export const tags = ['list view']; {docs.exports.GridList.description} - ```tsx render docs={docs.exports.GridList} links={docs.links} props={['selectionMode']} initialProps={{'aria-label': 'Favorite pokemon', selectionMode: 'multiple'}} type="vanilla" files={["starters/docs/src/GridList.tsx", "starters/docs/src/GridList.css"]} + ```tsx render docs={docs.exports.GridList} links={docs.links} props={['layout', 'selectionMode']} initialProps={{'aria-label': 'Favorite pokemon', selectionMode: 'multiple', layout: 'grid'}} type="vanilla" files={["starters/docs/src/GridList.tsx", "starters/docs/src/GridList.css"]} "use client"; + import {Text} from 'react-aria-components'; import {GridList, GridListItem} from 'vanilla-starter/GridList'; import {Button} from 'vanilla-starter/Button'; - - Charizard - + + + Desert Sunset + PNG • 2/3/2024 - - Blastoise - + + + Hiking Trail + JPEG • 1/10/2022 - - Venusaur - + + + Lion + JPEG • 8/28/2021 - - Pikachu - + + + Mountain Sunrise + PNG • 3/15/2015 + + + + Giraffe tongue + PNG • 11/27/2019 + + + + Golden Hour + WEBP • 7/24/2024 + + + + Architecture + PNG • 12/24/2016 + + + + Peeking leopard + JPEG • 3/2/2016 + + + + Roofs + JPEG • 4/24/2025 + + + + Half Dome Deer + DNG • 8/28/2018 ``` @@ -62,26 +97,262 @@ export const tags = ['list view']; ```tsx render "use client"; import {GridList, GridListItem} from 'vanilla-starter/GridList'; +import {Text} from 'react-aria-components'; + +///- begin collapse -/// +let images = [ + { + id: "8SXaMMWCTGc", + title: "A Ficus Lyrata Leaf", + user: "Clay Banks", + image: "https://images.unsplash.com/photo-1580133318324-f2f76d987dd8?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + }, + { + id: "pYjCqqDEOFo", + title: "Italian beach", + user: "Alan Bajura", + image: "https://images.unsplash.com/photo-1737100522891-e8946ac97fd1?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + }, + { + id: "CF-2tl6MQj0", + title: "Forest road", + user: "Artem Stoliar", + image: "https://images.unsplash.com/photo-1738249034651-1896f689be58?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 300 + }, + { + id: "OW97sLU0cOw", + title: "Snowy Aurora", + user: "Janosch Diggelmann", + image: "https://images.unsplash.com/photo-1738189669835-61808a9d5981?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + }, + { + id: "WfeLZ02IhkM", + title: "A blue and white firework is seen from above", + user: "Janosch Diggelmann", + image: "https://images.unsplash.com/photo-1738168601630-1c1f3ef5a95a?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 300 + }, + { + id: "w1GpST72Bg8", + title: "Snowy Mountain", + user: "Daniil Silantev", + image: "https://images.unsplash.com/photo-1738165170747-ecc6e3a4d97c?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 267 + }, + { + id: "0iN0KIt6lYI", + title: "Pastel Sunset", + user: "Marek Piwnicki", + image: "https://images.unsplash.com/photo-1737917818689-f3b3708de5d7?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 640 + }, + { + id: "-mFKPfXXUG0", + title: "Snowy Birches", + user: "Simon Berger", + image: "https://images.unsplash.com/photo-1737972970322-cc2e255021bd?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 400 + }, + { + id: "y36Nj_edtRE", + title: "Snowy Lake Reflections", + user: "Daniel Seßler", + image: "https://images.unsplash.com/photo-1736018545810-3de4c7ec25fa?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + }, + { + id: "NvBV-YwlgBw", + title: "Rocky night sky", + user: "Dennis Haug", + image: "https://images.unsplash.com/photo-1735528655501-cf671a3323c3?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 400 + }, + { + id: "UthQdrPFxt0", + title: "A pine tree covered in snow in a forest", + user: "Anita Austvika", + image: "https://images.unsplash.com/photo-1737312905026-5dfdff1097bc?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + }, + { + id: "2k74xaf8dfc", + title: "The sun shines through the trees in the forest", + user: "Joyce G", + image: "https://images.unsplash.com/photo-1736185597807-371cae1c7e4e?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + }, + { + id: "Yje5kgfvCm0", + title: "A blurry photo of a field of flowers", + user: "Eugene Golovesov", + image: "https://images.unsplash.com/photo-1736483065204-e55e62092780?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + }, + { + id: "G2bsj2LVttI", + title: "A foggy road lined with trees and grass", + user: "Ingmar H", + image: "https://images.unsplash.com/photo-1737903071772-4d20348b4d81?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 533 + }, + { + id: "ppyNBOkfiuY", + title: "A close up of a green palm tree", + user: "Junel Mujar", + image: "https://images.unsplash.com/photo-1736849544918-6ddb5cfc2c42?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 533 + }, + { + id: "UcWUMqIsld8", + title: "A green leaf floating on top of a body of water", + user: "Allec Gomes", + image: "https://images.unsplash.com/photo-1737559217439-a5703e9b65cb?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + }, + { + id: "xHqOVq9w8OI", + title: "Leafy plants", + user: "Joshua Michaels", + image: "https://images.unsplash.com/photo-1563364664-399838d1394c?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 266 + }, + { + id: "uWx3_XEc-Jw", + title: "A view of a mountain covered in fog", + user: "iuliu illes", + image: "https://images.unsplash.com/photo-1737403428945-c584529b7b17?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 298 + }, + { + id: "2_3lhGt8i-Y", + title: "A field with tall grass and fog in the background", + user: "Ingmar H", + image: "https://images.unsplash.com/photo-1737439987404-a3ee9fb95351?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + }, + { + id: "FV-__IOxb08", + title: "A close up of a wave on a sandy beach", + user: "Jonathan Borba", + image: "https://images.unsplash.com/photo-1726502102472-2108ef2a5cae?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + }, + { + id: "_BS-vK3boOU", + title: "Desert textures", + user: "Braden Jarvis", + image: "https://images.unsplash.com/photo-1722359546494-8e3a00f88e95?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 561 + }, + { + id: "LjAcS9lJdBg", + title: "Tew Falls, waterfall, in Hamilton, Canada.", + user: "Andre Portolesi", + image: "https://images.unsplash.com/photo-1705021246536-aecfad654893?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 500 + }, + { + id: "hlj6xJG30FE", + title: "Cave light rays", + user: "Intricate Explorer", + image: "https://images.unsplash.com/photo-1631641551473-fbe46919289d?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 267 + }, + { + id: "vMoZvKeZOhw", + title: "Salt Marshes, Isle of Harris, Scotland", + user: "Nils Leonhardt", + image: "https://images.unsplash.com/photo-1585951301678-8fd6f3b32c7e?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + }, + { + id: "wCLCK9LDDjI", + title: "An aerial view of a snow covered forest", + user: "Lukas Hädrich", + image: "https://images.unsplash.com/photo-1737405555489-78b3755eaa81?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 267 + }, + { + id: "OdDx3_NB-Wk", + title: "Tall grass", + user: "Ingmar H", + image: "https://images.unsplash.com/photo-1737301519296-062cd324dbfa?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + }, + { + id: "Gn-FOw1geFc", + title: "Larches on Maple Pass, Washington", + user: "Noelle", + image: "https://images.unsplash.com/photo-1737496538329-a59d10148a08?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + }, + { + id: "VhKJHOz2tJ8", + title: "Heart Nebula", + user: "Arnaud Girault", + image: "https://images.unsplash.com/photo-1737478598284-b9bc11cb1e9b?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 266 + }, + { + id: "w5QmH_uqB0U", + title: "A pile of shells sitting on top of a sandy beach", + user: "Toa Heftiba", + image: "https://images.unsplash.com/photo-1725366351350-a64a1be919ef?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + } +]; +///- end collapse -/// function Example() { - let options = [ - { id: 1, name: 'Aardvark' }, - { id: 2, name: 'Cat' }, - { id: 3, name: 'Dog' }, - { id: 4, name: 'Kangaroo' }, - { id: 5, name: 'Koala' }, - { id: 6, name: 'Penguin' }, - { id: 7, name: 'Snake' }, - { id: 8, name: 'Turtle' }, - { id: 9, name: 'Wombat' } - ]; - return ( - /*- begin highlight -*/ - - {(item) => {item.name}} + + {/*- end highlight -*/} + {(image) => ( + + + {image.title} + By {image.user} + + )} - /*- end highlight -*/ ); } ``` @@ -92,51 +363,48 @@ Use [renderEmptyState](#empty-state) to display a spinner during initial load. T ```tsx render "use client"; -import {Collection, GridListLoadMoreItem} from 'react-aria-components'; -import {GridList, GridListItem} from 'vanilla-starter/GridList'; +import {GridList, GridListItem, GridListLoadMoreItem} from 'vanilla-starter/GridList'; +import {Collection, Text} from 'react-aria-components'; import {ProgressCircle} from 'vanilla-starter/ProgressCircle'; import {useAsyncList} from '@react-stately/data'; -interface Character { - name: string -} - function AsyncLoadingExample() { - let list = useAsyncList({ - async load({ signal, cursor }) { - if (cursor) { - cursor = cursor.replace(/^http:\/\//i, 'https://'); - } - + let list = useAsyncList({ + async load({signal, cursor, items}) { + let page = cursor || 1; let res = await fetch( - cursor || `https://swapi.py4e.com/api/people/?search=`, - { signal } + `https://api.unsplash.com/topics/nature/photos?page=${page}&per_page=30&client_id=AJuU-FPh11hn7RuumUllp4ppT8kgiLS7LtOHp_sp4nc`, + {signal} ); - let json = await res.json(); - - return { - items: json.results, - cursor: json.next - }; + let nextItems = await res.json(); + // Filter duplicates which might be returned by the API. + let existingKeys = new Set(items.map(i => i.id)); + nextItems = nextItems.filter(i => !existingKeys.has(i.id) && (i.description || i.alt_description)); + return {items: nextItems, cursor: nextItems.length ? page + 1 : null}; } }); return ( ( )}> - {(item) => {item.name}} + {(item) => ( + + + {item.description || item.alt_description} + By {item.user.name} + + )} {/*- begin highlight -*/} - - + isLoading={list.loadingState === 'loadingMore'} /> {/*- end highlight -*/} ); @@ -150,14 +418,89 @@ Use the `href` prop on a `` to create a link. See the **client sid ```tsx render docs={docs.exports.GridList} links={docs.links} props={['selectionBehavior']} initialProps={{'aria-label': 'Links', selectionMode: 'multiple'}} wide "use client"; import {GridList, GridListItem} from 'vanilla-starter/GridList'; - - - {/*- begin highlight -*/} - Adobe - {/*- end highlight -*/} - Apple - Google - Microsoft +import {Text} from 'react-aria-components'; + +///- begin collapse -/// +let images = [ + { + id: "dxylfBs2Xzc", + title: "Tropical island", + image: "https://images.unsplash.com/photo-1757258632083-e9b8a5345047?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTc2MDYyMjY4NHw&ixlib=rb-4.1.0&q=80&w=1080", + width: 5464, + height: 3640, + href: "https://unsplash.com/photos/aerial-view-of-a-tropical-island-coastline-with-clear-blue-water-dxylfBs2Xzc" + }, + { + id: "xloDEfz0X7g", + title: "Bryce Canyon", + image: "https://images.unsplash.com/photo-1759872409669-05565abbb575?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTc2MDYyMjY4NHw&ixlib=rb-4.1.0&q=80&w=1080", + width: 4032, + height: 3024, + href: "https://unsplash.com/photos/orange-rock-formations-with-green-trees-and-blue-sky-xloDEfz0X7g" + }, + { + id: "oTBY78rZcEU", + title: "Snowy river", + image: "https://images.unsplash.com/photo-1735577561802-380c3afb0146?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTc2MDYyMjY4NHw&ixlib=rb-4.1.0&q=80&w=1080", + width: 3264, + height: 4896, + href: "https://unsplash.com/photos/a-river-surrounded-by-snow-covered-trees-and-mountains-oTBY78rZcEU" + }, + { + id: "Go811IU9a2g", + title: "Ocean waves", + image: "https://images.unsplash.com/photo-1759997604062-c31f20012ac1?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTc2MDYyMjY4NHw&ixlib=rb-4.1.0&q=80&w=1080", + width: 5250, + height: 3500, + href: "https://unsplash.com/photos/a-large-wave-crashes-on-a-sandy-beach-Go811IU9a2g" + }, + { + id: "B0mydNIV-sI", + title: "Mount Kazbek at Dawn", + image: "https://images.unsplash.com/photo-1760464864365-2188cd2afcde?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTc2MDYyMjY4NHw&ixlib=rb-4.1.0&q=80&w=1080", + width: 3947, + height: 5920, + href: "https://unsplash.com/photos/snow-capped-mountain-peak-illuminated-by-sunrise-B0mydNIV-sI" + }, + { + id: "IHfbPJYsnsI", + title: "Snowy mountain sunrise", + image: "https://images.unsplash.com/photo-1759675795062-a657fcb278b1?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTc2MDYyMjY4NHw&ixlib=rb-4.1.0&q=80&w=1080", + width: 5794, + height: 3360, + href: "https://unsplash.com/photos/snowy-mountains-rise-from-the-ocean-at-sunrise-IHfbPJYsnsI" + }, + { + id: "mmcSaJrRuCM", + title: "Mount Blum", + image: "https://images.unsplash.com/photo-1760301269447-fbc82b5a8d14?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTc2MDYyMjY4NHw&ixlib=rb-4.1.0&q=80&w=1080", + width: 5862, + height: 4000, + href: "https://unsplash.com/photos/majestic-mountain-peak-illuminated-by-sunrise-light-mmcSaJrRuCM" + }, + { + id: "SSpEIUBRG9s", + title: "Sunset", + image: "https://images.unsplash.com/photo-1760199025509-2ecc68d39acd?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTc2MDYyMjY4NHw&ixlib=rb-4.1.0&q=80&w=1080", + width: 6000, + height: 4000, + href: "https://unsplash.com/photos/silhouette-of-trees-and-plants-against-a-sunset-sky-SSpEIUBRG9s" + } +]; +///- end collapse -/// + + + {image => ( + + + {image.title} + + )} ``` @@ -180,7 +523,7 @@ Use the `selectionMode` prop to enable single or multiple selection. The selecte ```tsx render docs={docs.exports.GridList} links={docs.links} props={['selectionMode', 'selectionBehavior', 'disabledBehavior', 'disallowEmptySelection']} initialProps={{selectionMode: 'multiple'}} wide "use client"; -import type {Selection} from 'react-aria-components'; +import {type Selection, Text} from 'react-aria-components'; import {GridList, GridListItem} from 'vanilla-starter/GridList'; import {useState} from 'react'; @@ -188,10 +531,11 @@ function Example(props) { let [selected, setSelected] = useState(new Set()); return ( -
+ <> alert(`Clicked ${key}`)} ///- end highlight -/// > - Lettuce - Tomato - Cheese - Tuna Salad - Egg Salad - Ham + + + Desert Sunset + PNG • 2/3/2024 + + + + Hiking Trail + JPEG • 1/10/2022 + + + + Lion + JPEG • 8/28/2021 + + + + Mountain Sunrise + PNG • 3/15/2015 + + + + Giraffe tongue + PNG • 11/27/2019 + + + + Golden Hour + WEBP • 7/24/2024 + + + + Architecture + PNG • 12/24/2016 + + + + Peeking leopard + JPEG • 3/2/2016 + + + + Roofs + JPEG • 4/24/2025 + + + + Half Dome Deer + DNG • 8/28/2018 +

Current selection: {selected === 'all' ? 'all' : [...selected].join(', ')}

-
+ ); } ``` @@ -220,22 +608,261 @@ GridList supports drag and drop interactions when the `dragAndDropHooks` prop is "use client"; import {useListData} from 'react-stately'; import {GridList, GridListItem} from 'vanilla-starter/GridList'; -import {useDragAndDrop} from 'react-aria-components'; +import {useDragAndDrop, Text} from 'react-aria-components'; + +///- begin collapse -/// +let images = [ + { + id: "8SXaMMWCTGc", + title: "A Ficus Lyrata Leaf in the sunlight (2/2) (IG: @clay.banks)", + user: "Clay Banks", + image: "https://images.unsplash.com/photo-1580133318324-f2f76d987dd8?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + }, + { + id: "pYjCqqDEOFo", + title: "beach of Italy", + user: "alan bajura", + image: "https://images.unsplash.com/photo-1737100522891-e8946ac97fd1?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + }, + { + id: "CF-2tl6MQj0", + title: "A winding road in the middle of a forest", + user: "Artem Stoliar", + image: "https://images.unsplash.com/photo-1738249034651-1896f689be58?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 300 + }, + { + id: "OW97sLU0cOw", + title: "A green and purple aurora over a snow covered forest", + user: "Janosch Diggelmann", + image: "https://images.unsplash.com/photo-1738189669835-61808a9d5981?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + }, + { + id: "WfeLZ02IhkM", + title: "A blue and white firework is seen from above", + user: "Janosch Diggelmann", + image: "https://images.unsplash.com/photo-1738168601630-1c1f3ef5a95a?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 300 + }, + { + id: "w1GpST72Bg8", + title: "A snow covered mountain with a sky background", + user: "Daniil Silantev", + image: "https://images.unsplash.com/photo-1738165170747-ecc6e3a4d97c?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 267 + }, + { + id: "0iN0KIt6lYI", + title: "\"Pastel Sunset\"", + user: "Marek Piwnicki", + image: "https://images.unsplash.com/photo-1737917818689-f3b3708de5d7?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 640 + }, + { + id: "-mFKPfXXUG0", + title: "Leave the weight behind! You must make yourself light to strive upwards — to reach the light. (A serene winter landscape featuring a dense collection of bare, white trees.)", + user: "Simon Berger", + image: "https://images.unsplash.com/photo-1737972970322-cc2e255021bd?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 400 + }, + { + id: "MOk6URQ28R4", + title: "A snow covered tree with a sky background", + user: "Daniil Silantev", + image: "https://images.unsplash.com/photo-1738081359113-a7a33c509cf9?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + }, + { + id: "y36Nj_edtRE", + title: "A lake surrounded by trees covered in snow", + user: "Daniel Seßler", + image: "https://images.unsplash.com/photo-1736018545810-3de4c7ec25fa?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + }, + { + id: "NvBV-YwlgBw", + title: "The night sky with stars above a rock formation", + user: "Dennis Haug", + image: "https://images.unsplash.com/photo-1735528655501-cf671a3323c3?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 400 + }, + { + id: "UthQdrPFxt0", + title: "A pine tree covered in snow in a forest", + user: "Anita Austvika", + image: "https://images.unsplash.com/photo-1737312905026-5dfdff1097bc?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + }, + { + id: "2k74xaf8dfc", + title: "The sun shines through the trees in the forest", + user: "Joyce G", + image: "https://images.unsplash.com/photo-1736185597807-371cae1c7e4e?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + }, + { + id: "Yje5kgfvCm0", + title: "A blurry photo of a field of flowers", + user: "Eugene Golovesov", + image: "https://images.unsplash.com/photo-1736483065204-e55e62092780?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + }, + { + id: "G2bsj2LVttI", + title: "A foggy road lined with trees and grass", + user: "Ingmar H", + image: "https://images.unsplash.com/photo-1737903071772-4d20348b4d81?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 533 + }, + { + id: "ppyNBOkfiuY", + title: "A close up of a green palm tree", + user: "Junel Mujar", + image: "https://images.unsplash.com/photo-1736849544918-6ddb5cfc2c42?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 533 + }, + { + id: "UcWUMqIsld8", + title: "A green leaf floating on top of a body of water", + user: "Allec Gomes", + image: "https://images.unsplash.com/photo-1737559217439-a5703e9b65cb?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + }, + { + id: "xHqOVq9w8OI", + title: "green-leafed plant", + user: "Joshua Michaels", + image: "https://images.unsplash.com/photo-1563364664-399838d1394c?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 266 + }, + { + id: "uWx3_XEc-Jw", + title: "A view of a mountain covered in fog", + user: "iuliu illes", + image: "https://images.unsplash.com/photo-1737403428945-c584529b7b17?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 298 + }, + { + id: "2_3lhGt8i-Y", + title: "A field with tall grass and fog in the background", + user: "Ingmar H", + image: "https://images.unsplash.com/photo-1737439987404-a3ee9fb95351?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + }, + { + id: "FV-__IOxb08", + title: "A close up of a wave on a sandy beach", + user: "Jonathan Borba", + image: "https://images.unsplash.com/photo-1726502102472-2108ef2a5cae?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + }, + { + id: "_BS-vK3boOU", + title: "Desert textures", + user: "Braden Jarvis", + image: "https://images.unsplash.com/photo-1722359546494-8e3a00f88e95?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 561 + }, + { + id: "LjAcS9lJdBg", + title: "Tew Falls, waterfall, in Hamilton, Canada.", + user: "Andre Portolesi", + image: "https://images.unsplash.com/photo-1705021246536-aecfad654893?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 500 + }, + { + id: "hlj6xJG30FE", + title: "Find me on Instagram! @intricateexplorer", + user: "Intricate Explorer", + image: "https://images.unsplash.com/photo-1631641551473-fbe46919289d?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 267 + }, + { + id: "vMoZvKeZOhw", + title: "Salt Marshes, Isle of Harris, Scotland by Nils Leonhardt. Visit my website: https://nilsleonhardt.com/storytelling-harris/ Instagram: @am.basteir", + user: "Nils Leonhardt", + image: "https://images.unsplash.com/photo-1585951301678-8fd6f3b32c7e?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + }, + { + id: "wCLCK9LDDjI", + title: "An aerial view of a snow covered forest", + user: "Lukas Hädrich", + image: "https://images.unsplash.com/photo-1737405555489-78b3755eaa81?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 267 + }, + { + id: "OdDx3_NB-Wk", + title: "A close up of a tall grass with a sky in the background", + user: "Ingmar H", + image: "https://images.unsplash.com/photo-1737301519296-062cd324dbfa?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + }, + { + id: "Gn-FOw1geFc", + title: "Larches on Maple Pass, Washington", + user: "noelle", + image: "https://images.unsplash.com/photo-1737496538329-a59d10148a08?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + }, + { + id: "VhKJHOz2tJ8", + title: "IC 1805 La nébuleuse du coeur", + user: "arnaud girault", + image: "https://images.unsplash.com/photo-1737478598284-b9bc11cb1e9b?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 266 + }, + { + id: "w5QmH_uqB0U", + title: "A pile of shells sitting on top of a sandy beach", + user: "Toa Heftiba", + image: "https://images.unsplash.com/photo-1725366351350-a64a1be919ef?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wzNDA4NDh8MHwxfHRvcGljfHw2c01WalRMU2tlUXx8fHx8Mnx8MTczODM2NzE4M3w&ixlib=rb-4.0.3&q=80&w=400", + width: 400, + height: 600 + } +]; +///- end collapse -/// function Example() { let list = useListData({ - initialItems: [ - {id: 1, name: 'Adobe Photoshop'}, - {id: 2, name: 'Adobe XD'}, - {id: 3, name: 'Adobe Dreamweaver'}, - {id: 4, name: 'Adobe InDesign'}, - {id: 5, name: 'Adobe Connect'} - ] + initialItems: images }); ///- begin highlight -/// let {dragAndDropHooks} = useDragAndDrop({ - getItems: (keys) => [...keys].map(key => ({'text/plain': list.getItem(key).name})), + getItems: (keys) => [...keys].map(key => ({'text/plain': list.getItem(key).title})), onReorder(e) { if (e.target.dropPosition === 'before') { list.moveBefore(e.target.key, e.keys); @@ -249,13 +876,20 @@ function Example() { return ( - {item => {item.name}} + {image => ( + + + {image.title} + {image.user} + + )} ); } diff --git a/packages/dev/s2-docs/pages/react-aria/ListBox.mdx b/packages/dev/s2-docs/pages/react-aria/ListBox.mdx index 3e1c7218b4e..b39702a53a1 100644 --- a/packages/dev/s2-docs/pages/react-aria/ListBox.mdx +++ b/packages/dev/s2-docs/pages/react-aria/ListBox.mdx @@ -15,7 +15,7 @@ export const tags = ['options']; {docs.exports.ListBox.description} - ```tsx render docs={docs.exports.ListBox} links={docs.links} props={['selectionMode']} type="vanilla" files={["starters/docs/src/ListBox.tsx", "starters/docs/src/ListBox.css"]} + ```tsx render docs={docs.exports.ListBox} links={docs.links} props={['selectionMode']} initialProps={{selectionMode: 'multiple'}} type="vanilla" files={["starters/docs/src/ListBox.tsx", "starters/docs/src/ListBox.css"]} "use client"; import {ListBox, ListBoxItem} from 'vanilla-starter/ListBox'; @@ -29,7 +29,7 @@ export const tags = ['options']; ``` - ```tsx render docs={docs.exports.ListBox} links={docs.links} props={['selectionMode']} type="tailwind" files={["starters/tailwind/src/ListBox.tsx"]} + ```tsx render docs={docs.exports.ListBox} links={docs.links} props={['selectionMode']} initialProps={{selectionMode: 'multiple'}} type="tailwind" files={["starters/tailwind/src/ListBox.tsx"]} "use client"; import {ListBox, ListBoxItem} from 'tailwind-starter/ListBox'; @@ -145,9 +145,9 @@ Use [renderEmptyState](#empty-state) to display a spinner during initial load. T ```tsx render "use client"; -import {Collection, ListBoxLoadMoreItem} from 'react-aria-components'; -import {ListBox, ListBoxItem} from 'vanilla-starter/ListBox'; +import {ListBox, ListBoxItem, ListBoxLoadMoreItem} from 'vanilla-starter/ListBox'; import {ProgressCircle} from 'vanilla-starter/ProgressCircle'; +import {Collection} from 'react-aria-components'; import {useAsyncList} from 'react-stately'; interface Character { @@ -183,9 +183,7 @@ function AsyncLoadingExample() { {/*- begin highlight -*/} - - + isLoading={list.loadingState === 'loadingMore'} /> {/*- end highlight -*/} ); @@ -271,52 +269,61 @@ Use the `layout` and `orientation` props to create horizontal and vertical stack import {ListBox, ListBoxItem, Text} from 'react-aria-components'; ///- begin collapse -/// -let albums = [ +let planets = [ { id: 1, - image: 'https://images.unsplash.com/photo-1593958812614-2db6a598c71c?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Nnx8ZGlzY298ZW58MHx8MHx8fDA%3D&auto=format&fit=crop&w=900&q=60', - title: 'Euphoric Echoes', - artist: 'Luna Solstice' + title: 'Mercury', + description: 'A year lasts 88 days' }, { id: 2, - image: 'https://images.unsplash.com/photo-1601042879364-f3947d3f9c16?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8M3x8bmVvbnxlbnwwfHwwfHx8MA%3D%3D&auto=format&fit=crop&w=900&q=60', - title: 'Neon Dreamscape', - artist: 'Electra Skyline' + title: 'Venus', + description: 'Spins backwards!' }, { id: 3, - image: 'https://images.unsplash.com/photo-1528722828814-77b9b83aafb2?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTF8fHNwYWNlfGVufDB8fDB8fHww&auto=format&fit=crop&w=900&q=60', - title: 'Cosmic Serenade', - artist: 'Orion\'s Symphony' + title: 'Earth', + description: 'Only planet with life' }, { id: 4, - image: 'https://images.unsplash.com/photo-1511379938547-c1f69419868d?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8M3x8bXVzaWN8ZW58MHx8MHx8fDA%3D&auto=format&fit=crop&w=900&q=60', - title: 'Melancholy Melodies', - artist: 'Violet Mistral' + title: 'Mars', + description: 'Has the tallest volcano' }, { id: 5, - image: 'https://images.unsplash.com/photo-1608433319511-dfe8ea4cbd3c?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTF8fGJlYXR8ZW58MHx8MHx8fDA%3D&auto=format&fit=crop&w=900&q=60', - title: 'Rhythmic Illusions', - artist: 'Mirage Beats' + title: 'Jupiter', + description: 'Can fit 1,300 Earths' + }, + { + id: 6, + title: 'Saturn', + description: 'Rings made of ice' + }, + { + id: 7, + title: 'Uranus', + description: 'Rolls on its side' + }, + { + id: 8, + title: 'Neptune', + description: 'Fastest winds in space' } ]; ///- end collapse -/// {item => ( - {item.title} - {item.artist} + {item.description} )} diff --git a/packages/dev/s2-docs/pages/react-aria/Menu.mdx b/packages/dev/s2-docs/pages/react-aria/Menu.mdx index bbfcde42091..e58ab58f55a 100644 --- a/packages/dev/s2-docs/pages/react-aria/Menu.mdx +++ b/packages/dev/s2-docs/pages/react-aria/Menu.mdx @@ -15,29 +15,61 @@ export const tags = ['dropdown']; ```tsx render type="vanilla" files={["starters/docs/src/Menu.tsx", "starters/docs/src/Menu.css"]} "use client"; - import {MenuTrigger, Menu, Popover, SubmenuTrigger, MenuSection, Separator} from 'react-aria-components'; + import {MenuTrigger, SubmenuTrigger, Menu, MenuItem, MenuSection} from 'vanilla-starter/Menu'; + import {Separator, Text, Keyboard} from 'react-aria-components'; + import {Popover} from 'vanilla-starter/Popover'; import {Button} from 'vanilla-starter/Button'; - import {MenuItem} from 'vanilla-starter/Menu'; + import {Button} from 'vanilla-starter/Button'; + import {Ellipsis, FolderOpen, Pencil, Copy, Trash, Share, Mail, Smartphone, Instagram} from 'lucide-react'; - + - alert('open')}>Open - alert('rename')}>Rename… - alert('duplicate')}>Duplicate - alert('share')}>Share… - - Share - + + alert('open')}> + + Open + ⌘O + + alert('rename')}> + + Rename… + ⌘R + + alert('duplicate')}> + + Duplicate + ⌘D + + alert('delete')}> + + Delete… + ⌘⌫ + + + + + Share + - Email - SMS - Instagram + + + Email + + + + SMS + + + + Instagram + - - - alert('delete')}>Delete… + + Show files @@ -50,20 +82,19 @@ export const tags = ['dropdown']; ```tsx render type="tailwind" files={["starters/tailwind/src/Menu.tsx"]} "use client"; - import {MenuTrigger, SubmenuTrigger} from 'react-aria-components'; - import {Menu, MenuItem, MenuSection, MenuSeparator} from 'tailwind-starter/Menu'; + import {MenuTrigger, SubmenuTrigger, Menu, MenuItem, MenuSection, MenuSeparator} from 'tailwind-starter/Menu'; import {Button} from 'tailwind-starter/Button'; import {MoreHorizontal} from 'lucide-react'; - alert('open')}>Open alert('rename')}>Rename… alert('duplicate')}>Duplicate - alert('share')}>Share… + alert('delete')}>Delete… Share @@ -72,7 +103,6 @@ export const tags = ['dropdown']; Instagram - alert('delete')}>Delete… Show files @@ -90,7 +120,9 @@ export const tags = ['dropdown']; ```tsx render hideImports "use client"; -import {MenuTrigger, Menu, MenuItem, Button, Popover} from 'react-aria-components'; +import {MenuTrigger, Menu, MenuItem} from 'vanilla-starter/Menu'; +import {Popover} from 'vanilla-starter/Popover'; +import {Button} from 'vanilla-starter/Button'; function Example() { let items = [ @@ -126,7 +158,10 @@ Use the `"label"` and `"description"` slots to separate primary and secondary co ```tsx render hideImports "use client"; -import {MenuTrigger, Menu, MenuItem, Text, Keyboard, Button, Popover} from 'react-aria-components'; +import {MenuTrigger, Menu, MenuItem} from 'vanilla-starter/Menu'; +import {Text, Keyboard} from 'react-aria-components'; +import {Popover} from 'vanilla-starter/Popover'; +import {Button} from 'vanilla-starter/Button'; @@ -165,7 +200,10 @@ Use the `` component to group options. A `
` element may als ```tsx render hideImports "use client"; -import {MenuTrigger, Menu, MenuItem, MenuSection, Header, Button, Popover} from 'react-aria-components'; +import {Header} from 'react-aria-components'; +import {MenuTrigger, Menu, MenuItem, MenuSection} from 'vanilla-starter/Menu'; +import {Popover} from 'vanilla-starter/Popover'; +import {Button} from 'vanilla-starter/Button'; @@ -196,8 +234,9 @@ Wrap a `` and a `` with a `` to create a subm ```tsx render hideImports "use client"; -import {MenuTrigger, Menu, Popover, SubmenuTrigger, Button, Popover} from 'react-aria-components'; -import {MenuItem} from 'vanilla-starter/Menu'; +import {MenuTrigger, SubmenuTrigger, Menu, MenuItem, MenuSection} from 'vanilla-starter/Menu'; +import {Popover} from 'vanilla-starter/Popover'; +import {Button} from 'vanilla-starter/Button'; @@ -215,12 +254,10 @@ import {MenuItem} from 'vanilla-starter/Menu'; Instagram Email - - - Work - Personal - - + + Work + Personal +
@@ -235,7 +272,10 @@ Separators may be added between menu items or sections in order to create non-la ```tsx render hideImports "use client"; -import {MenuTrigger, Menu, MenuItem, Separator, Button, Popover} from 'react-aria-components'; +import {MenuTrigger, Menu, MenuItem, MenuSection} from 'vanilla-starter/Menu'; +import {Separator} from 'react-aria-components'; +import {Popover} from 'vanilla-starter/Popover'; +import {Button} from 'vanilla-starter/Button'; @@ -263,7 +303,9 @@ Use the `href` prop on a `` to create a link. See the **client side ro ```tsx render hideImports "use client"; -import {MenuTrigger, Menu, MenuItem, Button, Popover} from 'react-aria-components'; +import {MenuTrigger, Menu, MenuItem, MenuSection} from 'vanilla-starter/Menu'; +import {Popover} from 'vanilla-starter/Popover'; +import {Button} from 'vanilla-starter/Button'; @@ -298,11 +340,11 @@ function Example() { return ( - + {/*- begin highlight -*/} - - + + {/*- end highlight -*/} News Travel @@ -328,7 +370,9 @@ Use the `selectionMode` prop to enable single or multiple selection. The selecte ```tsx render docs={docs.exports.Menu} links={docs.links} props={['selectionMode', 'disallowEmptySelection']} initialProps={{selectionMode: 'multiple'}} wide align="start" "use client"; import type {Selection} from 'react-aria-components'; -import {MenuTrigger, Menu, MenuItem, Button, Popover} from 'react-aria-components'; +import {MenuTrigger, Menu, MenuItem} from 'vanilla-starter/Menu'; +import {Button} from 'vanilla-starter/Button'; +import {Popover} from 'vanilla-starter/Popover'; import {useState} from 'react'; function Example(props) { @@ -368,7 +412,10 @@ Each section in a menu may have independent selection states by passing `selecti ```tsx render hideImports "use client"; import type {Selection} from 'react-aria-components'; -import {MenuTrigger, Menu, MenuItem, MenuSection, Header, Button, Popover} from 'react-aria-components'; +import {Header} from 'react-aria-components'; +import {MenuTrigger, Menu, MenuItem, MenuSection} from 'vanilla-starter/Menu'; +import {Button} from 'vanilla-starter/Button'; +import {Popover} from 'vanilla-starter/Popover'; import {useState} from 'react'; function Example() { @@ -417,7 +464,10 @@ function Example() { ```tsx render hideImports "use client"; -import {MenuTrigger, Menu, MenuItem, Button, Popover, Pressable} from 'react-aria-components'; +import {Pressable} from 'react-aria-components'; +import {MenuTrigger, Menu, MenuItem} from 'vanilla-starter/Menu'; +import {Button} from 'vanilla-starter/Button'; +import {Popover} from 'vanilla-starter/Popover'; {/*- begin highlight -*/} @@ -453,10 +503,16 @@ Use `trigger="longPress"` to open the menu on long press instead of on click/tap ```tsx render hideImports "use client"; -import {MenuTrigger, Menu, MenuItem, Button, Popover} from 'react-aria-components'; +import {MenuTrigger, Menu, MenuItem} from 'vanilla-starter/Menu'; +import {Button} from 'vanilla-starter/Button'; +import {Popover} from 'vanilla-starter/Popover'; +import {ChevronDown} from 'lucide-react'; - + Rotate diff --git a/packages/dev/s2-docs/pages/react-aria/Modal.mdx b/packages/dev/s2-docs/pages/react-aria/Modal.mdx index e2f5b0ca18b..9b317e3048f 100644 --- a/packages/dev/s2-docs/pages/react-aria/Modal.mdx +++ b/packages/dev/s2-docs/pages/react-aria/Modal.mdx @@ -19,8 +19,9 @@ export const tags = ['dialog', 'popup', 'overlay']; import {DialogTrigger, Heading} from 'react-aria-components'; import {Modal} from 'vanilla-starter/Modal'; import {Dialog} from 'vanilla-starter/Dialog'; - import {Button} from 'vanilla-starter/Button'; + import {Form} from 'vanilla-starter/Form'; import {TextField} from 'vanilla-starter/TextField'; + import {Button} from 'vanilla-starter/Button'; function Example(props) { return ( @@ -28,12 +29,16 @@ export const tags = ['dialog', 'popup', 'overlay']; -
- Sign up - - - - + Subscribe to our newsletter +

Enter your information to subscribe to our newsletter and receive updates about new features and announcements.

+
+ + +
+ + +
+
@@ -46,8 +51,9 @@ export const tags = ['dialog', 'popup', 'overlay']; import {DialogTrigger, Heading} from 'react-aria-components'; import {Modal} from 'tailwind-starter/Modal'; import {Dialog} from 'tailwind-starter/Dialog'; - import {Button} from 'tailwind-starter/Button'; + import {Form} from 'tailwind-starter/Form'; import {TextField} from 'tailwind-starter/TextField'; + import {Button} from 'tailwind-starter/Button'; function Example(props) { return ( @@ -55,12 +61,12 @@ export const tags = ['dialog', 'popup', 'overlay']; -
+ Sign up - - + +
diff --git a/packages/dev/s2-docs/pages/react-aria/MonthDropdown.tsx b/packages/dev/s2-docs/pages/react-aria/MonthDropdown.tsx index 68b6279cc9f..84c57a9e83b 100644 --- a/packages/dev/s2-docs/pages/react-aria/MonthDropdown.tsx +++ b/packages/dev/s2-docs/pages/react-aria/MonthDropdown.tsx @@ -37,7 +37,7 @@ export function MonthDropdown(): ReactElement { return ( {/*- begin highlight -*/} diff --git a/packages/dev/s2-docs/pages/react-aria/Table.mdx b/packages/dev/s2-docs/pages/react-aria/Table.mdx index d1edbdb9d86..74556365ad2 100644 --- a/packages/dev/s2-docs/pages/react-aria/Table.mdx +++ b/packages/dev/s2-docs/pages/react-aria/Table.mdx @@ -16,8 +16,7 @@ export const tags = ['data', 'grid']; ```tsx render docs={docs.exports.Table} links={docs.links} props={['selectionMode']} initialProps={{'aria-label': 'Files', selectionMode: 'multiple'}} type="vanilla" files={["starters/docs/src/Table.tsx", "starters/docs/src/Table.css"]} "use client"; - import {Table, TableHeader, Column, Row} from 'vanilla-starter/Table'; - import {TableBody, Cell} from 'react-aria-components'; + import {Table, TableHeader, Column, Row, TableBody, Cell} from 'vanilla-starter/Table'; @@ -95,8 +94,7 @@ In this example, both the columns and the rows are provided to the table via a r ```tsx render "use client"; -import {Table, TableHeader, Column, Row} from 'vanilla-starter/Table'; -import {TableBody, Cell} from 'react-aria-components'; +import {Table, TableHeader, Column, Row, TableBody, Cell} from 'vanilla-starter/Table'; import {CheckboxGroup} from 'vanilla-starter/CheckboxGroup'; import {Checkbox} from 'vanilla-starter/Checkbox'; import {Button} from 'vanilla-starter/Button'; @@ -134,7 +132,7 @@ function FileTable() { return (
- + Type Date Modified @@ -174,8 +172,8 @@ Use [renderEmptyState](#empty-state) to display a spinner during initial load. T ```tsx render "use client"; -import {Table, TableHeader, Column, Row, TableBody, Cell} from 'vanilla-starter/Table'; -import {Collection, TableLoadMoreItem} from 'react-aria-components'; +import {Table, TableHeader, Column, Row, TableBody, Cell, TableLoadMoreItem} from 'vanilla-starter/Table'; +import {Collection} from 'react-aria-components'; import {ProgressCircle} from 'vanilla-starter/ProgressCircle'; import {useAsyncList} from 'react-stately'; @@ -211,8 +209,8 @@ function AsyncSortTable() { style={{ height: 150, overflow: 'auto', - border: '1px solid var(--border-color)', - borderRadius: 6 + border: '0.5px solid var(--border-color)', + borderRadius: 'var(--radius)' }}>
- Name - Height - Mass - Birth Year + Name + Height + Mass + Birth Year ( @@ -246,9 +244,7 @@ function AsyncSortTable() { {/*- begin highlight -*/} - - + isLoading={list.loadingState === 'loadingMore'} /> {/*- end highlight -*/}
@@ -263,8 +259,7 @@ Use the `href` prop on a `` to create a link. See the **client side routing ```tsx render docs={docs.exports.ListBox} links={docs.links} props={['selectionBehavior']} initialProps={{'aria-label': 'Bookmarks', selectionMode: 'multiple'}} wide "use client"; -import {Table, TableHeader, Column, Row} from 'vanilla-starter/Table'; -import {TableBody, Cell} from 'react-aria-components'; +import {Table, TableHeader, Column, Row, TableBody, Cell} from 'vanilla-starter/Table'; @@ -298,8 +293,7 @@ import {TableBody, Cell} from 'react-aria-components'; ```tsx render hideImports "use client"; -import {Table, TableHeader, Column, Row} from 'vanilla-starter/Table'; -import {TableBody, Cell} from 'react-aria-components'; +import {Table, TableHeader, Column, Row, TableBody, Cell} from 'vanilla-starter/Table';
@@ -322,15 +316,14 @@ Use the `selectionMode` prop to enable single or multiple selection. The selecte ```tsx render docs={docs.exports.Table} links={docs.links} props={['selectionMode', 'selectionBehavior', 'disabledBehavior', 'disallowEmptySelection']} initialProps={{selectionMode: 'multiple'}} wide "use client"; import type {Selection} from 'react-aria-components'; -import {Table, TableHeader, Column, Row} from 'vanilla-starter/Table'; -import {TableBody, Cell} from 'react-aria-components'; +import {Table, TableHeader, Column, Row, TableBody, Cell} from 'vanilla-starter/Table'; import {useState} from 'react'; function Example(props) { let [selected, setSelected] = useState(new Set()); return ( -
+ <>

Current selection: {selected === 'all' ? 'all' : [...selected].join(', ')}

-
+ ); } ``` @@ -381,8 +374,8 @@ Set the `allowsSorting` prop on a `` to make it sortable. When the colum ```tsx render "use client"; -import {Table, TableHeader, Column, Row} from 'vanilla-starter/Table'; -import {TableBody, Cell, type SortDescriptor} from 'react-aria-components'; +import {type SortDescriptor} from 'react-aria-components'; +import {Table, TableHeader, Column, TableBody, Row, Cell} from 'vanilla-starter/Table'; import {useState} from 'react'; ///- begin collapse -/// @@ -395,7 +388,11 @@ const rows = [ ///- end collapse -/// function SortableTable() { - let [sortDescriptor, setSortDescriptor] = useState(null); + let [sortDescriptor, setSortDescriptor] = useState({ + column: 'name', + direction: 'ascending' + }); + let sortedRows = rows; if (sortDescriptor) { sortedRows = rows.toSorted((a, b) => { @@ -442,8 +439,8 @@ Wrap the `` with a ``, and add a ` {/*- begin highlight -*/} - -
- File Name - -
-
- Size - -
- Date Modified - -
-
+ File Name + Size + Date Modified {/*- end highlight -*/}
@@ -492,8 +479,8 @@ The ResizableTableContainer's `onResize` event is called when a column resizer i ```tsx render "use client"; -import {Table, TableHeader, Column, Row} from 'vanilla-starter/Table'; -import {ResizableTableContainer, ColumnResizer, TableBody, Cell} from 'react-aria-components'; +import {Table, TableHeader, Column, Row, TableBody, Cell} from 'vanilla-starter/Table'; +import {ResizableTableContainer} from 'react-aria-components'; import {useSyncExternalStore} from 'react'; ///- begin collapse -/// @@ -533,14 +520,12 @@ export default function ResizableTable() { {column => ( -
- {column.name} - -
+ {column.name}
)} diff --git a/packages/dev/s2-docs/pages/react-aria/TextField.mdx b/packages/dev/s2-docs/pages/react-aria/TextField.mdx index 55deb3f373b..ab9d9c0702e 100644 --- a/packages/dev/s2-docs/pages/react-aria/TextField.mdx +++ b/packages/dev/s2-docs/pages/react-aria/TextField.mdx @@ -20,7 +20,7 @@ export const tags = ['input']; docs={vanillaDocs.exports.TextField} links={vanillaDocs.links} props={['label', 'description', 'isReadOnly', 'isDisabled']} - initialProps={{label: 'Name'}} + initialProps={{label: 'Name', placeholder: 'Enter your full name'}} type="vanilla" files={["starters/docs/src/TextField.tsx", "starters/docs/src/TextField.css"]} /> @@ -49,6 +49,7 @@ function Example() { <> @@ -67,7 +68,7 @@ Use the `name` prop to submit the text value to the server. Set the `isRequired` "use client"; import {TextField} from 'vanilla-starter/TextField'; import {Button} from 'vanilla-starter/Button'; -import {Form} from 'react-aria-components'; +import {Form} from 'vanilla-starter/Form';; function Example(props) { return ( @@ -75,6 +76,7 @@ function Example(props) { -