diff --git a/src/modules/Checkbox/Checkbox.d.ts b/src/modules/Checkbox/Checkbox.d.ts index 436a1d0466..1611cfe45d 100644 --- a/src/modules/Checkbox/Checkbox.d.ts +++ b/src/modules/Checkbox/Checkbox.d.ts @@ -40,7 +40,7 @@ export interface CheckboxProps { * @param {SyntheticEvent} event - React's original SyntheticEvent. * @param {object} data - All props and proposed checked/indeterminate state. */ - onChange?: (event: React.FormEvent, data: this) => void; + onChange?: (event: React.FormEvent, data: CheckboxProps) => void; /** * Called when the checkbox or label is clicked. @@ -48,7 +48,15 @@ export interface CheckboxProps { * @param {SyntheticEvent} event - React's original SyntheticEvent. * @param {object} data - All props and current checked/indeterminate state. */ - onClick?: (event: React.MouseEvent, data: this) => void; + onClick?: (event: React.MouseEvent, data: CheckboxProps) => void; + + /** + * Called when the user presses down on the mouse. + * + * @param {SyntheticEvent} event - React's original SyntheticEvent. + * @param {object} data - All props and current checked/indeterminate state. + */ + onMouseDown?: (event: React.MouseEvent, data: CheckboxProps) => void; /** Format as a radio element. This means it is an exclusive option. */ radio?: boolean; diff --git a/src/modules/Checkbox/Checkbox.js b/src/modules/Checkbox/Checkbox.js index 988596a1a5..c12708d2b4 100644 --- a/src/modules/Checkbox/Checkbox.js +++ b/src/modules/Checkbox/Checkbox.js @@ -67,6 +67,14 @@ export default class Checkbox extends Component { */ onClick: PropTypes.func, + /** + * Called when the user presses down on the mouse. + * + * @param {SyntheticEvent} event - React's original SyntheticEvent. + * @param {object} data - All props and current checked/indeterminate state. + */ + onMouseDown: PropTypes.func, + /** Format as a radio element. This means it is an exclusive option. */ radio: customPropTypes.every([ PropTypes.bool, @@ -132,10 +140,18 @@ export default class Checkbox extends Component { return !disabled && !readOnly && !(radio && checked) } + computeTabIndex = () => { + const { disabled, tabIndex } = this.props + + if (!_.isNil(tabIndex)) return tabIndex + return disabled ? -1 : 0 + } + handleInputRef = c => (this.inputRef = c) - handleClick = (e) => { + handleClick = e => { debug('handleClick()') + const { onChange, onClick } = this.props const { checked, indeterminate } = this.state @@ -147,11 +163,22 @@ export default class Checkbox extends Component { } } + handleMouseDown = e => { + debug('handleMouseDown()') + + const { onMouseDown } = this.props + const { checked, indeterminate } = this.state + + _.invoke('focus', this.inputRef) + if (onMouseDown) onMouseDown(e, { ...this.props, checked: !!checked, indeterminate: !!indeterminate }) + } + // Note: You can't directly set the indeterminate prop on the input, so we // need to maintain a ref to the input and set it manually whenever the // component updates. setIndeterminate = () => { const { indeterminate } = this.state + if (this.inputRef) this.inputRef.indeterminate = !!indeterminate } @@ -164,7 +191,6 @@ export default class Checkbox extends Component { radio, readOnly, slider, - tabIndex, toggle, type, value, @@ -189,19 +215,21 @@ export default class Checkbox extends Component { const rest = getUnhandledProps(Checkbox, this.props) const ElementType = getElementType(Checkbox, this.props) - let computedTabIndex - if (!_.isNil(tabIndex)) computedTabIndex = tabIndex - else computedTabIndex = disabled ? -1 : 0 - return ( - + diff --git a/test/specs/modules/Checkbox/Checkbox-test.js b/test/specs/modules/Checkbox/Checkbox-test.js index e7aaaf4c1e..4efaefa72b 100644 --- a/test/specs/modules/Checkbox/Checkbox-test.js +++ b/test/specs/modules/Checkbox/Checkbox-test.js @@ -161,6 +161,22 @@ describe('Checkbox', () => { }) }) + describe('onMouseDown', () => { + it('sets focus to container', () => { + const mountNode = document.createElement('div') + document.body.appendChild(mountNode) + + const wrapper = mount(, { attachTo: mountNode }) + const input = document.querySelector('.ui.checkbox input') + + wrapper.simulate('mousedown') + document.activeElement.should.equal(input) + + wrapper.detach() + document.body.removeChild(mountNode) + }) + }) + describe('readOnly', () => { it('cannot be checked', () => { shallow()