diff --git a/integration/specs/Picklist/picklist-3.spec.js b/integration/specs/Picklist/picklist-3.spec.js
index 39e9715d6..87d6af1d4 100644
--- a/integration/specs/Picklist/picklist-3.spec.js
+++ b/integration/specs/Picklist/picklist-3.spec.js
@@ -56,7 +56,7 @@ describe('Picklist with multiple options', () => {
await firstOption.waitUntilIsVisible();
await expect(await firstOption.isVisible()).toBe(true);
});
- it.skip('should not close when click on search input', async () => {
+ it('should not close when click on search input', async () => {
const picklist = new PagePicklist(PICKLIST);
await picklist.clickInput();
await picklist.waitUntilOpen();
diff --git a/src/components/Calendar/__test__/day.spec.js b/src/components/Calendar/__test__/day.spec.js
index 283efe170..fb004b3be 100644
--- a/src/components/Calendar/__test__/day.spec.js
+++ b/src/components/Calendar/__test__/day.spec.js
@@ -31,7 +31,6 @@ describe('Day', () => {
disabledDays={['04/24/2019']}
/>,
);
- console.log(component.html());
component.find('span').simulate('keydown', { key: 'Enter' });
expect(onChangeMockFn).not.toBeCalled();
});
diff --git a/src/components/Picklist/index.js b/src/components/Picklist/index.js
index 9520aad90..6b41b3b57 100644
--- a/src/components/Picklist/index.js
+++ b/src/components/Picklist/index.js
@@ -20,7 +20,7 @@ import InternalDropdown from '../InternalDropdown';
import InternalOverlay from '../InternalOverlay';
import WindowResize from '../../libs/WindowResize';
-function positionResolver(opts) {
+function positionResolver(opts, enableSearch) {
const { trigger, viewport, content } = opts;
const newOpts = {
trigger,
@@ -30,6 +30,13 @@ function positionResolver(opts) {
width: trigger.width,
},
};
+ if (enableSearch && viewport.width <= 600) {
+ return {
+ top: 0,
+ left: 0,
+ width: viewport.width,
+ };
+ }
return {
...InternalOverlay.defaultPositionResolver(newOpts),
width: trigger.width,
@@ -55,7 +62,6 @@ class Picklist extends Component {
this.handleBlur = this.handleBlur.bind(this);
this.handleKeyPressed = this.handleKeyPressed.bind(this);
this.handleChange = this.handleChange.bind(this);
- this.handleContainerClick = this.handleContainerClick.bind(this);
this.closeAndFocusInput = this.closeAndFocusInput.bind(this);
this.handleWindowScroll = this.handleWindowScroll.bind(this);
this.handleWindowResize = this.handleWindowResize.bind(this);
@@ -78,12 +84,14 @@ class Picklist extends Component {
if (!wasOpen && isOpen) {
// eslint-disable-next-line id-length
this.outsideClick.startListening(this.containerRef.current, (_, event) => {
- if (this.eventTarget !== event.target) {
+ if (!this.dropdownRef.current.contains(event.target)) {
this.closeMenu();
this.handleBlur();
}
});
- this.windowScrolling.startListening(this.handleWindowScroll);
+ if (window.screen.width > 600) {
+ this.windowScrolling.startListening(this.handleWindowScroll);
+ }
this.windowResize.startListening(this.handleWindowResize);
}
}
@@ -182,10 +190,6 @@ class Picklist extends Component {
}, 0);
}
- handleContainerClick(event) {
- this.eventTarget = event.target;
- }
-
/**
* Sets focus on the element.
* @public
@@ -250,7 +254,6 @@ class Picklist extends Component {
onKeyDown={this.handleKeyPressed}
ref={this.containerRef}
readOnly={readOnly}
- onClick={this.handleContainerClick}
>
positionResolver(opt, enableSearch)}
onOpened={() => this.dropdownRef.current.focus()}
triggerElementRef={() => this.triggerRef}
+ keepScrollEnabled
>
;
diff --git a/src/components/RadioButtonGroup/index.js b/src/components/RadioButtonGroup/index.js
index 61f3b56ed..08e2bde04 100644
--- a/src/components/RadioButtonGroup/index.js
+++ b/src/components/RadioButtonGroup/index.js
@@ -115,6 +115,7 @@ class RadioButtonGroup extends Component {
onChange,
variant,
size,
+ borderRadius,
} = this.props;
const { options, markerLeft, markerWidth } = this.state;
const markerStyle = {
@@ -123,7 +124,12 @@ class RadioButtonGroup extends Component {
};
return (
-
+
-
+
-
@@ -202,6 +213,8 @@ RadioButtonGroup.propTypes = {
style: PropTypes.object,
/** The id of the outer element. */
id: PropTypes.string,
+ /** The border radius of the radio button. Valid values are square, semi-rounded and rounded. This value defaults to rounded. */
+ borderRadius: PropTypes.oneOf(['square', 'semi-rounded', 'rounded']),
};
RadioButtonGroup.defaultProps = {
@@ -217,6 +230,7 @@ RadioButtonGroup.defaultProps = {
required: false,
options: [],
size: 'medium',
+ borderRadius: 'rounded',
error: null,
id: undefined,
};
diff --git a/src/components/RadioButtonGroup/marker.js b/src/components/RadioButtonGroup/marker.js
index 397c818d5..4829fc476 100644
--- a/src/components/RadioButtonGroup/marker.js
+++ b/src/components/RadioButtonGroup/marker.js
@@ -5,7 +5,7 @@ import StyledMarkerContainer from './styled/markerContainer';
import StyledMarker from './styled/marker';
export default function Marker(props) {
- const { style, isVisible, variant, size } = props;
+ const { style, isVisible, variant, size, borderRadius } = props;
const markerStyle = {
...style,
opacity: isVisible ? 1 : 0,
@@ -14,7 +14,12 @@ export default function Marker(props) {
return (
-
+
);
@@ -25,6 +30,7 @@ Marker.propTypes = {
isVisible: PropTypes.any,
variant: PropTypes.oneOf(['default', 'inverse', 'brand']),
size: PropTypes.oneOf(['x-small', 'small', 'medium', 'large']),
+ borderRadius: PropTypes.oneOf(['square', 'semi-rounded', 'rounded']),
};
Marker.defaultProps = {
@@ -32,4 +38,5 @@ Marker.defaultProps = {
isVisible: false,
variant: 'default',
size: 'medium',
+ borderRadius: 'rounded',
};
diff --git a/src/components/RadioButtonGroup/readme.md b/src/components/RadioButtonGroup/readme.md
index b7725b6a0..b5a4e4e6a 100644
--- a/src/components/RadioButtonGroup/readme.md
+++ b/src/components/RadioButtonGroup/readme.md
@@ -271,7 +271,7 @@ class RequiredRadioButtonGroup extends React.Component {
##### RadioButtonGroup error
```js
-import React from 'react';
+import React , { useState } from 'react';
import { RadioButtonGroup } from 'react-rainbow-components';
const options = [
@@ -281,36 +281,23 @@ const options = [
{ value: 'on', label: 'On' },
];
-class ErrorRadioButtonGroup extends React.Component {
- constructor(props) {
- super(props);
- this.state = {
- value: 'anonymous',
- };
- this.handleOnChange = this.handleOnChange.bind(this);
- }
-
- handleOnChange(event) {
- return this.setState({ value: event.target.value });
- }
-
- render() {
- const { value } = this.state;
+ const ErrorRadioButtonGroup = () => {
+ const [value, setValue] = useState('anonymous');
+ const handleOnChange = event => setValue(event.target.value);
return (
);
}
-}
-
-
-
+
+
+
```
@@ -499,3 +486,69 @@ const Contacts = ({ data: contacts }) => {
```
+
+
+##### RadioButtonGroup with different Border Radius
+
+```js
+
+ import React, { useState } from 'react';
+ import { RadioButtonGroup } from 'react-rainbow-components';
+
+ const options = [
+ { value: 'off', label: 'Off' },
+ { value: 'parking', label: 'Parking' },
+ { value: 'auto', label: 'Auto' },
+ { value: 'on', label: 'On' },
+ ];
+
+ const BorderRadiusRadioButtonGroup = () => {
+ const [value1, setValue1] = useState('auto');
+ const [value2, setValue2] = useState('auto');
+ const [value3, setValue3] = useState('auto');
+
+ const handleOnChange1 = event => {
+ setValue1(event.target.value);
+ }
+ const handleOnChange2 = event => {
+ setValue2(event.target.value);
+ }
+ const handleOnChange3 = event => {
+ setValue3(event.target.value);
+ }
+
+ return (
+ <>
+
+
+
+ >
+ );
+ }
+
+
+
+
+
+```
\ No newline at end of file
diff --git a/src/components/RadioButtonGroup/styled/buttonItemsContainer.js b/src/components/RadioButtonGroup/styled/buttonItemsContainer.js
index 805071398..8147edfd4 100644
--- a/src/components/RadioButtonGroup/styled/buttonItemsContainer.js
+++ b/src/components/RadioButtonGroup/styled/buttonItemsContainer.js
@@ -1,7 +1,11 @@
import styled from 'styled-components';
import attachThemeAttrs from '../../../styles/helpers/attachThemeAttrs';
import { replaceAlpha } from '../../../styles/helpers/color';
-import { BORDER_RADIUS_2 } from '../../../styles/borderRadius';
+import {
+ BORDER_RADIUS_2,
+ BORDER_RADIUS_SQUARE,
+ BORDER_RADIUS_SEMI_ROUNDED,
+} from '../../../styles/borderRadius';
import { COLOR_GRAY_2 } from '../../../styles/colors';
const sizeMap = { large: '3rem', medium: '2.5rem', small: '1.8rem', 'x-small': '1.3rem' };
@@ -31,6 +35,18 @@ const StyledButtonItemsContainer = attachThemeAttrs(styled.div).attrs(props => {
border: solid 1px ${props.inverse.border};
background-color: ${props.inverse.background};
`};
+
+ ${props =>
+ props.borderRadius === 'square' &&
+ `
+ border-radius: ${BORDER_RADIUS_SQUARE} !important;
+ `};
+
+ ${props =>
+ props.borderRadius === 'semi-rounded' &&
+ `
+ border-radius: ${BORDER_RADIUS_SEMI_ROUNDED} !important;
+ `};
`;
export default StyledButtonItemsContainer;
diff --git a/src/components/RadioButtonGroup/styled/marker.js b/src/components/RadioButtonGroup/styled/marker.js
index 6cf0d49af..0b33eafeb 100644
--- a/src/components/RadioButtonGroup/styled/marker.js
+++ b/src/components/RadioButtonGroup/styled/marker.js
@@ -1,7 +1,11 @@
/* stylelint-disable max-line-length */
import styled from 'styled-components';
import attachThemeAttrs from '../../../styles/helpers/attachThemeAttrs';
-import { BORDER_RADIUS_2 } from '../../../styles/borderRadius';
+import {
+ BORDER_RADIUS_2,
+ BORDER_RADIUS_SQUARE,
+ BORDER_RADIUS_SEMI_ROUNDED,
+} from '../../../styles/borderRadius';
const sizeMap = { large: '3.1rem', medium: '2.6rem', small: '1.81rem', 'x-small': '1.31rem' };
const StyledMarker = attachThemeAttrs(styled.span)`
@@ -32,6 +36,18 @@ const StyledMarker = attachThemeAttrs(styled.span)`
background-color: ${props.palette.brand.main};
border: solid 1px ${props.palette.brand.dark};
`};
+
+ ${props =>
+ props.borderRadius === 'square' &&
+ `
+ border-radius: ${BORDER_RADIUS_SQUARE} !important;
+ `};
+
+ ${props =>
+ props.borderRadius === 'semi-rounded' &&
+ `
+ border-radius: ${BORDER_RADIUS_SEMI_ROUNDED} !important;
+ `};
`;
export default StyledMarker;
diff --git a/src/components/Tab/__test__/tab.spec.js b/src/components/Tab/__test__/tab.spec.js
index c460717fa..ef0a06987 100644
--- a/src/components/Tab/__test__/tab.spec.js
+++ b/src/components/Tab/__test__/tab.spec.js
@@ -4,13 +4,17 @@ import Tab from '..';
describe('', () => {
it('should set the right class names when custom class name is passed', () => {
- const component = mount();
+ const component = mount(
+ {}} name="tab-1" className="custom-class-name" />,
+ );
expect(component.find('li.custom-class-name').exists()).toBe(true);
});
it('should call onSelect when clicked', () => {
const onSelectMockFn = jest.fn();
- const component = mount();
+ const component = mount(
+ {}} name="tab-1" onSelect={onSelectMockFn} />,
+ );
const aComponent = component.find('button');
aComponent.simulate('click');
@@ -18,56 +22,72 @@ describe('', () => {
});
it('should not call onSelect when clicked if disabled is passed', () => {
const onSelectMockFn = jest.fn();
- const component = mount();
+ const component = mount(
+ {}} name="tab-1" onSelect={onSelectMockFn} disabled />,
+ );
const button = component.find('button');
button.simulate('click');
expect(onSelectMockFn).toHaveBeenCalledTimes(0);
});
it('should set role to presentation in li.', () => {
- const component = mount();
+ const component = mount(
+ {}} name="tab-1" activeTabName="tab-2" />,
+ );
const listItem = component.find('li');
expect(listItem.prop('role')).toBe('presentation');
});
it('should set the title passed as title in li.', () => {
- const component = mount();
+ const component = mount(
+ {}} name="tab-1" title="tab 1" activeTabName="tab-2" />,
+ );
const listItem = component.find('li');
expect(listItem.prop('title')).toBe('tab 1');
});
it('should set role to tab in button element', () => {
- const component = mount();
+ const component = mount(
+ {}} name="tab-1" activeTabName="tab-2" />,
+ );
const button = component.find('button');
expect(button.prop('role')).toBe('tab');
});
it('should set aria-selected to true in button element when the tab is selected', () => {
- const component = mount();
+ const component = mount(
+ {}} name="tab-1" activeTabName="tab-1" />,
+ );
const button = component.find('button');
expect(button.prop('aria-selected')).toBe(true);
});
it('should set tabIndex to 0 in button element when tab is selected', () => {
- const component = mount();
+ const component = mount(
+ {}} name="tab-1" activeTabName="tab-1" />,
+ );
const button = component.find('button');
expect(button.prop('tabIndex')).toBe(0);
});
it('should set tabIndex to -1 in button element when tab is not selected', () => {
- const component = mount();
+ const component = mount(
+ {}} name="tab-1" activeTabName="tab-2" />,
+ );
const button = component.find('button');
expect(button.prop('tabIndex')).toBe(-1);
});
it('should set id in the button element', () => {
- const component = mount();
+ const component = mount( {}} name="tab-1" id="tab 1" />);
const button = component.find('button');
expect(button.prop('id')).toBe('tab 1');
});
it('should set id in the button element', () => {
- const component = mount();
+ const component = mount(
+ {}} name="tab-1" ariaControls="tab-content-1" />,
+ );
const button = component.find('button');
expect(button.prop('aria-controls')).toBe('tab-content-1');
@@ -75,7 +95,12 @@ describe('', () => {
it('should call privateUpdateTab function with right data when a tab is changed', () => {
const privateUpdateTabMockFn = jest.fn();
const component = mount(
- ,
+ {}}
+ label="Tab-1"
+ name="tab-1"
+ privateUpdateTab={privateUpdateTabMockFn}
+ />,
);
component.setProps({ name: 'tab-2' });
const newData = {
@@ -88,13 +113,20 @@ describe('', () => {
it('should not call privateUpdateTab function if any tab is changed', () => {
const privateUpdateTabMockFn = jest.fn();
const component = mount(
- ,
+ {}}
+ label="Tab-1"
+ name="tab-1"
+ privateUpdateTab={privateUpdateTabMockFn}
+ />,
);
component.setProps({ name: 'tab-1' });
expect(privateUpdateTabMockFn).toHaveBeenCalledTimes(0);
});
it('should set type to "button" in button element', () => {
- const component = mount();
+ const component = mount(
+ {}} name="tab-1" activeTabName="tab-2" />,
+ );
const button = component.find('button');
expect(button.prop('type')).toBe('button');
});
diff --git a/src/components/Tab/index.js b/src/components/Tab/index.js
index 3f256a857..fbf7a6e34 100644
--- a/src/components/Tab/index.js
+++ b/src/components/Tab/index.js
@@ -16,7 +16,7 @@ class TabItem extends Component {
componentDidMount() {
const { privateRegisterTab, name, disabled } = this.props;
if (!disabled) {
- setTimeout(() => privateRegisterTab({ name, ref: this.tabRef.current }), 0);
+ privateRegisterTab({ name, ref: this.tabRef.current });
}
}
diff --git a/src/components/Tabset/__test__/tabset.spec.js b/src/components/Tabset/__test__/tabset.spec.js
index 493e3c24a..a359ea6ee 100644
--- a/src/components/Tabset/__test__/tabset.spec.js
+++ b/src/components/Tabset/__test__/tabset.spec.js
@@ -102,21 +102,6 @@ describe('', () => {
component.setProps();
expect(component.instance().updateButtonsVisibility).toHaveBeenCalledTimes(0);
});
- it('should call updateButtonsVisibility function when a child is changed', () => {
- isNotSameChildren.mockReset();
- isNotSameChildren.mockReturnValue(true);
- const component = mount(
-
-
-
-
- ,
- );
- component.instance().updateButtonsVisibility = jest.fn();
- component.instance().isFirstTime = false;
- component.setProps();
- expect(component.instance().updateButtonsVisibility).toHaveBeenCalledTimes(1);
- });
it('should call updateButtonsVisibility function and set isFirstTime to false when all children are registered and is first time', () => {
isNotSameChildren.mockReset();
isNotSameChildren.mockReturnValue(false);
@@ -129,12 +114,13 @@ describe('', () => {
);
component.instance().updateButtonsVisibility = jest.fn();
expect(component.instance().isFirstTime).toBe(true);
+ component.instance().tabsetChildren = [
+ ,
+ ,
+ ,
+ ];
component.setState({
- tabsetChildren: [
- ,
- ,
- ,
- ],
+ key: Date.now(),
});
expect(component.instance().updateButtonsVisibility).toHaveBeenCalledTimes(1);
expect(component.instance().isFirstTime).toBe(false);
@@ -178,12 +164,13 @@ describe('', () => {
,
);
component.instance().tabsetRef.current = { offsetWidth: 500 };
+ component.instance().tabsetChildren = [
+ ,
+ ,
+ ,
+ ];
component.setState({
- tabsetChildren: [
- ,
- ,
- ,
- ],
+ key: Date.now(),
});
expect(component.state().areButtonsVisible).toBe(true);
});
diff --git a/src/components/Tabset/index.js b/src/components/Tabset/index.js
index 2086adc18..72282fa63 100644
--- a/src/components/Tabset/index.js
+++ b/src/components/Tabset/index.js
@@ -1,5 +1,4 @@
-/* eslint-disable react/sort-comp */
-/* eslint-disable max-len */
+/* eslint-disable react/no-unused-state */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Provider } from './context';
@@ -38,7 +37,7 @@ export default class Tabset extends Component {
constructor(props) {
super(props);
this.state = {
- tabsetChildren: [],
+ key: Date.now(),
areButtonsVisible: false,
};
this.isFirstTime = true;
@@ -56,6 +55,7 @@ export default class Tabset extends Component {
[RIGHT_KEY]: () => this.selectTab(RIGHT_SIDE),
[LEFT_KEY]: () => this.selectTab(LEFT_SIDE),
};
+ this.tabsetChildren = [];
}
componentDidMount() {
@@ -67,9 +67,8 @@ export default class Tabset extends Component {
componentDidUpdate(prevProp) {
const { children } = this.props;
- const { tabsetChildren } = this.state;
const { isFirstTime } = this;
- const areAllChildrenRegistered = children.length === tabsetChildren.length;
+ const areAllChildrenRegistered = children.length === this.tabsetChildren.length;
if (isNotSameChildren(children, prevProp.children)) {
this.updateButtonsVisibility();
}
@@ -84,17 +83,16 @@ export default class Tabset extends Component {
}
setAsSelectedTab(tabIndex) {
- const { tabsetChildren } = this.state;
- tabsetChildren[tabIndex].ref.click();
- tabsetChildren[tabIndex].ref.focus();
+ this.tabsetChildren[tabIndex].ref.click();
+ this.tabsetChildren[tabIndex].ref.focus();
}
updateButtonsVisibility() {
- const { tabsetChildren, areButtonsVisible, variant } = this.state;
+ const { areButtonsVisible, variant } = this.state;
const tabset = this.tabsetRef.current;
const { offsetWidth: resizeWidth } = this.resizeTarget.current;
const { scrollWidth, scrollLeft, offsetWidth: tabsetWidth } = tabset;
- const childrenTotalWidth = getChildrenTotalWidth(tabsetChildren);
+ const childrenTotalWidth = getChildrenTotalWidth(this.tabsetChildren);
const buttonWidth = areButtonsVisible ? 94 : 0;
const padding = resizeWidth - tabsetWidth - buttonWidth;
const delta = variant === 'line' ? 0 : 1;
@@ -115,7 +113,7 @@ export default class Tabset extends Component {
selectTab(side) {
const { activeTabName } = this.props;
- const { tabsetChildren } = this.state;
+ const { tabsetChildren } = this;
const activeTabIndex = getTabIndexFromName(tabsetChildren, activeTabName);
if (activeTabIndex === tabsetChildren.length - 1 && side === RIGHT_SIDE) {
@@ -129,7 +127,7 @@ export default class Tabset extends Component {
isLeftButtonDisabled() {
const { activeTabName } = this.props;
- const { tabsetChildren } = this.state;
+ const { tabsetChildren } = this;
const { screenWidth, scrollLeft } = this;
return getLeftButtonDisabledState({
activeTabName,
@@ -141,7 +139,7 @@ export default class Tabset extends Component {
isRightButtonDisabled() {
const { activeTabName } = this.props;
- const { tabsetChildren } = this.state;
+ const { tabsetChildren } = this;
const { screenWidth, scrollLeft, maxScroll } = this;
return getRightButtonDisabledState({
activeTabName,
@@ -169,26 +167,29 @@ export default class Tabset extends Component {
}
updateTab(tab, nameToUpdate) {
- const { tabsetChildren } = this.state;
+ const { tabsetChildren } = this;
const newTabsetChildren = getUpdatedTabsetChildren(tabsetChildren, tab, nameToUpdate);
- this.setState({ tabsetChildren: newTabsetChildren });
+ this.tabsetChildren = newTabsetChildren;
+ this.setState({ key: Date.now() });
}
registerTab(tab) {
- const { tabsetChildren } = this.state;
+ const { tabsetChildren } = this;
const [...nodes] = getChildTabNodes(this.tabsetRef.current);
const newChildrenRefs = insertChildOrderly(tabsetChildren, tab, nodes);
- this.setState({ tabsetChildren: newChildrenRefs });
+ this.tabsetChildren = newChildrenRefs;
+ this.setState({ key: Date.now() });
}
unRegisterTab(tabName) {
- const { tabsetChildren } = this.state;
+ const { tabsetChildren } = this;
const newTabsetChildren = tabsetChildren.filter(tab => tab.name !== tabName);
- this.setState({ tabsetChildren: newTabsetChildren });
+ this.tabsetChildren = newTabsetChildren;
+ this.setState({ key: Date.now() });
}
scrollToSelectedTab(name) {
- const { tabsetChildren } = this.state;
+ const { tabsetChildren } = this;
const tabset = this.tabsetRef.current;
const { scrollLeft, offsetWidth: tabsetWidth } = tabset;
const tabIndex = getTabIndexFromName(tabsetChildren, name);
diff --git a/src/components/VerticalItem/index.js b/src/components/VerticalItem/index.js
index 0e869cd1f..15e208ab3 100644
--- a/src/components/VerticalItem/index.js
+++ b/src/components/VerticalItem/index.js
@@ -66,6 +66,9 @@ function Item(props) {
tabIndex={resolveTabIndex()}
isSelected={isSelected}
>
+
+ {icon}
+
@@ -79,12 +82,12 @@ function Item(props) {
tabIndex={resolveTabIndex()}
isSelected={isSelected}
>
+
+ {icon}
+
-
- {icon}
-
);
}