diff --git a/packages/@react-spectrum/s2/src/Picker.tsx b/packages/@react-spectrum/s2/src/Picker.tsx
index 34f5aa97b8b..1349668cfe1 100644
--- a/packages/@react-spectrum/s2/src/Picker.tsx
+++ b/packages/@react-spectrum/s2/src/Picker.tsx
@@ -740,7 +740,7 @@ function DefaultProvider({context, value, children}: {context: React.Context
{children};
}
-export interface PickerSectionProps extends Omit, 'style' | 'className' | 'render' | keyof GlobalDOMAttributes>, StyleProps {}
+export interface PickerSectionProps extends Omit, 'style' | 'className' | 'render' | keyof GlobalDOMAttributes> {}
export function PickerSection(props: PickerSectionProps): ReactNode {
let {size} = useContext(InternalPickerContext);
return (
diff --git a/packages/@react-spectrum/s2/stories/TableView.stories.tsx b/packages/@react-spectrum/s2/stories/TableView.stories.tsx
index f37a8976606..45ce91272e3 100644
--- a/packages/@react-spectrum/s2/stories/TableView.stories.tsx
+++ b/packages/@react-spectrum/s2/stories/TableView.stories.tsx
@@ -49,8 +49,9 @@ import User from '../s2wf-icons/S2_Icon_User_20_N.svg';
import {useTreeData} from 'react-stately/useTreeData';
let onActionFunc = action('onAction');
-let noOnAction = undefined;
+let noOnAction = null;
const onActionOptions = {onActionFunc, noOnAction};
+
const events = ['onResizeStart', 'onResize', 'onResizeEnd', 'onSelectionChange', 'onSortChange'];
const meta: Meta = {
@@ -62,7 +63,7 @@ const meta: Meta = {
tags: ['autodocs'],
args: {...getActionArgs(events)},
argTypes: {
- ...categorizeArgTypes('Events', ['onAction', 'onLoadMore', ...events]),
+ ...categorizeArgTypes('Events', ['onAction', 'onLoadMore', 'onResizeStart', 'onResize', 'onResizeEnd', 'onSelectionChange', 'onSortChange']),
children: {table: {disable: true}},
onAction: {
options: Object.keys(onActionOptions), // An array of serializable values
@@ -1783,7 +1784,7 @@ export const TableWithNestedRows: StoryObj = {
5/22/1980 |
-
+
| Applications |
Folder |
4/7/2025 |
diff --git a/packages/@react-spectrum/s2/stories/TreeView.stories.tsx b/packages/@react-spectrum/s2/stories/TreeView.stories.tsx
index d28392e2568..b9bebd80f52 100644
--- a/packages/@react-spectrum/s2/stories/TreeView.stories.tsx
+++ b/packages/@react-spectrum/s2/stories/TreeView.stories.tsx
@@ -45,9 +45,9 @@ import {useAsyncList} from 'react-stately/useAsyncList';
import {useListData} from 'react-stately/useListData';
let onActionFunc = action('onAction');
-let noOnAction = undefined;
+let noOnAction = null;
const onActionOptions = {onActionFunc, noOnAction};
-const events = ['onSelectionChange'];
+const events = ['onSelectionChange', 'onAction'];
const meta: Meta = {
component: TreeView,
@@ -57,7 +57,7 @@ const meta: Meta = {
tags: ['autodocs'],
args: {...getActionArgs(events)},
argTypes: {
- ...categorizeArgTypes('Events', ['onAction', ...events]),
+ ...categorizeArgTypes('Events', events),
children: {table: {disable: true}},
onAction: {
options: Object.keys(onActionOptions), // An array of serializable values
@@ -81,7 +81,7 @@ const TreeExampleStatic = (args: TreeViewProps): ReactElement => (
diff --git a/packages/@react-spectrum/s2/style/index.ts b/packages/@react-spectrum/s2/style/index.ts
index f21fc0ea971..ad6120f7d6c 100644
--- a/packages/@react-spectrum/s2/style/index.ts
+++ b/packages/@react-spectrum/s2/style/index.ts
@@ -28,7 +28,7 @@ export type {StyleString} from './types';
*
* @example
* ```tsx
- * import {space} from '@react-spectrum/s2/style' with {type: 'macro'};
+ * import {space, style} from '@react-spectrum/s2/style' with {type: 'macro'};
*
* const styles = style({
* gap: space(12) // 12/16 = 0.75rem
@@ -49,7 +49,7 @@ export function space(px: number): `[${string}]` {
*
* @example
* ```tsx
- * import {fontRelative} from '@react-spectrum/s2/style' with {type: 'macro'};
+ * import {fontRelative, style} from '@react-spectrum/s2/style' with {type: 'macro'};
*
* const styles = style({
* gap: fontRelative(2) // 2/14 = ~0.143em
@@ -135,7 +135,7 @@ const iconSizes = {
* ```tsx
* import {iconStyle} from '@react-spectrum/s2/style' with {type: 'macro'};
* import Edit from '@react-spectrum/s2/icons/Edit';
- *
+ *
*
* ```
*/
diff --git a/packages/dev/s2-docs/pages/react-aria/RangeCalendar.mdx b/packages/dev/s2-docs/pages/react-aria/RangeCalendar.mdx
index 510d219a325..53a972761a4 100644
--- a/packages/dev/s2-docs/pages/react-aria/RangeCalendar.mdx
+++ b/packages/dev/s2-docs/pages/react-aria/RangeCalendar.mdx
@@ -21,14 +21,14 @@ export const description = 'Displays one or more date grids and allows users to
component={VanillaRangeCalendar}
docs={vanillaDocs.exports.RangeCalendar}
links={vanillaDocs.links}
- props={['isDisabled', 'interactOutsideBehavior']}
+ props={['isDisabled', 'commitBehavior']}
type="vanilla"
files={["starters/docs/src/RangeCalendar.tsx", "starters/docs/src/RangeCalendar.css"]} />
diff --git a/packages/dev/s2-docs/pages/react-aria/TagGroup.mdx b/packages/dev/s2-docs/pages/react-aria/TagGroup.mdx
index 5aeaaecc903..972fefa34b5 100644
--- a/packages/dev/s2-docs/pages/react-aria/TagGroup.mdx
+++ b/packages/dev/s2-docs/pages/react-aria/TagGroup.mdx
@@ -101,7 +101,7 @@ import {TagGroup, Tag} from 'vanilla-starter/TagGroup';
Due to [HTML spec limitations](https://github.com/w3c/html-aria/issues/473), tags cannot be rendered as `` elements. React Aria handles link clicks with JavaScript and triggers native navigation. When using a client-side router, use the `onAction` event to programmatically trigger navigation instead of the `href` prop.
-## Selection
+## 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. Items can be disabled with the `isDisabled` prop. See the [selection guide](selection?component=TagGroup) for more details.
@@ -137,6 +137,30 @@ function Example(props) {
}
```
+Use the `onAction` prop to handle item actions.
+
+```tsx render wide
+"use client";
+import {TagGroup, Tag} from 'vanilla-starter/TagGroup';
+
+function Example() {
+ return (
+ alert(`Clicked ${key}`)}
+ ///- end highlight -///
+ >
+ Rock
+ Jazz
+ Pop
+ Classical
+ EDM
+
+ );
+}
+```
+
## Examples
diff --git a/packages/dev/s2-docs/pages/react-aria/frameworks.mdx b/packages/dev/s2-docs/pages/react-aria/frameworks.mdx
index a8f22dac396..04c1288126c 100644
--- a/packages/dev/s2-docs/pages/react-aria/frameworks.mdx
+++ b/packages/dev/s2-docs/pages/react-aria/frameworks.mdx
@@ -73,6 +73,9 @@ export const description = 'How to integrate with your framework.';
}
```
+
+ If you are using a [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) (CSP) with a nonce, add a `` tag to your document head, setting the `content` attribute to the generated nonce value. React Aria automatically reads the nonce from this tag.
+
@@ -184,6 +187,9 @@ export const description = 'How to integrate with your framework.';
});
```
+
+ If you are using a [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) (CSP) with a nonce, add a `` tag to your document head, setting the `content` attribute to the generated nonce value. React Aria automatically reads the nonce from this tag.
+
@@ -213,6 +219,9 @@ export const description = 'How to integrate with your framework.';
}
```
+
+ If you are using a [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) (CSP) with a nonce, add a `` tag to your document head, setting the `content` attribute to the generated nonce value. React Aria automatically reads the nonce from this tag.
+
@@ -243,6 +252,9 @@ export const description = 'How to integrate with your framework.';
});
```
+
+ If you are using a [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) (CSP) with a nonce, configure [`html.cspNonce`](https://vite.dev/config/shared-options.html#html-cspnonce) in `vite.config.ts`. React Aria automatically reads the nonce that Vite injects.
+
@@ -270,6 +282,9 @@ export const description = 'How to integrate with your framework.';
};
```
+
+ If you are using a [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) (CSP) with a nonce, configure [`__webpack_nonce__`](https://webpack.js.org/guides/csp/) in your entry script. React Aria automatically reads the nonce from the webpack global.
+
@@ -297,6 +312,9 @@ export const description = 'How to integrate with your framework.';
};
```
+
+ If you are using a [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) (CSP) with a nonce, add a `` tag to your document head, setting the `content` attribute to the generated nonce value. React Aria automatically reads the nonce from this tag.
+
@@ -324,6 +342,9 @@ export const description = 'How to integrate with your framework.';
});
```
+
+ If you are using a [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) (CSP) with a nonce, add a `` tag to your document head, setting the `content` attribute to the generated nonce value. React Aria automatically reads the nonce from this tag.
+
diff --git a/packages/dev/s2-docs/pages/s2/RangeCalendar.mdx b/packages/dev/s2-docs/pages/s2/RangeCalendar.mdx
index 1ee9a4285dc..d421d1130bc 100644
--- a/packages/dev/s2-docs/pages/s2/RangeCalendar.mdx
+++ b/packages/dev/s2-docs/pages/s2/RangeCalendar.mdx
@@ -15,7 +15,7 @@ export const description = 'Allows a user to select a contiguous range of dates.
component={RangeCalendar}
docs={docs.exports.RangeCalendar}
links={docs.links}
- props={['visibleMonths', 'pageBehavior', 'firstDayOfWeek', 'isDisabled', 'interactOutsideBehavior']}
+ props={['visibleMonths', 'pageBehavior', 'firstDayOfWeek', 'isDisabled', 'commitBehavior']}
initialProps={{'aria-label': 'Trip dates'}}
controlOptions={{
visibleMonths: {
diff --git a/packages/dev/s2-docs/pages/s2/TableView.mdx b/packages/dev/s2-docs/pages/s2/TableView.mdx
index 176e17fe035..6b40b756d0e 100644
--- a/packages/dev/s2-docs/pages/s2/TableView.mdx
+++ b/packages/dev/s2-docs/pages/s2/TableView.mdx
@@ -14,14 +14,13 @@ export const description = 'Displays data in rows and columns, with row selectio
{docs.exports.TableView.description}
-```tsx render docs={docs.exports.TableView} links={docs.links} props={['selectionMode', 'overflowMode', 'density', 'isQuiet', 'disabledBehavior']} initialProps={{'aria-label': 'Files', selectionMode: 'multiple', 'treeColumn': 'name', disabledBehavior: 'selection'}} type="s2"
+```tsx render docs={docs.exports.TableView} links={docs.links} props={['selectionMode', 'overflowMode', 'density', 'isQuiet']} initialProps={{'aria-label': 'Files', selectionMode: 'multiple', 'treeColumn': 'name'}} type="s2"
"use client";
import {TableView, TableHeader, Column, TableBody, Row, Cell} from '@react-spectrum/s2/TableView';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
Name
@@ -644,7 +643,7 @@ export default function EditableTable(props) {
Use `selectionMode` to enable single or multiple selection, and `selectedKeys` (matching each row's `id`) to control the selected rows. Return an [ActionBar](ActionBar) from `renderActionBar` to handle bulk actions, and use `onAction` for row navigation. Disable rows with `isDisabled`. See the [selection guide](selection) for details.
-```tsx render docs={docs.exports.TableView} links={docs.links} props={['selectionMode', 'disallowEmptySelection']} initialProps={{selectionMode: 'multiple'}} wide type="s2"
+```tsx render docs={docs.exports.TableView} links={docs.links} props={['selectionMode', 'disallowEmptySelection', 'disabledBehavior']} initialProps={{selectionMode: 'multiple', disabledBehavior: 'selection'}} wide type="s2"
"use client";
import {TableView, TableHeader, Column, TableBody, Row, Cell, type Selection} from '@react-spectrum/s2/TableView';
import {ActionBar, ActionButton} from '@react-spectrum/s2/ActionBar';
@@ -975,4 +974,4 @@ function subscribe(fn) {
### EditableCell
-
\ No newline at end of file
+
diff --git a/packages/dev/s2-docs/pages/s2/TagGroup.mdx b/packages/dev/s2-docs/pages/s2/TagGroup.mdx
index c9bf4761b17..2bf7bd5f5f5 100644
--- a/packages/dev/s2-docs/pages/s2/TagGroup.mdx
+++ b/packages/dev/s2-docs/pages/s2/TagGroup.mdx
@@ -201,7 +201,7 @@ import {Link} from '@react-spectrum/s2/Link';
```
-## Selection
+## 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. Items can be disabled with the `isDisabled` prop. See the [selection guide](selection?component=TagGroup) for more details.
@@ -235,6 +235,30 @@ function Example(props) {
}
```
+Use the `onAction` prop to handle item actions.
+
+```tsx render wide
+"use client";
+import {TagGroup, Tag} from '@react-spectrum/s2/TagGroup';
+
+function Example() {
+ return (
+ alert(`Clicked ${key}`)}
+ ///- end highlight -///
+ >
+ Rock
+ Jazz
+ Pop
+ Classical
+ EDM
+
+ );
+}
+```
+
## Group actions
diff --git a/packages/dev/s2-docs/pages/s2/migrating.mdx b/packages/dev/s2-docs/pages/s2/migrating.mdx
index 60b56f423b7..aead11d60a0 100644
--- a/packages/dev/s2-docs/pages/s2/migrating.mdx
+++ b/packages/dev/s2-docs/pages/s2/migrating.mdx
@@ -368,10 +368,7 @@ No updates needed.
- For dynamic tables, pass a `columns` prop into `Row`
- For `Row`: Update dynamic render function to pass in `column` instead of `columnKey`
- Move `loadingState` and `onLoadMore` from `TableBody` to `TableView`
-- Comment out `UNSTABLE_allowsExpandableRows` (it has not been implemented yet)
-- Comment out `UNSTABLE_onExpandedChange` (it has not been implemented yet)
-- Comment out `UNSTABLE_expandedKeys` (it has not been implemented yet)
-- Comment out `UNSTABLE_defaultExpandedKeys` (it has not been implemented yet)
+- For expandable rows, use `treeColumn` to designate your expandable column. `defaultExpanded`, `expandedKeys`, and `onExpandedChange` can be used to set and update your expanded rows. See the [TableView](TableView#expandable-rows) documentation for more details.
### Tabs
diff --git a/packages/react-aria-components/src/Table.tsx b/packages/react-aria-components/src/Table.tsx
index cfd6413d281..6d7179d6cd4 100644
--- a/packages/react-aria-components/src/Table.tsx
+++ b/packages/react-aria-components/src/Table.tsx
@@ -1377,7 +1377,6 @@ export const Row = /*#__PURE__*/ createBranchComponent(
isFocusVisible: isFocusVisibleWithin,
focusProps: focusWithinProps
} = useFocusRing({within: true});
-
let {hoverProps, isHovered} = useHover({
isDisabled: !states.allowsSelection && !states.hasAction,
onHoverStart: props.onHoverStart,
diff --git a/packages/react-aria-components/src/TagGroup.tsx b/packages/react-aria-components/src/TagGroup.tsx
index d0fc46fcc55..491da128447 100644
--- a/packages/react-aria-components/src/TagGroup.tsx
+++ b/packages/react-aria-components/src/TagGroup.tsx
@@ -244,7 +244,12 @@ export interface TagProps extends RenderProps, LinkDOMPro
*/
textValue?: string,
/** Whether the tag is disabled. */
- isDisabled?: boolean
+ isDisabled?: boolean,
+ /**
+ * Handler that is called when a user performs an action on the item. The exact user event depends on
+ * the collection's `selectionBehavior` prop and the interaction modality.
+ */
+ onAction?: () => void
}
/**
diff --git a/packages/react-aria-components/test/TagGroup.test.js b/packages/react-aria-components/test/TagGroup.test.js
index 6ec421718ec..9964bd1a3c3 100644
--- a/packages/react-aria-components/test/TagGroup.test.js
+++ b/packages/react-aria-components/test/TagGroup.test.js
@@ -661,6 +661,19 @@ describe('TagGroup', () => {
expect(onAction).toHaveBeenCalledTimes(1);
});
+ it('should support onAction on the items', async () => {
+ let onAction = jest.fn();
+ let {getAllByRole} = renderTagGroup({selectionMode: 'none'}, {}, {onAction});
+ let items = getAllByRole('row');
+
+ await user.click(items[0]);
+ expect(onAction).toHaveBeenCalledTimes(1);
+ onAction.mockReset();
+
+ await user.keyboard('{Enter}');
+ expect(onAction).toHaveBeenCalledTimes(1);
+ });
+
it('should support onAction with selectionMode = single, behaviour = replace', async () => {
let onAction = jest.fn();
let {getAllByRole} = renderTagGroup({onAction, selectionMode: 'single', selectionBehavior: 'replace'});
diff --git a/packages/react-aria-components/test/Tree.test.tsx b/packages/react-aria-components/test/Tree.test.tsx
index d9028b55ddc..434ac46e58a 100644
--- a/packages/react-aria-components/test/Tree.test.tsx
+++ b/packages/react-aria-components/test/Tree.test.tsx
@@ -751,36 +751,6 @@ describe('Tree', () => {
expect(onSelectionChange).toHaveBeenCalledTimes(0);
});
- it('multi select should expand the row if anywhere on the row is clicked and there is no onAction provided', async () => {
- let {getAllByRole} = render();
- let row = getAllByRole('row')[1];
- await user.hover(row);
- expect(row).toHaveAttribute('data-hovered', 'true');
-
- await user.click(row);
- expect(row).toHaveAttribute('aria-expanded', 'true');
- });
-
- it('single select should expand the row if anywhere on the row is clicked and there is no onAction provided', async () => {
- let {getAllByRole} = render();
- let row = getAllByRole('row')[1];
- await user.hover(row);
- expect(row).toHaveAttribute('data-hovered', 'true');
-
- await user.click(row);
- expect(row).toHaveAttribute('aria-expanded', 'true');
- });
-
- it('no selection should expand the row if anywhere on the row is clicked and there is no onAction provided', async () => {
- let {getAllByRole} = render();
- let row = getAllByRole('row')[1];
- await user.hover(row);
- expect(row).toHaveAttribute('data-hovered', 'true');
-
- await user.click(row);
- expect(row).toHaveAttribute('aria-expanded', 'true');
- });
-
it('should prevent Esc from clearing selection if escapeKeyBehavior is "none"', async () => {
let {getAllByRole} = render();
diff --git a/packages/react-aria-components/test/Treeble.test.tsx b/packages/react-aria-components/test/Treeble.test.js
similarity index 93%
rename from packages/react-aria-components/test/Treeble.test.tsx
rename to packages/react-aria-components/test/Treeble.test.js
index bd87825ea02..404e2f6847c 100644
--- a/packages/react-aria-components/test/Treeble.test.tsx
+++ b/packages/react-aria-components/test/Treeble.test.js
@@ -98,15 +98,8 @@ function Example(props) {
);
}
-interface ReorderableTreebleItem {
- id: string,
- title: string,
- type: string,
- date: string,
- children?: ReorderableTreebleItem[]
-}
function ReorderableTreeble(props) {
- let tree = useTreeData({
+ let tree = useTreeData({
initialItems: [
{id: '1', title: 'Documents', type: 'Directory', date: '10/20/2025', children: [
{id: '2', title: 'Project', type: 'Directory', date: '8/2/2025', children: [
@@ -121,7 +114,7 @@ function ReorderableTreeble(props) {
]
});
- let {dragAndDropHooks} = useDragAndDrop<{value: ReorderableTreebleItem}>({
+ let {dragAndDropHooks} = useDragAndDrop({
getItems: (keys, items) => items.map(item => ({'text/plain': item.value.title})),
onMove(e) {
if (e.target.dropPosition === 'before') {
@@ -246,7 +239,7 @@ describe('Treeble', () => {
expect(tester.rowHeaders[3]).toHaveTextContent('Job Posting');
});
- it.each(['mouse', 'touch', 'keyboard'] as const)('should expand a row with %s', async (interactionType) => {
+ it.each(['mouse', 'touch', 'keyboard'])('should expand a row with %s', async (interactionType) => {
let tree = render();
let tester = utils.createTester('Table', {root: tree.getByTestId('treeble')});
@@ -536,39 +529,6 @@ describe('Treeble', () => {
expect(onSelectionChange).toHaveBeenLastCalledWith(new Set(['games', 'mario', 'tetris']));
});
- it('supports expansion on disabled items with no action in disabledBehavior="selection" multiple selection', async () => {
- let tree = render();
- let tester = utils.createTester('Table', {root: tree.getByTestId('treeble')});
-
- await user.hover(tester.rows[1]);
- expect(tester.rows[1]).toHaveAttribute('data-hovered', 'true');
-
- await user.click(tester.rows[1]);
- expect(tester.rows[1]).toHaveAttribute('aria-expanded', 'true');
- });
-
- it('supports expansion on disabled items with no action in disabledBehavior="selection" single selection', async () => {
- let tree = render();
- let tester = utils.createTester('Table', {root: tree.getByTestId('treeble')});
-
- await user.hover(tester.rows[1]);
- expect(tester.rows[1]).toHaveAttribute('data-hovered', 'true');
-
- await user.click(tester.rows[1]);
- expect(tester.rows[1]).toHaveAttribute('aria-expanded', 'true');
- });
-
- it('supports expansion on disabled items with no action in disabledBehavior="selection" no selection', async () => {
- let tree = render();
- let tester = utils.createTester('Table', {root: tree.getByTestId('treeble')});
-
- await user.hover(tester.rows[1]);
- expect(tester.rows[1]).toHaveAttribute('data-hovered', 'true');
-
- await user.click(tester.rows[1]);
- expect(tester.rows[1]).toHaveAttribute('aria-expanded', 'true');
- });
-
it('should support drag and drop', async () => {
let tree = render();
let tester = utils.createTester('Table', {root: tree.getByRole('treegrid')});
diff --git a/packages/react-aria/src/calendar/useRangeCalendar.ts b/packages/react-aria/src/calendar/useRangeCalendar.ts
index 609ab55ea9d..04be782ab93 100644
--- a/packages/react-aria/src/calendar/useRangeCalendar.ts
+++ b/packages/react-aria/src/calendar/useRangeCalendar.ts
@@ -20,7 +20,7 @@ import {useRef} from 'react';
export interface AriaRangeCalendarProps extends RangeCalendarProps, DOMProps, AriaLabelingProps {
/**
- * Controls the behavior when a pointer is released outside the calendar:
+ * Controls the behavior when a pointer is released outside the calendar or a blur occurs mid selection:
*
* - `clear`: clear the currently selected range of dates.
*
@@ -29,7 +29,7 @@ export interface AriaRangeCalendarProps extends RangeCalend
* - `select`: select the currently hovered range of dates.
* @default 'select'
*/
- interactOutsideBehavior?: 'clear' | 'reset' | 'select'
+ commitBehavior?: 'clear' | 'reset' | 'select'
}
/**
@@ -37,7 +37,7 @@ export interface AriaRangeCalendarProps extends RangeCalend
* A range calendar displays one or more date grids and allows users to select a contiguous range of dates.
*/
export function useRangeCalendar(props: AriaRangeCalendarProps, state: RangeCalendarState, ref: RefObject): CalendarAria {
- let {interactOutsideBehavior = 'select', ...otherProps} = props;
+ let {commitBehavior = 'select', ...otherProps} = props;
let res = useCalendarBase(otherProps, state);
// We need to ignore virtual pointer events from VoiceOver due to these bugs.
@@ -52,13 +52,13 @@ export function useRangeCalendar(props: AriaRangeCalendarPr
isVirtualClick.current = e.width === 0 && e.height === 0;
});
- const interactOutsideBehaviorMapping = {
+ const commitBehaviorMapping = {
clear: () => state.clearSelection(),
reset: () => state.setAnchorDate(null),
select: () => state.selectFocusedDate()
};
- // Execute method corresponding to `interactOutsideBehavior` when pressing or releasing a pointer outside the calendar body,
+ // Execute method corresponding to `commitBehavior` when pressing or releasing a pointer outside the calendar body,
// except when pressing the next or previous buttons to switch months.
let endDragging = (e: PointerEvent) => {
if (isVirtualClick.current) {
@@ -77,13 +77,13 @@ export function useRangeCalendar(props: AriaRangeCalendarPr
isFocusWithin(ref.current) &&
(!nodeContains(ref.current, target) || !target.closest('button, [role="button"]'))
) {
- interactOutsideBehaviorMapping[interactOutsideBehavior]();
+ commitBehaviorMapping[commitBehavior]();
}
};
useEvent(windowRef, 'pointerup', endDragging);
- // Also execute method corresponding to `interactOutsideBehavior` on blur,
+ // Also execute method corresponding to `commitBehavior` on blur,
// e.g. tabbing away from the calendar.
res.calendarProps.onBlur = e => {
if (!ref.current) {
@@ -91,7 +91,7 @@ export function useRangeCalendar(props: AriaRangeCalendarPr
}
if ((!e.relatedTarget || !nodeContains(ref.current, e.relatedTarget)) && state.anchorDate) {
- interactOutsideBehaviorMapping[interactOutsideBehavior]();
+ commitBehaviorMapping[commitBehavior]();
}
};
diff --git a/packages/react-aria/src/dialog/useDialog.ts b/packages/react-aria/src/dialog/useDialog.ts
index 8d6f503252f..8a2015231fa 100644
--- a/packages/react-aria/src/dialog/useDialog.ts
+++ b/packages/react-aria/src/dialog/useDialog.ts
@@ -90,7 +90,7 @@ export function useDialog(props: AriaDialogProps, ref: RefObject, S extends GridState actions.onRowAction?.(node.key) : onAction;
-
- // Mirror useGridListItem: when no row action is provided, expandable tree-table rows use toggle as the
- // primary action if selection is off or the row is selection-disabled (disabledKeys / selection behavior).
- if (
- node != null &&
- 'treeColumn' in state &&
- state.treeColumn != null &&
- // I'd prefer if this was up in useTableRow, but onAction is a deprecated prop
- // and maybe we'll move the expandable rows down into useGridRow eventually
- 'toggleKey' in state &&
- typeof state.toggleKey === 'function' &&
- actions.onRowAction == null &&
- onAction == null
- ) {
- // adds the toggleKey type so it's not unknown below
- let tableState = state as typeof state & {toggleKey: (key: Key) => void};
- let children = tableState.collection.getChildren?.(node.key);
- let hasChildRows = [...(children ?? [])].length > 1;
- let hasLink = state.selectionManager.isLink(node.key);
- if (
- !hasLink &&
- hasChildRows &&
- ((state.disabledKeys.has(node.key) || node.props?.isDisabled) ||
- state.selectionManager.selectionMode === 'none')) {
- onRowAction = () => tableState.toggleKey(node.key);
- }
- }
-
let {itemProps, ...states} = useSelectableItem({
selectionManager: state.selectionManager,
key: node.key,
diff --git a/packages/react-aria/src/gridlist/useGridListItem.ts b/packages/react-aria/src/gridlist/useGridListItem.ts
index 844dbaafbd2..c2ab564852c 100644
--- a/packages/react-aria/src/gridlist/useGridListItem.ts
+++ b/packages/react-aria/src/gridlist/useGridListItem.ts
@@ -102,12 +102,7 @@ export function useGridListItem(props: AriaGridListItemOptions, state: ListSt
let children = state.collection.getChildren?.(node.key);
hasChildRows = hasChildRows || [...(children ?? [])].length > 1;
- if (
- onAction == null &&
- !hasLink &&
- hasChildRows &&
- ((state.disabledKeys.has(node.key) || node.props?.isDisabled) ||
- state.selectionManager.selectionMode === 'none')) {
+ if (onAction == null && !hasLink && state.selectionManager.selectionMode === 'none' && hasChildRows) {
onAction = () => state.toggleKey(node.key);
}