diff --git a/src/Selector/Input.tsx b/src/Selector/Input.tsx index 3b1f02397..71e909c1d 100644 --- a/src/Selector/Input.tsx +++ b/src/Selector/Input.tsx @@ -15,6 +15,8 @@ interface InputProps { value: string; open: boolean; tabIndex: number; + /** Pass accessibility props to input */ + attrs: object; onKeyDown: React.KeyboardEventHandler; onMouseDown: React.MouseEventHandler; @@ -39,6 +41,7 @@ const Input: React.RefForwardingComponent = ( onChange, onPaste, open, + attrs, }, ref, ) => { @@ -70,6 +73,7 @@ const Input: React.RefForwardingComponent = ( 'aria-autocomplete': 'list', 'aria-controls': `${id}_list`, 'aria-activedescendant': `${id}_list_${accessibilityIndex}`, + ...attrs, value: editable ? value : '', readOnly: !editable, unselectable: !editable ? 'on' : null, diff --git a/src/Selector/MultipleSelector.tsx b/src/Selector/MultipleSelector.tsx index 9e7cea79e..baef8aca9 100644 --- a/src/Selector/MultipleSelector.tsx +++ b/src/Selector/MultipleSelector.tsx @@ -1,5 +1,6 @@ import React from 'react'; import classNames from 'classnames'; +import pickAttrs from 'rc-util/lib/pickAttrs'; import CSSMotionList from 'rc-animate/lib/CSSMotionList'; import TransBtn from '../TransBtn'; import { LabelValueType, RawValueType, CustomTagProps } from '../interface/generator'; @@ -28,37 +29,39 @@ interface SelectorProps extends InnerSelectorProps { onSelect: (value: RawValueType, option: { selected: boolean }) => void; } -const SelectSelector: React.FC = ({ - id, - prefixCls, - - values, - open, - searchValue, - inputRef, - placeholder, - disabled, - mode, - showSearch, - autoFocus, - autoComplete, - accessibilityIndex, - tabIndex, - - removeIcon, - choiceTransitionName, - - maxTagCount, - maxTagTextLength, - maxTagPlaceholder = (omittedValues: LabelValueType[]) => `+ ${omittedValues.length} ...`, - tagRender, - - onSelect, - onInputChange, - onInputPaste, - onInputKeyDown, - onInputMouseDown, -}) => { +const SelectSelector: React.FC = props => { + const { + id, + prefixCls, + + values, + open, + searchValue, + inputRef, + placeholder, + disabled, + mode, + showSearch, + autoFocus, + autoComplete, + accessibilityIndex, + tabIndex, + + removeIcon, + choiceTransitionName, + + maxTagCount, + maxTagTextLength, + maxTagPlaceholder = (omittedValues: LabelValueType[]) => `+ ${omittedValues.length} ...`, + tagRender, + + onSelect, + onInputChange, + onInputPaste, + onInputKeyDown, + onInputMouseDown, + } = props; + const [motionAppear, setMotionAppear] = React.useState(false); const measureRef = React.useRef(null); const [inputWidth, setInputWidth] = React.useState(0); @@ -194,6 +197,7 @@ const SelectSelector: React.FC = ({ onChange={onInputChange} onPaste={onInputPaste} tabIndex={tabIndex} + attrs={pickAttrs(props, true)} /> {/* Measure Node */} diff --git a/src/Selector/SingleSelector.tsx b/src/Selector/SingleSelector.tsx index b55b5df5d..037ea9ad8 100644 --- a/src/Selector/SingleSelector.tsx +++ b/src/Selector/SingleSelector.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import pickAttrs from 'rc-util/lib/pickAttrs'; import Input from './Input'; import { InnerSelectorProps } from '.'; @@ -8,30 +9,32 @@ interface SelectorProps extends InnerSelectorProps { backfill?: boolean; } -const SingleSelector: React.FC = ({ - inputElement, - prefixCls, - id, - inputRef, - disabled, - autoFocus, - autoComplete, - accessibilityIndex, - mode, - open, - values, - placeholder, - tabIndex, +const SingleSelector: React.FC = props => { + const { + inputElement, + prefixCls, + id, + inputRef, + disabled, + autoFocus, + autoComplete, + accessibilityIndex, + mode, + open, + values, + placeholder, + tabIndex, - showSearch, - searchValue, - activeValue, + showSearch, + searchValue, + activeValue, + + onInputKeyDown, + onInputMouseDown, + onInputChange, + onInputPaste, + } = props; - onInputKeyDown, - onInputMouseDown, - onInputChange, - onInputPaste, -}) => { const combobox = mode === 'combobox'; const inputEditable = combobox || (showSearch && open); const item = values[0]; @@ -65,6 +68,7 @@ const SingleSelector: React.FC = ({ onChange={onInputChange} onPaste={onInputPaste} tabIndex={tabIndex} + attrs={pickAttrs(props, true)} /> diff --git a/tests/Accessibility.test.tsx b/tests/Accessibility.test.tsx new file mode 100644 index 000000000..5411d0ac2 --- /dev/null +++ b/tests/Accessibility.test.tsx @@ -0,0 +1,27 @@ +import { mount } from 'enzyme'; +import * as React from 'react'; +import Select from '../src'; +import { injectRunAllTimers } from './utils/common'; + +describe('Select.Accessibility', () => { + injectRunAllTimers(jest); + + beforeEach(() => { + jest.useFakeTimers(); + }); + + afterEach(() => { + jest.useRealTimers(); + }); + + it('pass aria info to internal input', () => { + const MySelect = Select as any; + const wrapper = mount(); + expect(wrapper.find('input').props()).toEqual( + expect.objectContaining({ + 'aria-label': 'light', + 'data-attr': 'bamboo', + }), + ); + }); +}); diff --git a/tests/__snapshots__/Select.test.tsx.snap b/tests/__snapshots__/Select.test.tsx.snap index 70ca1c514..574abbdbb 100644 --- a/tests/__snapshots__/Select.test.tsx.snap +++ b/tests/__snapshots__/Select.test.tsx.snap @@ -238,6 +238,8 @@ exports[`Select.Basic render renders aria-attributes correctly 1`] = ` aria-autocomplete="list" aria-controls="undefined_list" aria-haspopup="listbox" + aria-label="some-label" + aria-labelledby="test-id" aria-owns="undefined_list" autocomplete="off" class="antd-selection-search-input" @@ -355,6 +357,8 @@ exports[`Select.Basic render renders data-attributes correctly 1`] = ` aria-owns="undefined_list" autocomplete="off" class="antd-selection-search-input" + data-id="12345" + data-test="test-id" readonly="" role="combobox" style="opacity:0"