diff --git a/src/Select.js b/src/Select.js index f62b5353c9..de8054aa26 100644 --- a/src/Select.js +++ b/src/Select.js @@ -387,7 +387,10 @@ class Select extends React.Component { this.selectFocusedOption(); return; case 13: // enter - if (!this.state.isOpen) return; + if (!this.state.isOpen) { + this.focusNextOption(); + return; + } event.stopPropagation(); this.selectFocusedOption(); break; @@ -400,6 +403,17 @@ class Select extends React.Component { event.stopPropagation(); } break; + case 32: // space + if (!this.props.searchable) { + event.preventDefault(); + } + if (!this.state.isOpen) { + this.focusNextOption(); + return; + } + event.stopPropagation(); + this.selectFocusedOption(); + break; case 38: // up this.focusPreviousOption(); break; @@ -788,13 +802,14 @@ class Select extends React.Component { aria-expanded={isOpen} aria-owns={ariaOwns} aria-activedescendant={isOpen ? this._instancePrefix + '-option-' + focusedOptionIndex : this._instancePrefix + '-value'} + aria-labelledby={this.props['aria-labelledby']} + aria-label={this.props['aria-label']} className={className} tabIndex={this.props.tabIndex || 0} onBlur={this.handleInputBlur} onFocus={this.handleInputFocus} ref={ref => this.input = ref} - id={divProps.id ? divProps.id : this.props.id} - aria-readonly={'' + !!this.props.disabled} + aria-disabled={'' + !!this.props.disabled} style={{ border: 0, width: 1, display:'inline-block' }}/> ); } diff --git a/test/Select-test.js b/test/Select-test.js index 6254f15710..9312ff4283 100644 --- a/test/Select-test.js +++ b/test/Select-test.js @@ -32,6 +32,7 @@ var PLACEHOLDER_SELECTOR = '.Select-placeholder'; var ARROW_UP = { keyCode: 38, key: 'ArrowUp' }; var ARROW_DOWN = { keyCode: 40, key: 'ArrowDown' }; var KEY_ENTER = { keyCode: 13, key: 'Enter' }; +var KEY_SPACE = { keyCode: 32, key: 'Space' }; class PropsWrapper extends React.Component { @@ -3253,7 +3254,6 @@ describe('Select', () => { }); it('disabled option link is still clickable', () => { - var selectArrow = ReactDOM.findDOMNode(instance).querySelector('.Select-arrow'); var selectArrow = ReactDOM.findDOMNode(instance).querySelector('.Select-arrow'); TestUtils.Simulate.mouseDown(selectArrow); var options = ReactDOM.findDOMNode(instance).querySelectorAll('.Select-option'); @@ -3975,7 +3975,7 @@ describe('Select', () => { ); }); - it('updates the active descendant after a selection', () => { + it('updates the active descendant after a selection using enter key', () => { return expect(wrapper, 'with event', 'keyDown', ARROW_DOWN, 'on',
, @@ -3991,6 +3991,45 @@ describe('Select', () => { }); }); + + it('expands the drop down when the enter key is pressed', () => { + + return expect(wrapper, + 'with event', 'keyDown', KEY_ENTER, 'on', , + 'queried for', ) + .then(input => { + expect(instance.state.focusedOption, 'to equal', { value: 'one', label: 'label one' }); + }); + + }); + + it('updates the active descendant after a selection using space bar', () => { + + return expect(wrapper, + 'with event', 'keyDown', ARROW_DOWN, 'on', , + 'with event', 'keyDown', KEY_SPACE, 'on', , + 'queried for', ) + .then(input => { + + // [ 'three', 'two', 'one' ] is now selected, + // therefore in-focus should be 'four' + + const activeId = input.attributes['aria-activedescendant'].value; + expect(ReactDOM.findDOMNode(instance), 'queried for first', '#' + activeId, 'to have text', 'label four'); + }); + + }); + + it('expands the drop down when the space bar is pressed', () => { + + return expect(wrapper, + 'with event', 'keyDown', KEY_SPACE, 'on', , + 'queried for', ) + .then(input => { + expect(instance.state.focusedOption, 'to equal', { value: 'one', label: 'label one' }); + }); + + }); }); });