Skip to content

Commit cfd4319

Browse files
authored
Merge pull request coreui#84 from coreui/fix-switch
v2.5.2
2 parents 7542c9b + 17e98cb commit cfd4319

File tree

4 files changed

+76
-30
lines changed

4 files changed

+76
-30
lines changed

CHANGELOG.md

+17-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,23 @@
11
### [@coreui/react](https://coreui.io/) changelog
22

3-
##### `v2.5.1`
3+
##### `v2.5.2`
4+
- fix(Switch): does not provide any keyboard accessibility - thanks @roastery-zz close #44
5+
- fix(Switch): checked props and state out of sync - thanks @gravitymedianet @jinixx
6+
- fix(Switch): uncontrolled mode with defaultChecked
7+
8+
###### dependencies update
9+
- update `core-js` to `^2.6.9`
10+
- update `react-perfect-scrollbar` to `^1.5.3`
11+
- update `reactstrap` to `^8.0.1"
12+
- update `babel-eslint` to `^10.0.2`
13+
- update `enzyme` to `^3.10.0`
14+
- update `enzyme-adapter-react-16` to `^1.14.0`
15+
- update `eslint-plugin-import` to `^2.18.2`
16+
- update `eslint-plugin-react` to `^7.14.3`
17+
- update `react-router-dom` to `^5.0.1`
18+
- update `webpack-dev-server` to `^3.7.2`
419

20+
##### `v2.5.1`
521
- fix(SidebarNav): add missing `class` and `attributes` to navDropdown item
622
- fix(HeaderDropdown): add missing Dropdown.propTypes
723
- refactor(demo): AppHeaderDropdown remove style right auto

package.json

+13-13
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@coreui/react",
3-
"version": "2.5.1",
3+
"version": "2.5.2",
44
"description": "CoreUI React Bootstrap 4 components",
55
"license": "MIT",
66
"author": {
@@ -37,30 +37,30 @@
3737
"dependencies": {
3838
"@coreui/icons": "0.3.0",
3939
"classnames": "^2.2.6",
40-
"core-js": "^2.6.8",
40+
"core-js": "^2.6.9",
4141
"prop-types": "^15.7.2",
4242
"react-onclickout": "^2.0.8",
43-
"react-perfect-scrollbar": "^1.5.2",
44-
"reactstrap": "^7.1.0"
43+
"react-perfect-scrollbar": "^1.5.3",
44+
"reactstrap": "^8.0.1"
4545
},
4646
"peerDependencies": {
47-
"@coreui/coreui": "^2.1.9",
47+
"@coreui/coreui": "^2.1.12",
4848
"react": "^16.8.6",
49-
"react-router-dom": "^5.0.0"
49+
"react-router-dom": "^5.0.1"
5050
},
5151
"devDependencies": {
52-
"babel-eslint": "^10.0.1",
53-
"enzyme": "^3.9.0",
54-
"enzyme-adapter-react-16": "^1.13.1",
52+
"babel-eslint": "^10.0.2",
53+
"enzyme": "^3.10.0",
54+
"enzyme-adapter-react-16": "^1.14.0",
5555
"eslint": "^5.16.0",
56-
"eslint-plugin-import": "^2.17.2",
57-
"eslint-plugin-react": "^7.13.0",
56+
"eslint-plugin-import": "^2.18.2",
57+
"eslint-plugin-react": "^7.14.3",
5858
"nwb": "^0.23.0",
5959
"react": "^16.8.6",
6060
"react-dom": "^16.8.6",
61-
"react-router-dom": "^5.0.0",
61+
"react-router-dom": "^5.0.1",
6262
"sinon": "^5.1.1",
63-
"webpack-dev-server": "^3.4.1"
63+
"webpack-dev-server": "^3.7.2"
6464
},
6565
"repository": {
6666
"type": "git",

src/Switch.js

+44-14
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ const defaultProps = {
3333
outline: false,
3434
size: '',
3535
checked: false,
36-
defaultChecked: false,
37-
disabled: false,
38-
required: false,
36+
defaultChecked: undefined,
37+
disabled: undefined,
38+
required: undefined,
3939
type: 'checkbox',
4040
variant: '',
4141
dataOn: 'On',
@@ -45,35 +45,54 @@ const defaultProps = {
4545
class AppSwitch extends Component {
4646
constructor(props) {
4747
super(props);
48-
this.onChange = this.onChange.bind(this);
48+
this.handleChange = this.handleChange.bind(this);
49+
this.handleKeyDown = this.handleKeyDown.bind(this);
50+
this.handleKeyUp = this.handleKeyUp.bind(this);
4951
this.state = {
52+
uncontrolled: !!this.props.defaultChecked,
5053
checked: this.props.defaultChecked || this.props.checked,
5154
selected: []
5255
};
5356
}
5457

55-
onChange(event) {
56-
const target = event.target;
58+
toggleState(check) {
5759
this.setState({
58-
checked: target.checked,
60+
checked: check
5961
})
62+
}
63+
64+
handleChange(event) {
65+
const target = event.target;
66+
this.toggleState(target.checked)
6067

6168
if (this.props.onChange) {
6269
this.props.onChange(event);
6370
}
6471
}
6572

66-
componentDidUpdate(prevProps) {
67-
if (this.props.checked !== prevProps.checked) {
68-
this.setState({
69-
checked: this.props.checked
70-
})
73+
handleKeyDown(event) {
74+
if (event.key === ' ') {
75+
event.preventDefault();
76+
}
77+
}
78+
79+
handleKeyUp(event) {
80+
if (event.key === 'Enter' || event.key === ' ') {
81+
this.toggleState(!this.state.checked);
82+
}
83+
}
84+
85+
componentDidUpdate(prevProps, prevState) {
86+
if (!this.state.uncontrolled && (this.props.checked !== prevState.checked)) {
87+
this.toggleState(this.props.checked)
7188
}
7289
}
7390

7491
render() {
7592
const { className, disabled, color, name, label, outline, size, required, type, value, dataOn, dataOff, variant, ...attributes } = this.props;
7693

94+
const tabindex = attributes.tabIndex
95+
delete attributes.tabIndex
7796
delete attributes.checked
7897
delete attributes.defaultChecked
7998
delete attributes.onChange
@@ -98,8 +117,19 @@ class AppSwitch extends Component {
98117
);
99118

100119
return (
101-
<label className={classes}>
102-
<input type={type} className={inputClasses} onChange={this.onChange} checked={this.state.checked} name={name} required={required} disabled={disabled} value={value} {...attributes} />
120+
<label className={classes} tabIndex={tabindex} onKeyUp={this.handleKeyUp} onKeyDown={this.handleKeyDown}>
121+
<input type={type}
122+
className={inputClasses}
123+
onChange={this.handleChange}
124+
checked={this.state.checked}
125+
name={name}
126+
required={required}
127+
disabled={disabled}
128+
value={value}
129+
aria-checked={this.state.checked}
130+
aria-disabled={disabled}
131+
aria-readonly={disabled}
132+
{...attributes} />
103133
<span className={sliderClasses} data-checked={dataOn} data-unchecked={dataOff}></span>
104134
</label>
105135
);

tests/Switch.test.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ describe('AppSwitch', () => {
6060
expect(onChangeMock.called).toBe(true);
6161
});
6262

63-
it('should call onChange()', () => {
64-
const onChange = spy(AppSwitch.prototype, 'onChange');
63+
it('should call handleChange()', () => {
64+
const onChange = spy(AppSwitch.prototype, 'handleChange');
6565
const event = { target: { checked: true } };
6666
const wrapper = shallow(<AppSwitch label size="lg" />);
6767
expect(wrapper.find('input').props().checked).toBe(false);

0 commit comments

Comments
 (0)