From 58c1e15ff053a38426d0c22316390745609c623f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B3=E5=BB=B7=E5=AE=89?= <73953029+nrps9909@users.noreply.github.com> Date: Thu, 27 Aug 2026 20:35:08 +0800 Subject: [PATCH 1/2] fix: make clickable color blocks keyboard accessible --- src/components/ColorBlock.tsx | 16 ++++++++++++++++ tests/components.test.tsx | 30 ++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/src/components/ColorBlock.tsx b/src/components/ColorBlock.tsx index e78b9f3..20992e5 100644 --- a/src/components/ColorBlock.tsx +++ b/src/components/ColorBlock.tsx @@ -10,6 +10,7 @@ export type ColorBlockProps = { innerClassName?: string; /** Internal usage. Only used in antd ColorPicker semantic structure only */ innerStyle?: React.CSSProperties; + 'aria-label'?: string; onClick?: React.MouseEventHandler; }; @@ -20,14 +21,29 @@ const ColorBlock: React.FC = ({ style, innerClassName, innerStyle, + 'aria-label': ariaLabel, onClick, }) => { const colorBlockCls = `${prefixCls}-color-block`; + const onKeyDown: React.KeyboardEventHandler | undefined = + onClick + ? event => { + if (event.key === 'Enter' || event.key === ' ') { + event.preventDefault(); + event.currentTarget.click(); + } + } + : undefined; + return (
{ />, ); + const colorBlock = container.querySelector('.test-color-block'); const innerDiv = container.querySelector('.test-color-block-inner'); + expect(colorBlock).not.toHaveAttribute('role'); + expect(colorBlock).not.toHaveAttribute('tabindex'); + expect(colorBlock).not.toHaveAttribute('aria-label'); expect(innerDiv).toHaveClass('my-inner-class'); expect(innerDiv).toHaveStyle({ color: '#903' }); }); + + it('makes clickable ColorBlock keyboard accessible', () => { + const onClick = vi.fn(); + const { getByRole } = render( + , + ); + const button = getByRole('button', { name: 'Brand red' }); + + fireEvent.keyDown(button, { key: 'Enter' }); + fireEvent.keyDown(button, { key: ' ' }); + + expect(onClick).toHaveBeenCalledTimes(2); + }); + + it('uses the color value as the default name for clickable ColorBlock', () => { + const { getByRole } = render( + {}} />, + ); + + expect(getByRole('button', { name: '#ff0000' })).toBeInTheDocument(); + }); }); From b7e501087dd37295519dd6bc8579dcb5b444cb4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B3=E5=BB=B7=E5=AE=89?= <73953029+nrps9909@users.noreply.github.com> Date: Thu, 27 Aug 2026 20:45:31 +0800 Subject: [PATCH 2/2] fix: ignore repeated color block activation --- src/components/ColorBlock.tsx | 4 +++- tests/components.test.tsx | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/ColorBlock.tsx b/src/components/ColorBlock.tsx index 20992e5..c8c7efd 100644 --- a/src/components/ColorBlock.tsx +++ b/src/components/ColorBlock.tsx @@ -30,7 +30,9 @@ const ColorBlock: React.FC = ({ ? event => { if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); - event.currentTarget.click(); + if (!event.repeat) { + event.currentTarget.click(); + } } } : undefined; diff --git a/tests/components.test.tsx b/tests/components.test.tsx index b1ba093..28272f8 100644 --- a/tests/components.test.tsx +++ b/tests/components.test.tsx @@ -90,6 +90,7 @@ describe('ColorPicker.Components', () => { fireEvent.keyDown(button, { key: 'Enter' }); fireEvent.keyDown(button, { key: ' ' }); + fireEvent.keyDown(button, { key: 'Enter', repeat: true }); expect(onClick).toHaveBeenCalledTimes(2); });