diff --git a/.changeset/token-cancel-keyboard-removal.md b/.changeset/token-cancel-keyboard-removal.md new file mode 100644 index 00000000000..2687d83cae4 --- /dev/null +++ b/.changeset/token-cancel-keyboard-removal.md @@ -0,0 +1,5 @@ +--- +'@primer/react': patch +--- + +Token, IssueLabelToken: Respect canceled keyboard events when removing tokens with Backspace or Delete. diff --git a/packages/react/src/Token/TokenBase.tsx b/packages/react/src/Token/TokenBase.tsx index 03202c6f0cb..89ab5270f9d 100644 --- a/packages/react/src/Token/TokenBase.tsx +++ b/packages/react/src/Token/TokenBase.tsx @@ -60,6 +60,10 @@ const TokenBase = React.forwardRef) => { onKeyDown && onKeyDown(event) + if (event.defaultPrevented) { + return + } + if ((event.key === 'Backspace' || event.key === 'Delete') && onRemove) { onRemove() } diff --git a/packages/react/src/Token/__tests__/Token.test.tsx b/packages/react/src/Token/__tests__/Token.test.tsx index 73c01124c2a..edccf817c75 100644 --- a/packages/react/src/Token/__tests__/Token.test.tsx +++ b/packages/react/src/Token/__tests__/Token.test.tsx @@ -70,6 +70,28 @@ const testTokenComponent = (Component: React.ComponentType { + const onRemove = vi.fn() + const onKeyDown = vi.fn((event: React.KeyboardEvent) => event.preventDefault()) + const {getByText} = HTMLRender() + + fireEvent.keyDown(getByText('token'), {key}) + + expect(onKeyDown).toHaveBeenCalledTimes(1) + expect(onRemove).not.toHaveBeenCalled() + }) + + it.each(['Backspace', 'Delete'])('removes with %s when onKeyDown does not cancel the event', key => { + const onRemove = vi.fn() + const onKeyDown = vi.fn() + const {getByText} = HTMLRender() + + fireEvent.keyDown(getByText('token'), {key}) + + expect(onKeyDown).toHaveBeenCalledTimes(1) + expect(onRemove).toHaveBeenCalledTimes(1) + }) + it('renders with correct data-cursor-is-interactive attribute for button element', () => { const {getByText} = HTMLRender() const domNode = getByText('token')