From d2b7a2cd568141be7f108627b13fae3e185ff3ed Mon Sep 17 00:00:00 2001 From: hasegawa-101 Date: Fri, 14 Nov 2025 01:59:48 +0900 Subject: [PATCH 01/14] Add `onKeyDown` prop to ListBoxItem for custom keyboard handling --- .../react-aria-components/docs/ListBox.mdx | 40 +++++++++++++++++ .../react-aria-components/src/ListBox.tsx | 8 +++- .../stories/ListBox.stories.tsx | 43 +++++++++++++++++++ 3 files changed, 89 insertions(+), 2 deletions(-) diff --git a/packages/react-aria-components/docs/ListBox.mdx b/packages/react-aria-components/docs/ListBox.mdx index dae009ba866..8dd6b940bfe 100644 --- a/packages/react-aria-components/docs/ListBox.mdx +++ b/packages/react-aria-components/docs/ListBox.mdx @@ -409,6 +409,46 @@ By default, link items in a ListBox are not selectable, and only perform navigat The `` component works with frameworks and client side routers like [Next.js](https://nextjs.org/) and [React Router](https://reactrouter.com/en/main). As with other React Aria components that support links, this works via the component at the root of your app. See the [client side routing guide](routing.html) to learn how to set this up. +## Custom keyboard handling + +ListBox supports custom keyboard event handling on individual items via the `onKeyDown` prop on `ListBoxItem`. This enables you to implement additional keyboard interactions beyond the built-in selection and navigation behavior, such as deleting items with the Backspace or Delete keys. + +```tsx example +import {useListData} from 'react-stately'; + +function Example() { + let list = useListData({ + initialItems: [ + {id: 1, name: 'Item 1'}, + {id: 2, name: 'Item 2'}, + {id: 3, name: 'Item 3'}, + {id: 4, name: 'Item 4'}, + {id: 5, name: 'Item 5'} + ] + }); + + let handleKeyDown = (key: React.Key) => (e: React.KeyboardEvent) => { + if (e.key === 'Delete' || e.key === 'Backspace') { + e.preventDefault(); + list.remove(key); + } + }; + + return ( + + {item => ( + + {item.name} + + )} + + ); +} +``` + ## Sections ListBox supports sections in order to group options. Sections can be used by wrapping groups of items in a `ListBoxSection` element. A `
` element may also be included to label the section. diff --git a/packages/react-aria-components/src/ListBox.tsx b/packages/react-aria-components/src/ListBox.tsx index 636b0141c43..9e5424a7834 100644 --- a/packages/react-aria-components/src/ListBox.tsx +++ b/packages/react-aria-components/src/ListBox.tsx @@ -356,7 +356,9 @@ export interface ListBoxItemProps extends RenderProps void + onAction?: () => void, + /** Handler that is called when a key is pressed on the item. */ + onKeyDown?: (e: React.KeyboardEvent) => void } /** @@ -379,6 +381,8 @@ export const ListBoxItem = /*#__PURE__*/ createLeafComponent(ItemNode, function onHoverEnd: item.props.onHoverEnd }); + let keyDownProps = props.onKeyDown ? {onKeyDown: props.onKeyDown} : undefined; + let draggableItem: DraggableItemResult | null = null; if (dragState && dragAndDropHooks) { draggableItem = dragAndDropHooks.useDraggableItem!({key: item.key, hasAction: states.hasAction}, dragState); @@ -422,7 +426,7 @@ export const ListBoxItem = /*#__PURE__*/ createLeafComponent(ItemNode, function return ( { ); }; +export const ListBoxWithKeyboardDelete: ListBoxStory = () => { + let initialItems = [ + {id: 1, name: 'Item 1'}, + {id: 2, name: 'Item 2'}, + {id: 3, name: 'Item 3'}, + {id: 4, name: 'Item 4'}, + {id: 5, name: 'Item 5'} + ]; + + let list = useListData({ + initialItems + }); + + let handleKeyDown = (key: Key) => (e: React.KeyboardEvent) => { + if (e.key === 'Delete' || e.key === 'Backspace') { + e.preventDefault(); + list.remove(key); + action('onDelete')(key); + } + }; + + return ( +
+
+ Press Delete or Backspace to remove the focused item. +
+ + {item => ( + + {item.name} + + )} + +
+ ); +}; + From b404954bcbfe3ba45edec122594128c9cbd29951 Mon Sep 17 00:00:00 2001 From: hasegawa-101 Date: Fri, 14 Nov 2025 02:29:02 +0900 Subject: [PATCH 02/14] Update type annotation in ListBox example and fix style formatting in ListBox story --- packages/react-aria-components/docs/ListBox.mdx | 3 ++- packages/react-aria-components/stories/ListBox.stories.tsx | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/react-aria-components/docs/ListBox.mdx b/packages/react-aria-components/docs/ListBox.mdx index 8dd6b940bfe..011bded3f63 100644 --- a/packages/react-aria-components/docs/ListBox.mdx +++ b/packages/react-aria-components/docs/ListBox.mdx @@ -415,6 +415,7 @@ ListBox supports custom keyboard event handling on individual items via the `onK ```tsx example import {useListData} from 'react-stately'; +import type {Key} from 'react-aria-components'; function Example() { let list = useListData({ @@ -427,7 +428,7 @@ function Example() { ] }); - let handleKeyDown = (key: React.Key) => (e: React.KeyboardEvent) => { + let handleKeyDown = (key: Key) => (e: React.KeyboardEvent) => { if (e.key === 'Delete' || e.key === 'Backspace') { e.preventDefault(); list.remove(key); diff --git a/packages/react-aria-components/stories/ListBox.stories.tsx b/packages/react-aria-components/stories/ListBox.stories.tsx index f7dfce2881e..33b90446f89 100644 --- a/packages/react-aria-components/stories/ListBox.stories.tsx +++ b/packages/react-aria-components/stories/ListBox.stories.tsx @@ -832,7 +832,7 @@ export const ListBoxWithKeyboardDelete: ListBoxStory = () => { }; return ( -
+
Press Delete or Backspace to remove the focused item.
From dfd80e104b3b3fbf598bd1b4c0e732403c466fd1 Mon Sep 17 00:00:00 2001 From: hasegawa-101 Date: Fri, 14 Nov 2025 11:42:25 +0900 Subject: [PATCH 03/14] fix: remove custom keyboard handling example from ListBox docs and story --- .../react-aria-components/docs/ListBox.mdx | 41 ------------------ .../stories/ListBox.stories.tsx | 42 ------------------- 2 files changed, 83 deletions(-) diff --git a/packages/react-aria-components/docs/ListBox.mdx b/packages/react-aria-components/docs/ListBox.mdx index 011bded3f63..dae009ba866 100644 --- a/packages/react-aria-components/docs/ListBox.mdx +++ b/packages/react-aria-components/docs/ListBox.mdx @@ -409,47 +409,6 @@ By default, link items in a ListBox are not selectable, and only perform navigat The `` component works with frameworks and client side routers like [Next.js](https://nextjs.org/) and [React Router](https://reactrouter.com/en/main). As with other React Aria components that support links, this works via the component at the root of your app. See the [client side routing guide](routing.html) to learn how to set this up. -## Custom keyboard handling - -ListBox supports custom keyboard event handling on individual items via the `onKeyDown` prop on `ListBoxItem`. This enables you to implement additional keyboard interactions beyond the built-in selection and navigation behavior, such as deleting items with the Backspace or Delete keys. - -```tsx example -import {useListData} from 'react-stately'; -import type {Key} from 'react-aria-components'; - -function Example() { - let list = useListData({ - initialItems: [ - {id: 1, name: 'Item 1'}, - {id: 2, name: 'Item 2'}, - {id: 3, name: 'Item 3'}, - {id: 4, name: 'Item 4'}, - {id: 5, name: 'Item 5'} - ] - }); - - let handleKeyDown = (key: Key) => (e: React.KeyboardEvent) => { - if (e.key === 'Delete' || e.key === 'Backspace') { - e.preventDefault(); - list.remove(key); - } - }; - - return ( - - {item => ( - - {item.name} - - )} - - ); -} -``` - ## Sections ListBox supports sections in order to group options. Sections can be used by wrapping groups of items in a `ListBoxSection` element. A `
` element may also be included to label the section. diff --git a/packages/react-aria-components/stories/ListBox.stories.tsx b/packages/react-aria-components/stories/ListBox.stories.tsx index 33b90446f89..e9f33b3ba2a 100644 --- a/packages/react-aria-components/stories/ListBox.stories.tsx +++ b/packages/react-aria-components/stories/ListBox.stories.tsx @@ -12,8 +12,6 @@ import {action} from '@storybook/addon-actions'; import {Collection, DropIndicator, GridLayout, Header, ListBox, ListBoxItem, ListBoxProps, ListBoxSection, ListLayout, Separator, Text, useDragAndDrop, Virtualizer, WaterfallLayout} from 'react-aria-components'; -import {Key} from '@react-types/shared'; -import {Keyboard} from '@react-spectrum/text'; import {ListBoxLoadMoreItem} from '../'; import {LoadingSpinner, MyListBoxItem} from './utils'; import {Meta, StoryFn, StoryObj} from '@storybook/react'; @@ -810,44 +808,4 @@ export let VirtualizedListBoxDndOnAction: ListBoxStory = () => { ); }; -export const ListBoxWithKeyboardDelete: ListBoxStory = () => { - let initialItems = [ - {id: 1, name: 'Item 1'}, - {id: 2, name: 'Item 2'}, - {id: 3, name: 'Item 3'}, - {id: 4, name: 'Item 4'}, - {id: 5, name: 'Item 5'} - ]; - - let list = useListData({ - initialItems - }); - - let handleKeyDown = (key: Key) => (e: React.KeyboardEvent) => { - if (e.key === 'Delete' || e.key === 'Backspace') { - e.preventDefault(); - list.remove(key); - action('onDelete')(key); - } - }; - - return ( -
-
- Press Delete or Backspace to remove the focused item. -
- - {item => ( - - {item.name} - - )} - -
- ); -}; From 49e754d61d34db5edb243fecac719a7616713470 Mon Sep 17 00:00:00 2001 From: hasegawa-101 Date: Fri, 14 Nov 2025 13:27:50 +0900 Subject: [PATCH 04/14] test: add unit tests for `onKeyDown` prop in ListBox component --- .../react-aria-components/test/ListBox.test.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/react-aria-components/test/ListBox.test.js b/packages/react-aria-components/test/ListBox.test.js index a46b9fc71aa..ae754298691 100644 --- a/packages/react-aria-components/test/ListBox.test.js +++ b/packages/react-aria-components/test/ListBox.test.js @@ -1861,4 +1861,20 @@ describe('ListBox', () => { expect(onClick).toHaveBeenCalledTimes(1); }); }); + + describe('onKeyDown', () => { + it('should call onKeyDown handler when key is pressed on item', () => { + let onKeyDown = jest.fn(); + let {getAllByRole} = renderListbox({}, {onKeyDown}); + let options = getAllByRole('option'); + + fireEvent.keyDown(options[0], {key: 'Delete'}); + expect(onKeyDown).toHaveBeenCalledTimes(1); + expect(onKeyDown.mock.calls[0][0]).toHaveProperty('key', 'Delete'); + + fireEvent.keyDown(options[1], {key: 'Backspace'}); + expect(onKeyDown).toHaveBeenCalledTimes(2); + expect(onKeyDown.mock.calls[1][0]).toHaveProperty('key', 'Backspace'); + }); + }); }); From 00f7be5484060750a70129b662c55f38985f7e12 Mon Sep 17 00:00:00 2001 From: hasegawa-101 Date: Fri, 14 Nov 2025 14:01:35 +0900 Subject: [PATCH 05/14] test: remove redundant assertions for `onKeyDown` in ListBox tests --- packages/react-aria-components/test/ListBox.test.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/react-aria-components/test/ListBox.test.js b/packages/react-aria-components/test/ListBox.test.js index ae754298691..cee1431c938 100644 --- a/packages/react-aria-components/test/ListBox.test.js +++ b/packages/react-aria-components/test/ListBox.test.js @@ -1870,11 +1870,9 @@ describe('ListBox', () => { fireEvent.keyDown(options[0], {key: 'Delete'}); expect(onKeyDown).toHaveBeenCalledTimes(1); - expect(onKeyDown.mock.calls[0][0]).toHaveProperty('key', 'Delete'); fireEvent.keyDown(options[1], {key: 'Backspace'}); expect(onKeyDown).toHaveBeenCalledTimes(2); - expect(onKeyDown.mock.calls[1][0]).toHaveProperty('key', 'Backspace'); }); }); }); From e7356f78088b3734ce5696072d853f102721d069 Mon Sep 17 00:00:00 2001 From: hasegawa-101 Date: Sat, 15 Nov 2025 15:59:55 +0900 Subject: [PATCH 06/14] test: update `onKeyDown` tests in ListBox to use user-event for better simulation --- packages/react-aria-components/test/ListBox.test.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/react-aria-components/test/ListBox.test.js b/packages/react-aria-components/test/ListBox.test.js index cee1431c938..c1ffb040d50 100644 --- a/packages/react-aria-components/test/ListBox.test.js +++ b/packages/react-aria-components/test/ListBox.test.js @@ -1863,15 +1863,15 @@ describe('ListBox', () => { }); describe('onKeyDown', () => { - it('should call onKeyDown handler when key is pressed on item', () => { + it('should call onKeyDown handler when key is pressed on item', async () => { let onKeyDown = jest.fn(); - let {getAllByRole} = renderListbox({}, {onKeyDown}); - let options = getAllByRole('option'); + renderListbox({}, {onKeyDown}); - fireEvent.keyDown(options[0], {key: 'Delete'}); + await user.tab(); + await user.keyboard('{Delete}'); expect(onKeyDown).toHaveBeenCalledTimes(1); - fireEvent.keyDown(options[1], {key: 'Backspace'}); + await user.keyboard('{Backspace}'); expect(onKeyDown).toHaveBeenCalledTimes(2); }); }); From 2fbcf50ab995ca7ba9532d92ef70f95556fb84d0 Mon Sep 17 00:00:00 2001 From: hasegawa-101 Date: Fri, 14 Nov 2025 01:59:48 +0900 Subject: [PATCH 07/14] Add `onKeyDown` prop to ListBoxItem for custom keyboard handling --- .../react-aria-components/docs/ListBox.mdx | 40 +++++++++++++++++ .../react-aria-components/src/ListBox.tsx | 8 +++- .../stories/ListBox.stories.tsx | 43 +++++++++++++++++++ 3 files changed, 89 insertions(+), 2 deletions(-) diff --git a/packages/react-aria-components/docs/ListBox.mdx b/packages/react-aria-components/docs/ListBox.mdx index dae009ba866..8dd6b940bfe 100644 --- a/packages/react-aria-components/docs/ListBox.mdx +++ b/packages/react-aria-components/docs/ListBox.mdx @@ -409,6 +409,46 @@ By default, link items in a ListBox are not selectable, and only perform navigat The `` component works with frameworks and client side routers like [Next.js](https://nextjs.org/) and [React Router](https://reactrouter.com/en/main). As with other React Aria components that support links, this works via the component at the root of your app. See the [client side routing guide](routing.html) to learn how to set this up. +## Custom keyboard handling + +ListBox supports custom keyboard event handling on individual items via the `onKeyDown` prop on `ListBoxItem`. This enables you to implement additional keyboard interactions beyond the built-in selection and navigation behavior, such as deleting items with the Backspace or Delete keys. + +```tsx example +import {useListData} from 'react-stately'; + +function Example() { + let list = useListData({ + initialItems: [ + {id: 1, name: 'Item 1'}, + {id: 2, name: 'Item 2'}, + {id: 3, name: 'Item 3'}, + {id: 4, name: 'Item 4'}, + {id: 5, name: 'Item 5'} + ] + }); + + let handleKeyDown = (key: React.Key) => (e: React.KeyboardEvent) => { + if (e.key === 'Delete' || e.key === 'Backspace') { + e.preventDefault(); + list.remove(key); + } + }; + + return ( + + {item => ( + + {item.name} + + )} + + ); +} +``` + ## Sections ListBox supports sections in order to group options. Sections can be used by wrapping groups of items in a `ListBoxSection` element. A `
` element may also be included to label the section. diff --git a/packages/react-aria-components/src/ListBox.tsx b/packages/react-aria-components/src/ListBox.tsx index 636b0141c43..9e5424a7834 100644 --- a/packages/react-aria-components/src/ListBox.tsx +++ b/packages/react-aria-components/src/ListBox.tsx @@ -356,7 +356,9 @@ export interface ListBoxItemProps extends RenderProps void + onAction?: () => void, + /** Handler that is called when a key is pressed on the item. */ + onKeyDown?: (e: React.KeyboardEvent) => void } /** @@ -379,6 +381,8 @@ export const ListBoxItem = /*#__PURE__*/ createLeafComponent(ItemNode, function onHoverEnd: item.props.onHoverEnd }); + let keyDownProps = props.onKeyDown ? {onKeyDown: props.onKeyDown} : undefined; + let draggableItem: DraggableItemResult | null = null; if (dragState && dragAndDropHooks) { draggableItem = dragAndDropHooks.useDraggableItem!({key: item.key, hasAction: states.hasAction}, dragState); @@ -422,7 +426,7 @@ export const ListBoxItem = /*#__PURE__*/ createLeafComponent(ItemNode, function return ( { ); }; +export const ListBoxWithKeyboardDelete: ListBoxStory = () => { + let initialItems = [ + {id: 1, name: 'Item 1'}, + {id: 2, name: 'Item 2'}, + {id: 3, name: 'Item 3'}, + {id: 4, name: 'Item 4'}, + {id: 5, name: 'Item 5'} + ]; + + let list = useListData({ + initialItems + }); + + let handleKeyDown = (key: Key) => (e: React.KeyboardEvent) => { + if (e.key === 'Delete' || e.key === 'Backspace') { + e.preventDefault(); + list.remove(key); + action('onDelete')(key); + } + }; + + return ( +
+
+ Press Delete or Backspace to remove the focused item. +
+ + {item => ( + + {item.name} + + )} + +
+ ); +}; + From 139f601b2cdddf6ba29546747d425ebb52bac950 Mon Sep 17 00:00:00 2001 From: hasegawa-101 Date: Fri, 14 Nov 2025 02:29:02 +0900 Subject: [PATCH 08/14] Update type annotation in ListBox example and fix style formatting in ListBox story --- packages/react-aria-components/docs/ListBox.mdx | 3 ++- packages/react-aria-components/stories/ListBox.stories.tsx | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/react-aria-components/docs/ListBox.mdx b/packages/react-aria-components/docs/ListBox.mdx index 8dd6b940bfe..011bded3f63 100644 --- a/packages/react-aria-components/docs/ListBox.mdx +++ b/packages/react-aria-components/docs/ListBox.mdx @@ -415,6 +415,7 @@ ListBox supports custom keyboard event handling on individual items via the `onK ```tsx example import {useListData} from 'react-stately'; +import type {Key} from 'react-aria-components'; function Example() { let list = useListData({ @@ -427,7 +428,7 @@ function Example() { ] }); - let handleKeyDown = (key: React.Key) => (e: React.KeyboardEvent) => { + let handleKeyDown = (key: Key) => (e: React.KeyboardEvent) => { if (e.key === 'Delete' || e.key === 'Backspace') { e.preventDefault(); list.remove(key); diff --git a/packages/react-aria-components/stories/ListBox.stories.tsx b/packages/react-aria-components/stories/ListBox.stories.tsx index f7dfce2881e..33b90446f89 100644 --- a/packages/react-aria-components/stories/ListBox.stories.tsx +++ b/packages/react-aria-components/stories/ListBox.stories.tsx @@ -832,7 +832,7 @@ export const ListBoxWithKeyboardDelete: ListBoxStory = () => { }; return ( -
+
Press Delete or Backspace to remove the focused item.
From f1d2493e3bb958bccc42f1b717d8a5412c7bfd29 Mon Sep 17 00:00:00 2001 From: hasegawa-101 Date: Fri, 14 Nov 2025 11:42:25 +0900 Subject: [PATCH 09/14] fix: remove custom keyboard handling example from ListBox docs and story --- .../react-aria-components/docs/ListBox.mdx | 41 ------------------ .../stories/ListBox.stories.tsx | 42 ------------------- 2 files changed, 83 deletions(-) diff --git a/packages/react-aria-components/docs/ListBox.mdx b/packages/react-aria-components/docs/ListBox.mdx index 011bded3f63..dae009ba866 100644 --- a/packages/react-aria-components/docs/ListBox.mdx +++ b/packages/react-aria-components/docs/ListBox.mdx @@ -409,47 +409,6 @@ By default, link items in a ListBox are not selectable, and only perform navigat The `` component works with frameworks and client side routers like [Next.js](https://nextjs.org/) and [React Router](https://reactrouter.com/en/main). As with other React Aria components that support links, this works via the component at the root of your app. See the [client side routing guide](routing.html) to learn how to set this up. -## Custom keyboard handling - -ListBox supports custom keyboard event handling on individual items via the `onKeyDown` prop on `ListBoxItem`. This enables you to implement additional keyboard interactions beyond the built-in selection and navigation behavior, such as deleting items with the Backspace or Delete keys. - -```tsx example -import {useListData} from 'react-stately'; -import type {Key} from 'react-aria-components'; - -function Example() { - let list = useListData({ - initialItems: [ - {id: 1, name: 'Item 1'}, - {id: 2, name: 'Item 2'}, - {id: 3, name: 'Item 3'}, - {id: 4, name: 'Item 4'}, - {id: 5, name: 'Item 5'} - ] - }); - - let handleKeyDown = (key: Key) => (e: React.KeyboardEvent) => { - if (e.key === 'Delete' || e.key === 'Backspace') { - e.preventDefault(); - list.remove(key); - } - }; - - return ( - - {item => ( - - {item.name} - - )} - - ); -} -``` - ## Sections ListBox supports sections in order to group options. Sections can be used by wrapping groups of items in a `ListBoxSection` element. A `
` element may also be included to label the section. diff --git a/packages/react-aria-components/stories/ListBox.stories.tsx b/packages/react-aria-components/stories/ListBox.stories.tsx index 33b90446f89..e9f33b3ba2a 100644 --- a/packages/react-aria-components/stories/ListBox.stories.tsx +++ b/packages/react-aria-components/stories/ListBox.stories.tsx @@ -12,8 +12,6 @@ import {action} from '@storybook/addon-actions'; import {Collection, DropIndicator, GridLayout, Header, ListBox, ListBoxItem, ListBoxProps, ListBoxSection, ListLayout, Separator, Text, useDragAndDrop, Virtualizer, WaterfallLayout} from 'react-aria-components'; -import {Key} from '@react-types/shared'; -import {Keyboard} from '@react-spectrum/text'; import {ListBoxLoadMoreItem} from '../'; import {LoadingSpinner, MyListBoxItem} from './utils'; import {Meta, StoryFn, StoryObj} from '@storybook/react'; @@ -810,44 +808,4 @@ export let VirtualizedListBoxDndOnAction: ListBoxStory = () => { ); }; -export const ListBoxWithKeyboardDelete: ListBoxStory = () => { - let initialItems = [ - {id: 1, name: 'Item 1'}, - {id: 2, name: 'Item 2'}, - {id: 3, name: 'Item 3'}, - {id: 4, name: 'Item 4'}, - {id: 5, name: 'Item 5'} - ]; - - let list = useListData({ - initialItems - }); - - let handleKeyDown = (key: Key) => (e: React.KeyboardEvent) => { - if (e.key === 'Delete' || e.key === 'Backspace') { - e.preventDefault(); - list.remove(key); - action('onDelete')(key); - } - }; - - return ( -
-
- Press Delete or Backspace to remove the focused item. -
- - {item => ( - - {item.name} - - )} - -
- ); -}; From 299d78c15a30ecb87d9062127470cc7b00ac8089 Mon Sep 17 00:00:00 2001 From: hasegawa-101 Date: Fri, 14 Nov 2025 13:27:50 +0900 Subject: [PATCH 10/14] test: add unit tests for `onKeyDown` prop in ListBox component --- .../react-aria-components/test/ListBox.test.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/react-aria-components/test/ListBox.test.js b/packages/react-aria-components/test/ListBox.test.js index a46b9fc71aa..ae754298691 100644 --- a/packages/react-aria-components/test/ListBox.test.js +++ b/packages/react-aria-components/test/ListBox.test.js @@ -1861,4 +1861,20 @@ describe('ListBox', () => { expect(onClick).toHaveBeenCalledTimes(1); }); }); + + describe('onKeyDown', () => { + it('should call onKeyDown handler when key is pressed on item', () => { + let onKeyDown = jest.fn(); + let {getAllByRole} = renderListbox({}, {onKeyDown}); + let options = getAllByRole('option'); + + fireEvent.keyDown(options[0], {key: 'Delete'}); + expect(onKeyDown).toHaveBeenCalledTimes(1); + expect(onKeyDown.mock.calls[0][0]).toHaveProperty('key', 'Delete'); + + fireEvent.keyDown(options[1], {key: 'Backspace'}); + expect(onKeyDown).toHaveBeenCalledTimes(2); + expect(onKeyDown.mock.calls[1][0]).toHaveProperty('key', 'Backspace'); + }); + }); }); From 0c8979b494774da36f77da7fb8539f452c5d19d8 Mon Sep 17 00:00:00 2001 From: hasegawa-101 Date: Fri, 14 Nov 2025 14:01:35 +0900 Subject: [PATCH 11/14] test: remove redundant assertions for `onKeyDown` in ListBox tests --- packages/react-aria-components/test/ListBox.test.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/react-aria-components/test/ListBox.test.js b/packages/react-aria-components/test/ListBox.test.js index ae754298691..cee1431c938 100644 --- a/packages/react-aria-components/test/ListBox.test.js +++ b/packages/react-aria-components/test/ListBox.test.js @@ -1870,11 +1870,9 @@ describe('ListBox', () => { fireEvent.keyDown(options[0], {key: 'Delete'}); expect(onKeyDown).toHaveBeenCalledTimes(1); - expect(onKeyDown.mock.calls[0][0]).toHaveProperty('key', 'Delete'); fireEvent.keyDown(options[1], {key: 'Backspace'}); expect(onKeyDown).toHaveBeenCalledTimes(2); - expect(onKeyDown.mock.calls[1][0]).toHaveProperty('key', 'Backspace'); }); }); }); From 81ccc926ebd30db6f631a5dab6885b1b8340d9ad Mon Sep 17 00:00:00 2001 From: hasegawa-101 Date: Sat, 15 Nov 2025 15:59:55 +0900 Subject: [PATCH 12/14] test: update `onKeyDown` tests in ListBox to use user-event for better simulation --- packages/react-aria-components/test/ListBox.test.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/react-aria-components/test/ListBox.test.js b/packages/react-aria-components/test/ListBox.test.js index cee1431c938..c1ffb040d50 100644 --- a/packages/react-aria-components/test/ListBox.test.js +++ b/packages/react-aria-components/test/ListBox.test.js @@ -1863,15 +1863,15 @@ describe('ListBox', () => { }); describe('onKeyDown', () => { - it('should call onKeyDown handler when key is pressed on item', () => { + it('should call onKeyDown handler when key is pressed on item', async () => { let onKeyDown = jest.fn(); - let {getAllByRole} = renderListbox({}, {onKeyDown}); - let options = getAllByRole('option'); + renderListbox({}, {onKeyDown}); - fireEvent.keyDown(options[0], {key: 'Delete'}); + await user.tab(); + await user.keyboard('{Delete}'); expect(onKeyDown).toHaveBeenCalledTimes(1); - fireEvent.keyDown(options[1], {key: 'Backspace'}); + await user.keyboard('{Backspace}'); expect(onKeyDown).toHaveBeenCalledTimes(2); }); }); From cded5a0abfcddad17b9cda5f4ed2486a72f4f379 Mon Sep 17 00:00:00 2001 From: hasegawa-101 Date: Sat, 15 Nov 2025 16:23:47 +0900 Subject: [PATCH 13/14] chore: remove unnecessary blank lines in ListBox story --- packages/react-aria-components/stories/ListBox.stories.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/react-aria-components/stories/ListBox.stories.tsx b/packages/react-aria-components/stories/ListBox.stories.tsx index e9f33b3ba2a..47fb20b8e7b 100644 --- a/packages/react-aria-components/stories/ListBox.stories.tsx +++ b/packages/react-aria-components/stories/ListBox.stories.tsx @@ -807,5 +807,3 @@ export let VirtualizedListBoxDndOnAction: ListBoxStory = () => {
); }; - - From 175fc31ca7967dfb43eb201604b5104e82ec633a Mon Sep 17 00:00:00 2001 From: hasegawa-101 Date: Sat, 15 Nov 2025 16:30:20 +0900 Subject: [PATCH 14/14] chore: remove trailing blank line in ListBox story --- packages/react-aria-components/stories/ListBox.stories.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-aria-components/stories/ListBox.stories.tsx b/packages/react-aria-components/stories/ListBox.stories.tsx index 47fb20b8e7b..0256660a9ee 100644 --- a/packages/react-aria-components/stories/ListBox.stories.tsx +++ b/packages/react-aria-components/stories/ListBox.stories.tsx @@ -807,3 +807,4 @@ export let VirtualizedListBoxDndOnAction: ListBoxStory = () => {
); }; +