From b16bf86540d7f01f878f6a7a0f13d3c243a8599b 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 16:03:02 +0800 Subject: [PATCH] fix: support keyboard activation for marks --- src/Marks/Mark.tsx | 16 ++++++++++++++-- tests/marks.test.js | 46 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/src/Marks/Mark.tsx b/src/Marks/Mark.tsx index 437ee555f..7d70c8b3f 100644 --- a/src/Marks/Mark.tsx +++ b/src/Marks/Mark.tsx @@ -1,4 +1,5 @@ import { clsx } from 'clsx'; +import { KeyCode } from '@rc-component/util'; import * as React from 'react'; import SliderContext from '../context'; import { getDirectionStyle } from '../util'; @@ -13,7 +14,7 @@ export interface MarkProps { const Mark: React.FC = (props) => { const { prefixCls, style, children, value, onClick } = props; - const { min, max, direction, includedStart, includedEnd, included } = + const { min, max, direction, disabled, includedStart, includedEnd, included } = React.useContext(SliderContext); const textCls = `${prefixCls}-text`; @@ -23,6 +24,9 @@ const Mark: React.FC = (props) => { return ( = (props) => { e.stopPropagation(); }} onClick={() => { - onClick(value); + if (!disabled) { + onClick(value); + } + }} + onKeyDown={(event) => { + if (!disabled && (event.which === KeyCode.ENTER || event.which === KeyCode.SPACE)) { + event.preventDefault(); + onClick(value); + } }} > {children} diff --git a/tests/marks.test.js b/tests/marks.test.js index c5ffd4907..94ee530cf 100644 --- a/tests/marks.test.js +++ b/tests/marks.test.js @@ -37,7 +37,9 @@ describe('marks', () => { const marks = { 0: '0', 30: '30', 100: '100' }; const onChange = jest.fn(); const onChangeComplete = jest.fn(); - const { container } = render(); + const { container } = render( + , + ); fireEvent.click(container.getElementsByClassName('rc-slider-mark-text')[1]); expect(container.getElementsByClassName('rc-slider-handle')[0]).toHaveAttribute( 'aria-valuenow', @@ -49,6 +51,48 @@ describe('marks', () => { expect(onChangeComplete).toHaveBeenCalledWith(30); }); + it('should select marks with Enter and Space', () => { + const onChange = jest.fn(); + const onChangeComplete = jest.fn(); + const { container, getByRole } = render( + , + ); + + const middleMark = getByRole('button', { name: 'Middle' }); + const endMark = getByRole('button', { name: 'End' }); + + expect(fireEvent.keyDown(middleMark, { key: 'Enter', keyCode: 13, which: 13 })).toBe(false); + expect(container.getElementsByClassName('rc-slider-handle')[0]).toHaveAttribute( + 'aria-valuenow', + '30', + ); + expect(fireEvent.keyDown(endMark, { key: ' ', keyCode: 32, which: 32 })).toBe(false); + expect(container.getElementsByClassName('rc-slider-handle')[0]).toHaveAttribute( + 'aria-valuenow', + '100', + ); + expect(onChange).toHaveBeenNthCalledWith(1, 30); + expect(onChange).toHaveBeenNthCalledWith(2, 100); + expect(onChangeComplete).toHaveBeenNthCalledWith(1, 30); + expect(onChangeComplete).toHaveBeenNthCalledWith(2, 100); + }); + + it('should expose disabled marks without adding them to the tab order', () => { + const onChange = jest.fn(); + const { getByRole } = render(); + + const mark = getByRole('button', { name: 'Middle' }); + + expect(mark).toHaveAttribute('aria-disabled', 'true'); + expect(mark).toHaveAttribute('tabindex', '-1'); + fireEvent.keyDown(mark, { key: 'Enter', keyCode: 13, which: 13 }); + expect(onChange).not.toHaveBeenCalled(); + }); + // TODO: not implement yet // zombieJ: since this test leave years but not implement. Could we remove this? // xit('should select correct value while click on marks in Ranger', () => {