From 9d5dc6c157134d1bf4a498ff4e54266230407136 Mon Sep 17 00:00:00 2001 From: Daniel Silva Date: Fri, 29 Mar 2019 11:24:06 -0300 Subject: [PATCH 01/14] fix(Input style): Fix wrong error style var name --- components/shared/inputStyle.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/shared/inputStyle.jsx b/components/shared/inputStyle.jsx index 842ff5ed5..9b9f589eb 100644 --- a/components/shared/inputStyle.jsx +++ b/components/shared/inputStyle.jsx @@ -22,7 +22,7 @@ const HOVER_STYLE = css` box-shadow: 0 2px 6px 0 ${Colors.BLUE['50']}; `; -const ERROR_STŸLE = css` +const ERROR_STYLE = css` border-color: ${Colors.ERROR['500']}; `; @@ -77,7 +77,7 @@ const INPUT_STYLE = css` ${({ error }) => error && css` - ${ERROR_STŸLE} + ${ERROR_STYLE} :hover, :focus { ${ERROR_HOVER_STYLE} @@ -100,7 +100,7 @@ const INPUT_STYLE = css` export { DEFAULT_STYLE, HOVER_STYLE, - ERROR_STŸLE, + ERROR_STYLE, ERROR_HOVER_STYLE, DISABLED_STYLE, LABEL_STYLE, From 700cd643b00988929c334c05bacf08b9d3304505 Mon Sep 17 00:00:00 2001 From: Daniel Silva Date: Mon, 1 Apr 2019 06:04:26 -0300 Subject: [PATCH 02/14] feat(Radio Button Group): Radio Button Component --- components/RadioGroup/RadioButton.jsx | 61 +++++++++++++++++++++++++++ components/RadioGroup/RadioGroup.jsx | 2 + 2 files changed, 63 insertions(+) create mode 100644 components/RadioGroup/RadioButton.jsx diff --git a/components/RadioGroup/RadioButton.jsx b/components/RadioGroup/RadioButton.jsx new file mode 100644 index 000000000..a0d2c0eda --- /dev/null +++ b/components/RadioGroup/RadioButton.jsx @@ -0,0 +1,61 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import styled, { css } from 'styled-components'; +import Colors from '../Colors'; +import Button from '../Button'; +import { INPUT_STYLE } from '../shared'; + +const { ERROR_STYLE, ERROR_HOVER_STYLE } = INPUT_STYLE; + +const StyledButton = styled(Button)` + ${({ error }) => + error && + css` + ${ERROR_STYLE} + color: ${Colors.ERROR['500']}; + + :hover, :focus { + ${ERROR_HOVER_STYLE}; + color: ${Colors.ERROR['500']}; + background-color: ${Colors.ERROR['200']}; + } + `} +`; + +const RadioButton = ({ + children, + label, + onChange, + value, + checked, + ...rest +}) => { + const skin = checked ? 'primary' : 'secondary'; + + return ( + + {children} + + ); +}; + +RadioButton.displayName = 'RadioGroup.Radio'; + +RadioButton.defaultProps = { + disabled: false, + checked: false, + children: undefined, + label: undefined, + onChange: () => {}, +}; + +RadioButton.propTypes = { + disabled: PropTypes.bool, + checked: PropTypes.bool, + children: PropTypes.string, + label: PropTypes.string, + value: PropTypes.string.isRequired, + onChange: PropTypes.func, +}; + +export default RadioButton; diff --git a/components/RadioGroup/RadioGroup.jsx b/components/RadioGroup/RadioGroup.jsx index c7ec684d6..d238f172a 100644 --- a/components/RadioGroup/RadioGroup.jsx +++ b/components/RadioGroup/RadioGroup.jsx @@ -4,6 +4,7 @@ import styled from 'styled-components'; import { FieldGroup, ErrorMessage } from '../shared'; import Radio from './Radio'; +import RadioButton from './RadioButton'; const Group = styled(FieldGroup).attrs({ role: 'radiogroup', @@ -58,6 +59,7 @@ const RadioGroup = ({ }; RadioGroup.Radio = Radio; +RadioGroup.Button = RadioButton; /** * Group for Radio components. From b233185345527548364fb9968ebcdca55ccb8dec Mon Sep 17 00:00:00 2001 From: Daniel Silva Date: Mon, 1 Apr 2019 06:06:50 -0300 Subject: [PATCH 03/14] feat(Radio Button Group): Radio Group Label --- components/Button/Button.jsx | 118 +----------------------- components/Button/buttonStyle.js | 120 +++++++++++++++++++++++++ components/RadioGroup/RadioButton.jsx | 67 ++++++++------ components/shared/ButtonGroupLabel.jsx | 33 +++++++ components/shared/index.js | 2 + 5 files changed, 195 insertions(+), 145 deletions(-) create mode 100644 components/Button/buttonStyle.js create mode 100644 components/shared/ButtonGroupLabel.jsx diff --git a/components/Button/Button.jsx b/components/Button/Button.jsx index b95cc5ca6..f54c918af 100644 --- a/components/Button/Button.jsx +++ b/components/Button/Button.jsx @@ -2,21 +2,9 @@ import React from 'react'; import PropTypes from 'prop-types'; import styled from 'styled-components'; -import theme from '../shared/theme'; -import skins from './skins'; import Icon from '../Icon/Icon'; import Colors from '../Colors'; - -const fontSize = ({ size }) => { - const sizes = { - xsmall: '12px', - small: '12px', - medium: '16px', - large: '20px', - xlarge: '24px', - }; - return `font-size: ${sizes[size] || sizes.medium};`; -}; +import buttonStyle from './buttonStyle'; const iconSize = ({ size }) => { const sizes = { @@ -30,118 +18,16 @@ const iconSize = ({ size }) => { return `font-size: ${sizes[size] || sizes.normal};`; }; -const padding = ({ size }) => { - const paddings = { - xsmall: '0 12px', - small: '0 12px', - medium: '0 16px', - large: '0 16px', - xlarge: '0 16px', - }; - - return `padding: ${paddings[size] || paddings.medium};`; -}; - -const height = ({ size }) => { - const heights = { - xsmall: '24px', - small: '32px', - medium: '40px', - large: '48px', - xlarge: '56px', - }; - - return `height: ${heights[size] || heights.medium};`; -}; - const ButtonIcon = styled(Icon)` pointer-events: none; `; const StyledButton = styled.button` - display: flex; - align-items: center; - justify-content: center; - font-weight: bold; - letter-spacing: 0.2px; - - *:nth-child(2) { - margin-left: 5px; - } - - ${fontSize} - ${padding} - ${height} - ${theme.mixins.transition()}; + ${buttonStyle} ${ButtonIcon} { ${iconSize} } - - ${props => `cursor: ${props.disabled ? 'not-allowed' : 'pointer'};`} - ${props => props.full && `width: 100%;`} - ${props => - props.center && - ` - margin-left: auto; - margin-right: auto; - `} - - ${props => { - const { - unselected, - selected, - disabled, - focused, - hovered, - decoration, - borderRadius, - } = skins(props); - - return `${` - background-color: ${ - props.disabled ? disabled.background : unselected.background - }; - border: 1.5px solid ${ - props.disabled ? disabled.border : unselected.border - }; - - box-shadow: ${props.disabled ? disabled.shadow : unselected.shadow}; - - color: ${props.disabled ? disabled.color : unselected.color}; - - ${decoration ? `text-decoration: ${decoration};` : ''} - ${borderRadius ? `border-radius: ${borderRadius};` : ''} - `} - - ${ - !props.disabled - ? ` - &:hover { - box-shadow: ${hovered.shadow}; - background-color: ${hovered.background}; - border-color: ${hovered.border}; - color: ${hovered.color}; - } - ` - : '' - } - - &:focus { - box-shadow: ${focused.shadow}; - background-color: ${focused.background}; - border-color: ${focused.border}; - color: ${focused.color}; - } - - &:active { - box-shadow: ${selected.shadow}; - background-color: ${selected.background}; - border-color: ${selected.border}; - color: ${selected.color}; - } - `; - }} `; const Button = ({ children, icon, size, ...rest }) => ( diff --git a/components/Button/buttonStyle.js b/components/Button/buttonStyle.js new file mode 100644 index 000000000..ed1af1727 --- /dev/null +++ b/components/Button/buttonStyle.js @@ -0,0 +1,120 @@ +import { css } from 'styled-components'; +import skins from './skins'; + +const fontSize = ({ size }) => { + const sizes = { + xsmall: '12px', + small: '12px', + medium: '16px', + large: '20px', + xlarge: '24px', + }; + return `font-size: ${sizes[size] || sizes.medium};`; +}; + +const padding = ({ size }) => { + const paddings = { + xsmall: '0 12px', + small: '0 12px', + medium: '0 16px', + large: '0 16px', + xlarge: '0 16px', + }; + + return `padding: ${paddings[size] || paddings.medium};`; +}; + +const height = ({ size }) => { + const heights = { + xsmall: '24px', + small: '32px', + medium: '40px', + large: '48px', + xlarge: '56px', + }; + + return `height: ${heights[size] || heights.medium};`; +}; + +const skin = props => { + const { + unselected, + selected, + disabled, + focused, + hovered, + decoration, + borderRadius, + } = skins(props); + + return `${` + background-color: ${ + props.disabled ? disabled.background : unselected.background + }; + border: 1.5px solid ${props.disabled ? disabled.border : unselected.border}; + + box-shadow: ${props.disabled ? disabled.shadow : unselected.shadow}; + + color: ${props.disabled ? disabled.color : unselected.color}; + + ${decoration ? `text-decoration: ${decoration};` : ''} + ${borderRadius ? `border-radius: ${borderRadius};` : ''} + `} + + ${ + !props.disabled + ? ` + &:hover { + box-shadow: ${hovered.shadow}; + background-color: ${hovered.background}; + border-color: ${hovered.border}; + color: ${hovered.color}; + } + ` + : '' + } + + &:focus { + box-shadow: ${focused.shadow}; + background-color: ${focused.background}; + border-color: ${focused.border}; + color: ${focused.color}; + } + + &:active { + box-shadow: ${selected.shadow}; + background-color: ${selected.background}; + border-color: ${selected.border}; + color: ${selected.color}; + } + `; +}; + +export default css` + align-items: center; + ${props => `cursor: ${props.disabled ? 'not-allowed' : 'pointer'};`} + display: flex; + ${fontSize} + font-weight: bold; + ${height} + justify-content: center; + ${padding} + letter-spacing: 0.2px; + + ${props => + props.center && + ` + margin-left: auto; + margin-right: auto; + `} + + *:nth-child(2) { + margin-left: 5px; + } + + transition: all 0.2s ease-in-out; + + ${props => props.full && `width: 100%;`} + + ${skin} +`; diff --git a/components/RadioGroup/RadioButton.jsx b/components/RadioGroup/RadioButton.jsx index a0d2c0eda..7a24152cf 100644 --- a/components/RadioGroup/RadioButton.jsx +++ b/components/RadioGroup/RadioButton.jsx @@ -1,30 +1,26 @@ import React from 'react'; import PropTypes from 'prop-types'; -import styled, { css } from 'styled-components'; -import Colors from '../Colors'; -import Button from '../Button'; -import { INPUT_STYLE } from '../shared'; +import styled from 'styled-components'; +import ButtonGroupLabel from '../shared/ButtonGroupLabel'; -const { ERROR_STYLE, ERROR_HOVER_STYLE } = INPUT_STYLE; - -const StyledButton = styled(Button)` - ${({ error }) => - error && - css` - ${ERROR_STYLE} - color: ${Colors.ERROR['500']}; - - :hover, :focus { - ${ERROR_HOVER_STYLE}; - color: ${Colors.ERROR['500']}; - background-color: ${Colors.ERROR['200']}; - } - `} +const StyledRadio = styled.input.attrs({ + type: 'radio', +})` + border: 0; + height: 0; + margin: 0; + opacity: 0; + overflow: hidden; + padding: 0; + position: absolute; + width: 0; `; -const RadioButton = ({ +const Radio = ({ children, label, + error, + disabled, onChange, value, checked, @@ -33,29 +29,42 @@ const RadioButton = ({ const skin = checked ? 'primary' : 'secondary'; return ( - - {children} - + + onChange({ value, label }, e)} + {...rest} + /> + {children || label} + ); }; -RadioButton.displayName = 'RadioGroup.Radio'; +Radio.displayName = 'RadioGroup.Radio'; -RadioButton.defaultProps = { - disabled: false, +Radio.defaultProps = { checked: false, + disabled: false, + error: false, children: undefined, label: undefined, onChange: () => {}, }; -RadioButton.propTypes = { - disabled: PropTypes.bool, +Radio.propTypes = { checked: PropTypes.bool, + disabled: PropTypes.bool, + error: PropTypes.bool, children: PropTypes.string, label: PropTypes.string, value: PropTypes.string.isRequired, onChange: PropTypes.func, }; -export default RadioButton; +export default Radio; diff --git a/components/shared/ButtonGroupLabel.jsx b/components/shared/ButtonGroupLabel.jsx new file mode 100644 index 000000000..d81648e14 --- /dev/null +++ b/components/shared/ButtonGroupLabel.jsx @@ -0,0 +1,33 @@ +import styled, { css } from 'styled-components'; +import Colors from '../Colors'; +import buttonStyle from '../Button/buttonStyle'; +import Label from './Label'; +import { ERROR_HOVER_STYLE, ERROR_STYLE } from './inputStyle'; + +export default styled(Label)` + ${buttonStyle} + + margin-bottom: 16px; + + ${({ error, checked }) => + error && + css` + color: ${Colors.ERROR['500']}; + + ${ERROR_STYLE} + + :hover, :focus { + ${ERROR_HOVER_STYLE} + + color: ${checked ? Colors.WHITE : Colors.ERROR['500']}; + border-color: ${checked ? Colors.ERROR['900'] : Colors.ERROR['500']}; + background-color: ${checked ? Colors.ERROR['900'] : Colors.ERROR['200']}; + } + + ${checked && + ` + background-color: ${Colors.ERROR['500']}; + color: ${Colors.ERROR['200']}; + `} + `} +`; diff --git a/components/shared/index.js b/components/shared/index.js index 865d641ec..7c6cdc355 100644 --- a/components/shared/index.js +++ b/components/shared/index.js @@ -6,6 +6,7 @@ import masks from './masks'; import BREAKPOINTS from './breakpoints'; import uniqId from './uniqId'; import * as INPUT_STYLE from './inputStyle'; +import ButtonGroupLabel from './ButtonGroupLabel'; export { ErrorMessage, @@ -16,4 +17,5 @@ export { BREAKPOINTS, INPUT_STYLE, uniqId, + ButtonGroupLabel, }; From 455151950304dc36ac620936c9770a5a1c5cf782 Mon Sep 17 00:00:00 2001 From: Daniel Silva Date: Mon, 1 Apr 2019 06:07:41 -0300 Subject: [PATCH 04/14] refactor(Radio Group): Refactor radio group --- components/RadioGroup/HiddenRadio.jsx | 14 ++++++++++++++ components/RadioGroup/Radio.jsx | 2 -- components/RadioGroup/RadioGroup.jsx | 6 +++--- 3 files changed, 17 insertions(+), 5 deletions(-) create mode 100644 components/RadioGroup/HiddenRadio.jsx diff --git a/components/RadioGroup/HiddenRadio.jsx b/components/RadioGroup/HiddenRadio.jsx new file mode 100644 index 000000000..bdd818f31 --- /dev/null +++ b/components/RadioGroup/HiddenRadio.jsx @@ -0,0 +1,14 @@ +import styled from 'styled-components'; + +export default styled.input.attrs({ + type: 'radio', +})` + border: 0; + height: 0; + margin: 0; + opacity: 0; + overflow: hidden; + padding: 0; + position: absolute; + width: 0; +`; diff --git a/components/RadioGroup/Radio.jsx b/components/RadioGroup/Radio.jsx index c2dd7640c..3366a4953 100644 --- a/components/RadioGroup/Radio.jsx +++ b/components/RadioGroup/Radio.jsx @@ -186,8 +186,6 @@ const Radio = ({ ); -Radio.create = radio => ; - Radio.displayName = 'RadioGroup.Radio'; Radio.defaultProps = { diff --git a/components/RadioGroup/RadioGroup.jsx b/components/RadioGroup/RadioGroup.jsx index d238f172a..983c0f58a 100644 --- a/components/RadioGroup/RadioGroup.jsx +++ b/components/RadioGroup/RadioGroup.jsx @@ -42,17 +42,17 @@ const RadioGroup = ({ }), ); - const listItems = + const items = React.Children.map(children, child => React.cloneElement(child, { checked: child.props.value === value ? true : undefined, ...commonProps, }), - ) || radioOptions.map(Radio.create); + ) || radioOptions.map(props => ); return ( - {listItems} + {items} {error && {error}} ); From 88e7431307a22089f1dae435233a3ea28ad063be Mon Sep 17 00:00:00 2001 From: Daniel Silva Date: Mon, 1 Apr 2019 06:08:16 -0300 Subject: [PATCH 05/14] docs(Radio Button Group): Radio Button Story --- .../__snapshots__/Alert.unit.test.jsx.snap | 156 ++++---- .../__snapshots__/Badge.unit.test.jsx.snap | 26 +- .../__snapshots__/Button.unit.test.jsx.snap | 368 +++++++++--------- .../__snapshots__/Form.unit.test.jsx.snap | 26 +- .../__snapshots__/Modal.unit.test.jsx.snap | 71 ++-- stories/RadioGroup/RadioGroup.story.jsx | 5 + .../RadioGroup/sub-components/buttonGroup.jsx | 36 ++ stories/RadioGroup/sub-components/index.jsx | 3 +- .../sub-components/simpleRadioGroup.jsx | 6 +- 9 files changed, 369 insertions(+), 328 deletions(-) create mode 100644 stories/RadioGroup/sub-components/buttonGroup.jsx diff --git a/components/Alert/__snapshots__/Alert.unit.test.jsx.snap b/components/Alert/__snapshots__/Alert.unit.test.jsx.snap index 9f16163d9..eedfe9ac1 100644 --- a/components/Alert/__snapshots__/Alert.unit.test.jsx.snap +++ b/components/Alert/__snapshots__/Alert.unit.test.jsx.snap @@ -6,29 +6,29 @@ exports[`Alert component Should match the snapshot of a simple alert 1`] = ` } .c5 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; align-items: center; + cursor: pointer; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + font-size: 16px; + font-weight: bold; + height: 40px; -webkit-box-pack: center; -webkit-justify-content: center; -ms-flex-pack: center; justify-content: center; - font-weight: bold; + padding: 0 16px; -webkit-letter-spacing: 0.2px; -moz-letter-spacing: 0.2px; -ms-letter-spacing: 0.2px; letter-spacing: 0.2px; - font-size: 16px; - padding: 0 16px; - height: 40px; -webkit-transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out; - cursor: pointer; background-color: #1355d0; border: 1.5px solid #1355d0; box-shadow: 0 2px 4px 0 #cccccc; @@ -42,10 +42,6 @@ exports[`Alert component Should match the snapshot of a simple alert 1`] = ` margin-left: 5px; } -.c5 .c6 { - font-size: 24px; -} - .c5:hover { box-shadow: 0 2px 4px 0 #cccccc; background-color: #002f7b; @@ -67,6 +63,10 @@ exports[`Alert component Should match the snapshot of a simple alert 1`] = ` color: #FFFFFF; } +.c5 .c6 { + font-size: 24px; +} + .c2 { -webkit-align-items: start; -webkit-box-align: start; @@ -172,29 +172,29 @@ exports[`Alert component When you set a alert custom icon Should match the snaps } .c6 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; align-items: center; + cursor: pointer; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + font-size: 16px; + font-weight: bold; + height: 40px; -webkit-box-pack: center; -webkit-justify-content: center; -ms-flex-pack: center; justify-content: center; - font-weight: bold; + padding: 0 16px; -webkit-letter-spacing: 0.2px; -moz-letter-spacing: 0.2px; -ms-letter-spacing: 0.2px; letter-spacing: 0.2px; - font-size: 16px; - padding: 0 16px; - height: 40px; -webkit-transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out; - cursor: pointer; background-color: #1355d0; border: 1.5px solid #1355d0; box-shadow: 0 2px 4px 0 #cccccc; @@ -208,10 +208,6 @@ exports[`Alert component When you set a alert custom icon Should match the snaps margin-left: 5px; } -.c6 .c7 { - font-size: 24px; -} - .c6:hover { box-shadow: 0 2px 4px 0 #cccccc; background-color: #002f7b; @@ -233,6 +229,10 @@ exports[`Alert component When you set a alert custom icon Should match the snaps color: #FFFFFF; } +.c6 .c7 { + font-size: 24px; +} + .c2 { -webkit-align-items: start; -webkit-box-align: start; @@ -349,29 +349,29 @@ exports[`Alert component When you set a different skin Should match a skin snaps } .c5 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; align-items: center; + cursor: pointer; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + font-size: 16px; + font-weight: bold; + height: 40px; -webkit-box-pack: center; -webkit-justify-content: center; -ms-flex-pack: center; justify-content: center; - font-weight: bold; + padding: 0 16px; -webkit-letter-spacing: 0.2px; -moz-letter-spacing: 0.2px; -ms-letter-spacing: 0.2px; letter-spacing: 0.2px; - font-size: 16px; - padding: 0 16px; - height: 40px; -webkit-transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out; - cursor: pointer; background-color: #1355d0; border: 1.5px solid #1355d0; box-shadow: 0 2px 4px 0 #cccccc; @@ -385,10 +385,6 @@ exports[`Alert component When you set a different skin Should match a skin snaps margin-left: 5px; } -.c5 .c6 { - font-size: 24px; -} - .c5:hover { box-shadow: 0 2px 4px 0 #cccccc; background-color: #002f7b; @@ -410,6 +406,10 @@ exports[`Alert component When you set a different skin Should match a skin snaps color: #FFFFFF; } +.c5 .c6 { + font-size: 24px; +} + .c2 { -webkit-align-items: start; -webkit-box-align: start; @@ -515,29 +515,29 @@ exports[`Alert component When you set a different skin Should match a skin snaps } .c5 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; align-items: center; + cursor: pointer; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + font-size: 16px; + font-weight: bold; + height: 40px; -webkit-box-pack: center; -webkit-justify-content: center; -ms-flex-pack: center; justify-content: center; - font-weight: bold; + padding: 0 16px; -webkit-letter-spacing: 0.2px; -moz-letter-spacing: 0.2px; -ms-letter-spacing: 0.2px; letter-spacing: 0.2px; - font-size: 16px; - padding: 0 16px; - height: 40px; -webkit-transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out; - cursor: pointer; background-color: #1355d0; border: 1.5px solid #1355d0; box-shadow: 0 2px 4px 0 #cccccc; @@ -551,10 +551,6 @@ exports[`Alert component When you set a different skin Should match a skin snaps margin-left: 5px; } -.c5 .c6 { - font-size: 24px; -} - .c5:hover { box-shadow: 0 2px 4px 0 #cccccc; background-color: #002f7b; @@ -576,6 +572,10 @@ exports[`Alert component When you set a different skin Should match a skin snaps color: #FFFFFF; } +.c5 .c6 { + font-size: 24px; +} + .c2 { -webkit-align-items: start; -webkit-box-align: start; @@ -690,29 +690,29 @@ exports[`Alert component When you set a different skin Should match a skin snaps } .c5 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; align-items: center; + cursor: pointer; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + font-size: 16px; + font-weight: bold; + height: 40px; -webkit-box-pack: center; -webkit-justify-content: center; -ms-flex-pack: center; justify-content: center; - font-weight: bold; + padding: 0 16px; -webkit-letter-spacing: 0.2px; -moz-letter-spacing: 0.2px; -ms-letter-spacing: 0.2px; letter-spacing: 0.2px; - font-size: 16px; - padding: 0 16px; - height: 40px; -webkit-transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out; - cursor: pointer; background-color: #1355d0; border: 1.5px solid #1355d0; box-shadow: 0 2px 4px 0 #cccccc; @@ -726,10 +726,6 @@ exports[`Alert component When you set a different skin Should match a skin snaps margin-left: 5px; } -.c5 .c6 { - font-size: 24px; -} - .c5:hover { box-shadow: 0 2px 4px 0 #cccccc; background-color: #002f7b; @@ -751,6 +747,10 @@ exports[`Alert component When you set a different skin Should match a skin snaps color: #FFFFFF; } +.c5 .c6 { + font-size: 24px; +} + .c2 { -webkit-align-items: start; -webkit-box-align: start; @@ -874,29 +874,29 @@ exports[`Alert component When you set a different skin Should match a skin snaps } .c5 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; align-items: center; + cursor: pointer; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + font-size: 16px; + font-weight: bold; + height: 40px; -webkit-box-pack: center; -webkit-justify-content: center; -ms-flex-pack: center; justify-content: center; - font-weight: bold; + padding: 0 16px; -webkit-letter-spacing: 0.2px; -moz-letter-spacing: 0.2px; -ms-letter-spacing: 0.2px; letter-spacing: 0.2px; - font-size: 16px; - padding: 0 16px; - height: 40px; -webkit-transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out; - cursor: pointer; background-color: #1355d0; border: 1.5px solid #1355d0; box-shadow: 0 2px 4px 0 #cccccc; @@ -910,10 +910,6 @@ exports[`Alert component When you set a different skin Should match a skin snaps margin-left: 5px; } -.c5 .c6 { - font-size: 24px; -} - .c5:hover { box-shadow: 0 2px 4px 0 #cccccc; background-color: #002f7b; @@ -935,6 +931,10 @@ exports[`Alert component When you set a different skin Should match a skin snaps color: #FFFFFF; } +.c5 .c6 { + font-size: 24px; +} + .c2 { -webkit-align-items: start; -webkit-box-align: start; diff --git a/components/Badge/__snapshots__/Badge.unit.test.jsx.snap b/components/Badge/__snapshots__/Badge.unit.test.jsx.snap index e63f090a6..0c832932b 100644 --- a/components/Badge/__snapshots__/Badge.unit.test.jsx.snap +++ b/components/Badge/__snapshots__/Badge.unit.test.jsx.snap @@ -61,29 +61,29 @@ exports[` Should match snapshot with children 1`] = ` } .c2 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; align-items: center; + cursor: pointer; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + font-size: 16px; + font-weight: bold; + height: 40px; -webkit-box-pack: center; -webkit-justify-content: center; -ms-flex-pack: center; justify-content: center; - font-weight: bold; + padding: 0 16px; -webkit-letter-spacing: 0.2px; -moz-letter-spacing: 0.2px; -ms-letter-spacing: 0.2px; letter-spacing: 0.2px; - font-size: 16px; - padding: 0 16px; - height: 40px; -webkit-transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out; - cursor: pointer; background-color: #1355d0; border: 1.5px solid #1355d0; box-shadow: 0 2px 4px 0 #cccccc; @@ -97,10 +97,6 @@ exports[` Should match snapshot with children 1`] = ` margin-left: 5px; } -.c2 .c3 { - font-size: 24px; -} - .c2:hover { box-shadow: 0 2px 4px 0 #cccccc; background-color: #002f7b; @@ -122,6 +118,10 @@ exports[` Should match snapshot with children 1`] = ` color: #FFFFFF; } +.c2 .c3 { + font-size: 24px; +} +
Snapshots should match the snapshot 1`] = ` } .c11 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; align-items: center; + cursor: pointer; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + font-size: 16px; + font-weight: bold; + height: 40px; -webkit-box-pack: center; -webkit-justify-content: center; -ms-flex-pack: center; justify-content: center; - font-weight: bold; + padding: 0 16px; -webkit-letter-spacing: 0.2px; -moz-letter-spacing: 0.2px; -ms-letter-spacing: 0.2px; letter-spacing: 0.2px; - font-size: 16px; - padding: 0 16px; - height: 40px; -webkit-transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out; - cursor: pointer; background-color: #1355d0; border: 1.5px solid #1355d0; box-shadow: 0 2px 4px 0 #cccccc; @@ -73,10 +73,6 @@ exports[` Snapshots should match the snapshot 1`] = ` margin-left: 5px; } -.c11 .c12 { - font-size: 24px; -} - .c11:hover { box-shadow: 0 2px 4px 0 #cccccc; background-color: #002f7b; @@ -98,6 +94,10 @@ exports[` Snapshots should match the snapshot 1`] = ` color: #FFFFFF; } +.c11 .c12 { + font-size: 24px; +} + .c8 { padding: 12px 20px; font-size: 14px; @@ -246,29 +246,29 @@ exports[` Snapshots should match the snapshot 1`] = ` } .c11 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; align-items: center; + cursor: pointer; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + font-size: 16px; + font-weight: bold; + height: 40px; -webkit-box-pack: center; -webkit-justify-content: center; -ms-flex-pack: center; justify-content: center; - font-weight: bold; + padding: 0 16px; -webkit-letter-spacing: 0.2px; -moz-letter-spacing: 0.2px; -ms-letter-spacing: 0.2px; letter-spacing: 0.2px; - font-size: 16px; - padding: 0 16px; - height: 40px; -webkit-transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out; - cursor: pointer; background-color: #1355d0; border: 1.5px solid #1355d0; box-shadow: 0 2px 4px 0 #cccccc; @@ -282,10 +282,6 @@ exports[` Snapshots should match the snapshot 1`] = ` margin-left: 5px; } -.c11 .c12 { - font-size: 24px; -} - .c11:hover { box-shadow: 0 2px 4px 0 #cccccc; background-color: #002f7b; @@ -307,6 +303,10 @@ exports[` Snapshots should match the snapshot 1`] = ` color: #FFFFFF; } +.c11 .c12 { + font-size: 24px; +} + .c8 { padding: 12px 20px; font-size: 14px; @@ -992,26 +992,25 @@ exports[` Snapshots should match the snapshot 1`] = ` "isStatic": false, "lastClassName": "c11", "rules": Array [ - "display:flex;align-items:center;justify-content:center;font-weight:bold;letter-spacing:0.2px;*:nth-child(2){margin-left:5px;}", + "align-items:center;", [Function], - " ", + " display:flex;", [Function], - " ", + " font-weight:bold;", [Function], - " ", - "transition: all 0.2s ease-in-out", - ";", - ".c12", - "{", + " justify-content:center;", [Function], - "}", + " letter-spacing:0.2px;", [Function], - " ", + " *:nth-child(2){margin-left:5px;}transition:all 0.2s ease-in-out;", [Function], " ", [Function], " ", + ".c12", + "{", [Function], + "}", ], }, "displayName": "Button__StyledButton", diff --git a/stories/RadioGroup/RadioGroup.story.jsx b/stories/RadioGroup/RadioGroup.story.jsx index cd4bda3b7..438c8d1c3 100644 --- a/stories/RadioGroup/RadioGroup.story.jsx +++ b/stories/RadioGroup/RadioGroup.story.jsx @@ -62,6 +62,11 @@ stories.add('Radio group', () => (


+ + + +
+ diff --git a/stories/RadioGroup/sub-components/buttonGroup.jsx b/stories/RadioGroup/sub-components/buttonGroup.jsx new file mode 100644 index 000000000..d7e45b962 --- /dev/null +++ b/stories/RadioGroup/sub-components/buttonGroup.jsx @@ -0,0 +1,36 @@ +import React from 'react'; +import RadioGroup from '../../../components/RadioGroup'; + +class Group extends React.Component { + constructor(props) { + super(props); + + this.state = { value: undefined }; + } + + render() { + const { value } = this.state; + + return ( + this.setState({ value: opValue })} + > + Tomato sauce + Mustard + + Barbecue sauce Barbecue sauce Barbecue sauce + + + ); + } +} + +const buttonGroup = { + code: `;`, + component: , +}; + +export default buttonGroup; diff --git a/stories/RadioGroup/sub-components/index.jsx b/stories/RadioGroup/sub-components/index.jsx index 43a38fea5..0d2b2885e 100644 --- a/stories/RadioGroup/sub-components/index.jsx +++ b/stories/RadioGroup/sub-components/index.jsx @@ -1,5 +1,6 @@ import simpleRadioGroup from './simpleRadioGroup'; import propsRadioGroup from './propsRadioGroup'; import disabledRadio from './disabledRadio'; +import buttonGroup from './buttonGroup'; -export { simpleRadioGroup, propsRadioGroup, disabledRadio }; +export { simpleRadioGroup, propsRadioGroup, disabledRadio, buttonGroup }; diff --git a/stories/RadioGroup/sub-components/simpleRadioGroup.jsx b/stories/RadioGroup/sub-components/simpleRadioGroup.jsx index f75acfe25..c59790c0b 100644 --- a/stories/RadioGroup/sub-components/simpleRadioGroup.jsx +++ b/stories/RadioGroup/sub-components/simpleRadioGroup.jsx @@ -10,9 +10,9 @@ const options = [ const simpleRadioGroup = { code: `const options = ${JSON.stringify(options, null, 2)}; - /* or */ From e96319160aa1a313c1c2ed99be8fd89b12a4972b Mon Sep 17 00:00:00 2001 From: Daniel Silva Date: Tue, 2 Apr 2019 15:44:01 -0300 Subject: [PATCH 06/14] feat(Radio Button Group): Radio Button Group --- components/Button/buttonStyle.js | 28 +- components/RadioGroup/Radio.jsx | 25 +- components/RadioGroup/RadioButton.jsx | 83 +- .../RadioGroup/RadioButton.unit.test.jsx | 42 + components/RadioGroup/RadioGroup.jsx | 26 +- .../RadioGroup/RadioGroup.unit.test.jsx | 192 +++-- .../__snapshots__/Radio.unit.test.jsx.snap | 92 ++- .../RadioButton.unit.test.jsx.snap | 753 ++++++++++++++++++ .../RadioGroup.unit.test.jsx.snap | 610 +++++++++++++- components/shared/ButtonGroupLabel.jsx | 1 + .../RadioGroup/sub-components/buttonGroup.jsx | 9 +- 11 files changed, 1648 insertions(+), 213 deletions(-) create mode 100644 components/RadioGroup/RadioButton.unit.test.jsx create mode 100644 components/RadioGroup/__snapshots__/RadioButton.unit.test.jsx.snap diff --git a/components/Button/buttonStyle.js b/components/Button/buttonStyle.js index ed1af1727..e093292dd 100644 --- a/components/Button/buttonStyle.js +++ b/components/Button/buttonStyle.js @@ -70,22 +70,22 @@ const skin = props => { border-color: ${hovered.border}; color: ${hovered.color}; } - ` - : '' - } - &:focus { - box-shadow: ${focused.shadow}; - background-color: ${focused.background}; - border-color: ${focused.border}; - color: ${focused.color}; - } + &:focus { + box-shadow: ${focused.shadow}; + background-color: ${focused.background}; + border-color: ${focused.border}; + color: ${focused.color}; + } - &:active { - box-shadow: ${selected.shadow}; - background-color: ${selected.background}; - border-color: ${selected.border}; - color: ${selected.color}; + &:active { + box-shadow: ${selected.shadow}; + background-color: ${selected.background}; + border-color: ${selected.border}; + color: ${selected.color}; + } + ` + : '' } `; }; diff --git a/components/RadioGroup/Radio.jsx b/components/RadioGroup/Radio.jsx index 3366a4953..78bb75587 100644 --- a/components/RadioGroup/Radio.jsx +++ b/components/RadioGroup/Radio.jsx @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import styled from 'styled-components'; import Colors from '../Colors'; import Label from '../shared/Label'; +import HiddenRadio from './HiddenRadio'; const RadioMark = styled.span` background-color: ${Colors.WHITE}; @@ -29,24 +30,11 @@ const RadioMark = styled.span` } `; -const StyledRadio = styled.input.attrs({ - type: 'radio', -})` - border: 0; - height: 0; - margin: 0; - opacity: 0; - overflow: hidden; - padding: 0; - position: absolute; - width: 0; -`; - const RadioLabel = styled(Label)` cursor: pointer; user-select: none; - ${StyledRadio} { + ${HiddenRadio} { :checked { ~ ${RadioMark} { border-color: ${Colors.BLUE[500]}; @@ -76,7 +64,7 @@ const RadioLabel = styled(Label)` ${({ error }) => error && ` - ${StyledRadio} { + ${HiddenRadio} { :checked { ~ ${RadioMark} { border-color: ${Colors.ERROR[500]}; @@ -118,7 +106,7 @@ const RadioLabel = styled(Label)` cursor: not-allowed; } - ${StyledRadio} { + ${HiddenRadio} { :disabled { ~ ${RadioMark} { background-color: ${Colors.BLACK[200]}; @@ -159,7 +147,7 @@ const RadioLabel = styled(Label)` } `} - ${StyledRadio}:checked:disabled ~ ${RadioMark} { + ${HiddenRadio}:checked:disabled ~ ${RadioMark} { background-color: ${Colors.BLACK[400]}; border-color: ${Colors.BLACK[400]}; box-shadow: inset 0 0 0 3.5px ${Colors.WHITE}; @@ -176,9 +164,10 @@ const Radio = ({ ...rest }) => ( - onChange({ value, label }, e)} + value={value} {...rest} /> diff --git a/components/RadioGroup/RadioButton.jsx b/components/RadioGroup/RadioButton.jsx index 7a24152cf..cd8545a28 100644 --- a/components/RadioGroup/RadioButton.jsx +++ b/components/RadioGroup/RadioButton.jsx @@ -2,18 +2,34 @@ import React from 'react'; import PropTypes from 'prop-types'; import styled from 'styled-components'; import ButtonGroupLabel from '../shared/ButtonGroupLabel'; +import HiddenRadio from './HiddenRadio'; +import Icon from '../Icon'; -const StyledRadio = styled.input.attrs({ - type: 'radio', -})` - border: 0; - height: 0; - margin: 0; - opacity: 0; - overflow: hidden; - padding: 0; - position: absolute; - width: 0; +const LockIcon = styled(Icon).attrs({ + name: 'lock', +})``; + +const ButtonIcon = styled(Icon)` + margin-right: 8px; +`; + +const Wrapper = styled.div` + ${({ inline }) => + inline && + ` + display: inline-block; + vertical-align: top; + margin-right: 16px; + + :last-child { + margin-right: 0; + } + `} + + ${LockIcon} { + margin-left: 8px; + font-size: 17px; + } `; const Radio = ({ @@ -24,47 +40,58 @@ const Radio = ({ onChange, value, checked, + icon, + inline, ...rest }) => { const skin = checked ? 'primary' : 'secondary'; return ( - - + onChange({ value, label }, e)} - {...rest} - /> - {children || label} - + skin={skin} + checked={checked} + > + {icon && } + onChange({ value, label }, e)} + value={value} + {...rest} + /> + {children || label} + {disabled && } + + ); }; -Radio.displayName = 'RadioGroup.Radio'; +Radio.displayName = 'RadioGroup.Button'; Radio.defaultProps = { checked: false, + children: undefined, disabled: false, error: false, - children: undefined, + icon: undefined, + inline: false, label: undefined, onChange: () => {}, }; Radio.propTypes = { checked: PropTypes.bool, + children: PropTypes.string, disabled: PropTypes.bool, error: PropTypes.bool, - children: PropTypes.string, + icon: PropTypes.string, + inline: PropTypes.bool, label: PropTypes.string, - value: PropTypes.string.isRequired, onChange: PropTypes.func, + value: PropTypes.string.isRequired, }; export default Radio; diff --git a/components/RadioGroup/RadioButton.unit.test.jsx b/components/RadioGroup/RadioButton.unit.test.jsx new file mode 100644 index 000000000..85d2ca532 --- /dev/null +++ b/components/RadioGroup/RadioButton.unit.test.jsx @@ -0,0 +1,42 @@ +import React from 'react'; +import renderer from 'react-test-renderer'; +import RadioButton from './RadioButton'; + +describe('', () => { + describe('snapshot', () => { + it('simple', () => { + const component = ; + expect(renderer.create(component).toJSON()).toMatchSnapshot(); + }); + + it('checked', () => { + const component = ; + expect(renderer.create(component).toJSON()).toMatchSnapshot(); + }); + + it('inline', () => { + const component = ; + expect(renderer.create(component).toJSON()).toMatchSnapshot(); + }); + + it('icon', () => { + const component = ; + expect(renderer.create(component).toJSON()).toMatchSnapshot(); + }); + + it('disabled', () => { + const component = ; + expect(renderer.create(component).toJSON()).toMatchSnapshot(); + }); + + it('error', () => { + const component = ; + expect(renderer.create(component).toJSON()).toMatchSnapshot(); + }); + + it('children', () => { + const component = Foo; + expect(renderer.create(component).toJSON()).toMatchSnapshot(); + }); + }); +}); diff --git a/components/RadioGroup/RadioGroup.jsx b/components/RadioGroup/RadioGroup.jsx index 983c0f58a..8591e19c2 100644 --- a/components/RadioGroup/RadioGroup.jsx +++ b/components/RadioGroup/RadioGroup.jsx @@ -9,8 +9,6 @@ import RadioButton from './RadioButton'; const Group = styled(FieldGroup).attrs({ role: 'radiogroup', })` - display: flex; - flex-direction: column; position: relative; `; @@ -21,9 +19,11 @@ const ErrorLabel = styled(ErrorMessage)` ErrorLabel.displayName = 'ErrorLabel'; const RadioGroup = ({ + type, children, - name, error, + inline, + name, onChange, options, value, @@ -33,6 +33,7 @@ const RadioGroup = ({ name, error: Boolean(error), onChange, + inline, }; const radioOptions = options.map(option => Object.assign({}, option, { @@ -48,7 +49,10 @@ const RadioGroup = ({ checked: child.props.value === value ? true : undefined, ...commonProps, }), - ) || radioOptions.map(props => ); + ) || + radioOptions.map(props => + type === 'button' ? : , + ); return ( @@ -65,14 +69,17 @@ RadioGroup.Button = RadioButton; * Group for Radio components. */ RadioGroup.defaultProps = { - value: undefined, - error: undefined, + type: 'radio', children: undefined, - options: [], + error: undefined, + inline: false, onChange: () => {}, + options: [], + value: undefined, }; RadioGroup.propTypes = { + type: PropTypes.oneOf(['radio', 'button']), options: PropTypes.arrayOf( PropTypes.shape({ label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), @@ -81,9 +88,10 @@ RadioGroup.propTypes = { }), ), children: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.node), - PropTypes.node, + PropTypes.arrayOf(PropTypes.element), + PropTypes.element, ]), + inline: PropTypes.bool, onChange: PropTypes.func, /** Initialize RadioGroup with a value */ value: PropTypes.string, diff --git a/components/RadioGroup/RadioGroup.unit.test.jsx b/components/RadioGroup/RadioGroup.unit.test.jsx index d797ef504..58a308c14 100644 --- a/components/RadioGroup/RadioGroup.unit.test.jsx +++ b/components/RadioGroup/RadioGroup.unit.test.jsx @@ -5,6 +5,78 @@ import diff from 'jest-diff'; import stripAnsi from 'strip-ansi'; import RadioGroup from './RadioGroup'; +const _childrenTest = RadioItem => { + describe(`<${RadioItem.displayName} />`, () => { + it(`should render three <${RadioItem.displayName} />`, () => { + const component = ( + + Foo + Bar + Baz + + ); + const wrapper = shallow(component); + const radios = wrapper.find(RadioItem); + + expect(radios).toHaveLength(3); + }); + + it(`every <${ + RadioItem.displayName + } /> should have the name`, () => { + const component = ( + + Foo + Bar + Baz + + ); + const wrapper = mount(component); + const radios = wrapper.find(RadioItem); + + radios.map(radio => + expect(radio.prop('name')).toBe(wrapper.prop('name')), + ); + }); + + it(`should have <${ + RadioItem.displayName + } /> checked matching value`, () => { + const component = ( + + Foo + Bar + Baz + + ); + const wrapper = shallow(component); + const radios = wrapper.find(RadioItem); + + const radioBar = radios.at(1); + expect(radioBar.prop('checked')).toBe(true); + }); + + it(`should call onChange on every <${RadioItem.displayName} />`, () => { + const onChangeMock = jest.fn(); + + const component = ( + + Foo + Bar + Baz + + ); + + const wrapper = shallow(component); + const radios = wrapper.find(RadioItem); + + radios.map(radio => radio.simulate('change')); + + expect(onChangeMock).toBeCalledTimes(3); + }); + }); +}; + describe('', () => { describe('snapshot', () => { it('simple with options', () => { @@ -18,6 +90,19 @@ describe('', () => { expect(renderer.create(component)).toMatchSnapshot(); }); + it('simple with button options', () => { + const options = [ + { value: 'Foo', label: 'Foo' }, + { value: 'Bar', label: 'Bar' }, + { value: 'Baz', label: 'Baz' }, + ]; + + const component = ( + + ); + expect(renderer.create(component)).toMatchSnapshot(); + }); + it('simple with ', () => { const component = ( @@ -29,6 +114,28 @@ describe('', () => { expect(renderer.create(component)).toMatchSnapshot(); }); + it('simple with ', () => { + const component = ( + + Foo + Bar + Baz + + ); + expect(renderer.create(component)).toMatchSnapshot(); + }); + + it('simple with inline', () => { + const component = ( + + Foo + Bar + Baz + + ); + expect(renderer.create(component)).toMatchSnapshot(); + }); + it('should render the same', () => { const options = [ { value: 'Foo', label: 'Foo' }, @@ -54,71 +161,34 @@ describe('', () => { `Snapshot Diff:\n ${stripAnsi(diff(snapOptions, snapComposable))}`, ).toMatchSnapshot(); }); - }); - - describe('', () => { - it('should render three ', () => { - const component = ( - - Foo - Bar - Baz - - ); - const wrapper = shallow(component); - const radios = wrapper.find(RadioGroup.Radio); - expect(radios).toHaveLength(3); - }); - - it('every should have the name', () => { - const component = ( - - Foo - Bar - Baz - - ); - const wrapper = mount(component); - const radios = wrapper.find(RadioGroup.Radio); - - radios.map(radio => - expect(radio.prop('name')).toBe(wrapper.prop('name')), - ); - }); - - it('should have checked matching value', () => { - const component = ( - - Foo - Bar - Baz - - ); - const wrapper = shallow(component); - const radios = wrapper.find(RadioGroup.Radio); - - const radioBar = radios.at(1); - expect(radioBar.prop('checked')).toBe(true); - }); - - it('should call onChange on every ', () => { - const onChangeMock = jest.fn(); - - const component = ( - - Foo - Bar - Baz - - ); + it('should render the same, with ', () => { + const options = [ + { value: 'Foo', label: 'Foo' }, + { value: 'Bar', label: 'Bar' }, + { value: 'Baz', label: 'Baz' }, + ]; - const wrapper = shallow(component); - const radios = wrapper.find(RadioGroup.Radio); + const snapOptions = renderer + .create() + .toJSON(); - radios.map(radio => radio.simulate('change')); + const snapComposable = renderer + .create( + + Foo + Bar + Baz + , + ) + .toJSON(); - expect(onChangeMock).toBeCalledTimes(3); + expect( + `Snapshot Diff:\n ${stripAnsi(diff(snapOptions, snapComposable))}`, + ).toMatchSnapshot(); }); }); + + _childrenTest(RadioGroup.Radio); + _childrenTest(RadioGroup.Button); }); diff --git a/components/RadioGroup/__snapshots__/Radio.unit.test.jsx.snap b/components/RadioGroup/__snapshots__/Radio.unit.test.jsx.snap index 6552fb355..15d2c76b3 100644 --- a/components/RadioGroup/__snapshots__/Radio.unit.test.jsx.snap +++ b/components/RadioGroup/__snapshots__/Radio.unit.test.jsx.snap @@ -1,6 +1,17 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[` snapshot children 1`] = ` +.c2 { + border: 0; + height: 0; + margin: 0; + opacity: 0; + overflow: hidden; + padding: 0; + position: absolute; + width: 0; +} + .c4 { background-color: #FFFFFF; border: 1.5px solid #999999; @@ -26,17 +37,6 @@ exports[` snapshot children 1`] = ` width: 50%; } -.c2 { - border: 0; - height: 0; - margin: 0; - opacity: 0; - overflow: hidden; - padding: 0; - position: absolute; - width: 0; -} - .c0 { display: block; margin-bottom: 5px; @@ -191,6 +191,7 @@ exports[` snapshot children 1`] = ` disabled={false} onChange={[Function]} type="radio" + value="Foo" /> snapshot children 1`] = ` `; exports[` snapshot disabled 1`] = ` +.c2 { + border: 0; + height: 0; + margin: 0; + opacity: 0; + overflow: hidden; + padding: 0; + position: absolute; + width: 0; +} + .c4 { background-color: #FFFFFF; border: 1.5px solid #999999; @@ -225,17 +237,6 @@ exports[` snapshot disabled 1`] = ` width: 50%; } -.c2 { - border: 0; - height: 0; - margin: 0; - opacity: 0; - overflow: hidden; - padding: 0; - position: absolute; - width: 0; -} - .c5 .c1:checked ~ .c3 { border-color: #1355d0; } @@ -345,6 +346,7 @@ exports[` snapshot disabled 1`] = ` disabled={true} onChange={[Function]} type="radio" + value="Foo" /> snapshot disabled 1`] = ` `; exports[` snapshot error 1`] = ` +.c2 { + border: 0; + height: 0; + margin: 0; + opacity: 0; + overflow: hidden; + padding: 0; + position: absolute; + width: 0; +} + .c4 { background-color: #FFFFFF; border: 1.5px solid #999999; @@ -379,17 +392,6 @@ exports[` snapshot error 1`] = ` width: 50%; } -.c2 { - border: 0; - height: 0; - margin: 0; - opacity: 0; - overflow: hidden; - padding: 0; - position: absolute; - width: 0; -} - .c5 .c1:checked ~ .c3 { border-color: #1355d0; } @@ -544,6 +546,7 @@ exports[` snapshot error 1`] = ` disabled={false} onChange={[Function]} type="radio" + value="Foo" /> snapshot error 1`] = ` `; exports[` snapshot simple 1`] = ` +.c2 { + border: 0; + height: 0; + margin: 0; + opacity: 0; + overflow: hidden; + padding: 0; + position: absolute; + width: 0; +} + .c4 { background-color: #FFFFFF; border: 1.5px solid #999999; @@ -578,17 +592,6 @@ exports[` snapshot simple 1`] = ` width: 50%; } -.c2 { - border: 0; - height: 0; - margin: 0; - opacity: 0; - overflow: hidden; - padding: 0; - position: absolute; - width: 0; -} - .c0 { display: block; margin-bottom: 5px; @@ -634,6 +637,7 @@ exports[` snapshot simple 1`] = ` disabled={false} onChange={[Function]} type="radio" + value="Foo" /> snapshot checked 1`] = ` +.c1 { + display: block; + margin-bottom: 5px; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + cursor: pointer; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + font-size: 16px; + font-weight: bold; + height: 40px; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + padding: 0 16px; + -webkit-letter-spacing: 0.2px; + -moz-letter-spacing: 0.2px; + -ms-letter-spacing: 0.2px; + letter-spacing: 0.2px; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + background-color: #1355d0; + border: 1.5px solid #1355d0; + box-shadow: 0 2px 4px 0 #cccccc; + color: #FFFFFF; + -webkit-text-decoration: none; + text-decoration: none; + border-radius: 4px; + margin-bottom: 16px; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; +} + +.c1 *:nth-child(2) { + margin-left: 5px; +} + +.c1:hover { + box-shadow: 0 2px 4px 0 #cccccc; + background-color: #002f7b; + border-color: #002f7b; + color: #FFFFFF; +} + +.c1:focus { + box-shadow: 0 2px 6px 0 rgba(19,85,208,0.5); + background-color: #1355d0; + border-color: #1355d0; + color: #FFFFFF; +} + +.c1:active { + box-shadow: 0 2px 4px 0 #4c4c4c; + background-color: #002f7b; + border-color: #002f7b; + color: #FFFFFF; +} + +.c2 { + border: 0; + height: 0; + margin: 0; + opacity: 0; + overflow: hidden; + padding: 0; + position: absolute; + width: 0; +} + +.c0 .c3 { + margin-left: 8px; + font-size: 17px; +} + +
+ +
+`; + +exports[` snapshot children 1`] = ` +.c1 { + display: block; + margin-bottom: 5px; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + cursor: pointer; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + font-size: 16px; + font-weight: bold; + height: 40px; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + padding: 0 16px; + -webkit-letter-spacing: 0.2px; + -moz-letter-spacing: 0.2px; + -ms-letter-spacing: 0.2px; + letter-spacing: 0.2px; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + background-color: #FFFFFF; + border: 1.5px solid #1355d0; + box-shadow: 0 2px 4px 0 #cccccc; + color: #1355d0; + -webkit-text-decoration: none; + text-decoration: none; + border-radius: 4px; + margin-bottom: 16px; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; +} + +.c1 *:nth-child(2) { + margin-left: 5px; +} + +.c1:hover { + box-shadow: 0 2px 4px 0 #cccccc; + background-color: #e5edfc; + border-color: #1355d0; + color: #1355d0; +} + +.c1:focus { + box-shadow: 0 2px 4px 0 rgba(19,85,208,0.5); + background-color: #FFFFFF; + border-color: #1355d0; + color: #1355d0; +} + +.c1:active { + box-shadow: 0 2px 4px 0 #4c4c4c; + background-color: #e5edfc; + border-color: #1355d0; + color: #1355d0; +} + +.c2 { + border: 0; + height: 0; + margin: 0; + opacity: 0; + overflow: hidden; + padding: 0; + position: absolute; + width: 0; +} + +.c0 .c3 { + margin-left: 8px; + font-size: 17px; +} + +
+ +
+`; + +exports[` snapshot disabled 1`] = ` +.c1 { + display: block; + margin-bottom: 5px; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + cursor: not-allowed; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + font-size: 16px; + font-weight: bold; + height: 40px; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + padding: 0 16px; + -webkit-letter-spacing: 0.2px; + -moz-letter-spacing: 0.2px; + -ms-letter-spacing: 0.2px; + letter-spacing: 0.2px; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + background-color: rgba(204,204,204,0.4); + border: 1.5px solid #999999; + box-shadow: 0 2px 4px 0 #cccccc; + color: #999999; + -webkit-text-decoration: none; + text-decoration: none; + border-radius: 4px; + margin-bottom: 16px; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; +} + +.c1 *:nth-child(2) { + margin-left: 5px; +} + +.c2 { + border: 0; + height: 0; + margin: 0; + opacity: 0; + overflow: hidden; + padding: 0; + position: absolute; + width: 0; +} + +.c0 .c3 { + margin-left: 8px; + font-size: 17px; +} + +.c4 .c3 { + margin-left: 8px; + font-size: 17px; +} + +
+ +
+`; + +exports[` snapshot error 1`] = ` +.c1 { + display: block; + margin-bottom: 5px; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + cursor: pointer; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + font-size: 16px; + font-weight: bold; + height: 40px; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + padding: 0 16px; + -webkit-letter-spacing: 0.2px; + -moz-letter-spacing: 0.2px; + -ms-letter-spacing: 0.2px; + letter-spacing: 0.2px; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + background-color: #FFFFFF; + border: 1.5px solid #1355d0; + box-shadow: 0 2px 4px 0 #cccccc; + color: #1355d0; + -webkit-text-decoration: none; + text-decoration: none; + border-radius: 4px; + margin-bottom: 16px; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + color: #ff2d4d; + border-color: #ff2d4d; +} + +.c1 *:nth-child(2) { + margin-left: 5px; +} + +.c1:hover { + box-shadow: 0 2px 4px 0 #cccccc; + background-color: #e5edfc; + border-color: #1355d0; + color: #1355d0; +} + +.c1:focus { + box-shadow: 0 2px 4px 0 rgba(19,85,208,0.5); + background-color: #FFFFFF; + border-color: #1355d0; + color: #1355d0; +} + +.c1:active { + box-shadow: 0 2px 4px 0 #4c4c4c; + background-color: #e5edfc; + border-color: #1355d0; + color: #1355d0; +} + +.c1:hover, +.c1:focus { + border-color: #ff2d4d; + box-shadow: 0 2px 6px 0 #ff2d4d; + color: #ff2d4d; + border-color: #ff2d4d; + background-color: #ffe5e9; +} + +.c2 { + border: 0; + height: 0; + margin: 0; + opacity: 0; + overflow: hidden; + padding: 0; + position: absolute; + width: 0; +} + +.c0 .c3 { + margin-left: 8px; + font-size: 17px; +} + +
+ +
+`; + +exports[` snapshot icon 1`] = ` +.c1 { + display: block; + margin-bottom: 5px; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + cursor: pointer; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + font-size: 16px; + font-weight: bold; + height: 40px; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + padding: 0 16px; + -webkit-letter-spacing: 0.2px; + -moz-letter-spacing: 0.2px; + -ms-letter-spacing: 0.2px; + letter-spacing: 0.2px; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + background-color: #FFFFFF; + border: 1.5px solid #1355d0; + box-shadow: 0 2px 4px 0 #cccccc; + color: #1355d0; + -webkit-text-decoration: none; + text-decoration: none; + border-radius: 4px; + margin-bottom: 16px; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; +} + +.c1 *:nth-child(2) { + margin-left: 5px; +} + +.c1:hover { + box-shadow: 0 2px 4px 0 #cccccc; + background-color: #e5edfc; + border-color: #1355d0; + color: #1355d0; +} + +.c1:focus { + box-shadow: 0 2px 4px 0 rgba(19,85,208,0.5); + background-color: #FFFFFF; + border-color: #1355d0; + color: #1355d0; +} + +.c1:active { + box-shadow: 0 2px 4px 0 #4c4c4c; + background-color: #e5edfc; + border-color: #1355d0; + color: #1355d0; +} + +.c3 { + border: 0; + height: 0; + margin: 0; + opacity: 0; + overflow: hidden; + padding: 0; + position: absolute; + width: 0; +} + +.c2 { + margin-right: 8px; +} + +.c0 .c4 { + margin-left: 8px; + font-size: 17px; +} + +
+ +
+`; + +exports[` snapshot inline 1`] = ` +.c1 { + display: block; + margin-bottom: 5px; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + cursor: pointer; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + font-size: 16px; + font-weight: bold; + height: 40px; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + padding: 0 16px; + -webkit-letter-spacing: 0.2px; + -moz-letter-spacing: 0.2px; + -ms-letter-spacing: 0.2px; + letter-spacing: 0.2px; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + background-color: #FFFFFF; + border: 1.5px solid #1355d0; + box-shadow: 0 2px 4px 0 #cccccc; + color: #1355d0; + -webkit-text-decoration: none; + text-decoration: none; + border-radius: 4px; + margin-bottom: 16px; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; +} + +.c1 *:nth-child(2) { + margin-left: 5px; +} + +.c1:hover { + box-shadow: 0 2px 4px 0 #cccccc; + background-color: #e5edfc; + border-color: #1355d0; + color: #1355d0; +} + +.c1:focus { + box-shadow: 0 2px 4px 0 rgba(19,85,208,0.5); + background-color: #FFFFFF; + border-color: #1355d0; + color: #1355d0; +} + +.c1:active { + box-shadow: 0 2px 4px 0 #4c4c4c; + background-color: #e5edfc; + border-color: #1355d0; + color: #1355d0; +} + +.c2 { + border: 0; + height: 0; + margin: 0; + opacity: 0; + overflow: hidden; + padding: 0; + position: absolute; + width: 0; +} + +.c0 { + display: inline-block; + vertical-align: top; + margin-right: 16px; +} + +.c0:last-child { + margin-right: 0; +} + +.c0 .c3 { + margin-left: 8px; + font-size: 17px; +} + +
+ +
+`; + +exports[` snapshot simple 1`] = ` +.c1 { + display: block; + margin-bottom: 5px; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + cursor: pointer; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + font-size: 16px; + font-weight: bold; + height: 40px; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + padding: 0 16px; + -webkit-letter-spacing: 0.2px; + -moz-letter-spacing: 0.2px; + -ms-letter-spacing: 0.2px; + letter-spacing: 0.2px; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + background-color: #FFFFFF; + border: 1.5px solid #1355d0; + box-shadow: 0 2px 4px 0 #cccccc; + color: #1355d0; + -webkit-text-decoration: none; + text-decoration: none; + border-radius: 4px; + margin-bottom: 16px; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; +} + +.c1 *:nth-child(2) { + margin-left: 5px; +} + +.c1:hover { + box-shadow: 0 2px 4px 0 #cccccc; + background-color: #e5edfc; + border-color: #1355d0; + color: #1355d0; +} + +.c1:focus { + box-shadow: 0 2px 4px 0 rgba(19,85,208,0.5); + background-color: #FFFFFF; + border-color: #1355d0; + color: #1355d0; +} + +.c1:active { + box-shadow: 0 2px 4px 0 #4c4c4c; + background-color: #e5edfc; + border-color: #1355d0; + color: #1355d0; +} + +.c2 { + border: 0; + height: 0; + margin: 0; + opacity: 0; + overflow: hidden; + padding: 0; + position: absolute; + width: 0; +} + +.c0 .c3 { + margin-left: 8px; + font-size: 17px; +} + +
+ +
+`; diff --git a/components/RadioGroup/__snapshots__/RadioGroup.unit.test.jsx.snap b/components/RadioGroup/__snapshots__/RadioGroup.unit.test.jsx.snap index 24b5c98e2..2a13f8dd2 100644 --- a/components/RadioGroup/__snapshots__/RadioGroup.unit.test.jsx.snap +++ b/components/RadioGroup/__snapshots__/RadioGroup.unit.test.jsx.snap @@ -5,7 +5,387 @@ exports[` snapshot should render the same 1`] = ` Compared values have no visual difference." `; +exports[` snapshot should render the same, with 1`] = ` +"Snapshot Diff: + Compared values have no visual difference." +`; + +exports[` snapshot simple with 1`] = ` +.c2 { + display: block; + margin-bottom: 5px; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + cursor: pointer; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + font-size: 16px; + font-weight: bold; + height: 40px; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + padding: 0 16px; + -webkit-letter-spacing: 0.2px; + -moz-letter-spacing: 0.2px; + -ms-letter-spacing: 0.2px; + letter-spacing: 0.2px; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + background-color: #FFFFFF; + border: 1.5px solid #1355d0; + box-shadow: 0 2px 4px 0 #cccccc; + color: #1355d0; + -webkit-text-decoration: none; + text-decoration: none; + border-radius: 4px; + margin-bottom: 16px; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; +} + +.c2 *:nth-child(2) { + margin-left: 5px; +} + +.c2:hover { + box-shadow: 0 2px 4px 0 #cccccc; + background-color: #e5edfc; + border-color: #1355d0; + color: #1355d0; +} + +.c2:focus { + box-shadow: 0 2px 4px 0 rgba(19,85,208,0.5); + background-color: #FFFFFF; + border-color: #1355d0; + color: #1355d0; +} + +.c2:active { + box-shadow: 0 2px 4px 0 #4c4c4c; + background-color: #e5edfc; + border-color: #1355d0; + color: #1355d0; +} + +.c4 { + border: 0; + height: 0; + margin: 0; + opacity: 0; + overflow: hidden; + padding: 0; + position: absolute; + width: 0; +} + +.c5 .c3:checked ~ .c6 { + border-color: #1355d0; +} + +.c5 .c3:checked ~ .c6:after { + background-color: #1355d0; + display: block; +} + +.c5 .c3:focus ~ .c6 { + border-color: #1355d0; + box-shadow: 0 2px 6px 0 rgba(19,85,208,0.5); +} + +.c5 .c3:checked:disabled ~ .c6 { + background-color: #999999; + border-color: #999999; + box-shadow: inset 0 0 0 3.5px #FFFFFF; +} + +.c1 .c7 { + margin-left: 8px; + font-size: 17px; +} + +.c0 { + position: relative; + margin-bottom: 20px; + min-width: 250px; + width: 100%; + position: relative; +} + +
+
+ +
+
+ +
+
+ +
+
+`; + +exports[` snapshot simple with inline 1`] = ` +.c2 { + display: block; + margin-bottom: 5px; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + cursor: pointer; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + font-size: 16px; + font-weight: bold; + height: 40px; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + padding: 0 16px; + -webkit-letter-spacing: 0.2px; + -moz-letter-spacing: 0.2px; + -ms-letter-spacing: 0.2px; + letter-spacing: 0.2px; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + background-color: #FFFFFF; + border: 1.5px solid #1355d0; + box-shadow: 0 2px 4px 0 #cccccc; + color: #1355d0; + -webkit-text-decoration: none; + text-decoration: none; + border-radius: 4px; + margin-bottom: 16px; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; +} + +.c2 *:nth-child(2) { + margin-left: 5px; +} + +.c2:hover { + box-shadow: 0 2px 4px 0 #cccccc; + background-color: #e5edfc; + border-color: #1355d0; + color: #1355d0; +} + +.c2:focus { + box-shadow: 0 2px 4px 0 rgba(19,85,208,0.5); + background-color: #FFFFFF; + border-color: #1355d0; + color: #1355d0; +} + +.c2:active { + box-shadow: 0 2px 4px 0 #4c4c4c; + background-color: #e5edfc; + border-color: #1355d0; + color: #1355d0; +} + +.c4 { + border: 0; + height: 0; + margin: 0; + opacity: 0; + overflow: hidden; + padding: 0; + position: absolute; + width: 0; +} + +.c5 .c3:checked ~ .c6 { + border-color: #1355d0; +} + +.c5 .c3:checked ~ .c6:after { + background-color: #1355d0; + display: block; +} + +.c5 .c3:focus ~ .c6 { + border-color: #1355d0; + box-shadow: 0 2px 6px 0 rgba(19,85,208,0.5); +} + +.c5 .c3:checked:disabled ~ .c6 { + background-color: #999999; + border-color: #999999; + box-shadow: inset 0 0 0 3.5px #FFFFFF; +} + +.c1 { + display: inline-block; + vertical-align: top; + margin-right: 16px; +} + +.c1:last-child { + margin-right: 0; +} + +.c1 .c7 { + margin-left: 8px; + font-size: 17px; +} + +.c0 { + position: relative; + margin-bottom: 20px; + min-width: 250px; + width: 100%; + position: relative; +} + +
+
+ +
+
+ +
+
+ +
+
+`; + exports[` snapshot simple with 1`] = ` +.c3 { + border: 0; + height: 0; + margin: 0; + opacity: 0; + overflow: hidden; + padding: 0; + position: absolute; + width: 0; +} + .c5 { background-color: #FFFFFF; border: 1.5px solid #999999; @@ -31,17 +411,6 @@ exports[` snapshot simple with 1`] = ` width: 50%; } -.c3 { - border: 0; - height: 0; - margin: 0; - opacity: 0; - overflow: hidden; - padding: 0; - position: absolute; - width: 0; -} - .c1 { display: block; margin-bottom: 5px; @@ -83,13 +452,6 @@ exports[` snapshot simple with 1`] = ` margin-bottom: 20px; min-width: 250px; width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; position: relative; } @@ -107,6 +469,7 @@ exports[` snapshot simple with 1`] = ` name="groceries" onChange={[Function]} type="radio" + value="Foo" /> snapshot simple with 1`] = ` name="groceries" onChange={[Function]} type="radio" + value="Bar" /> snapshot simple with 1`] = ` name="groceries" onChange={[Function]} type="radio" + value="Baz" /> snapshot simple with 1`] = `
`; +exports[` snapshot simple with button options 1`] = ` +.c2 { + display: block; + margin-bottom: 5px; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + cursor: pointer; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + font-size: 16px; + font-weight: bold; + height: 40px; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + padding: 0 16px; + -webkit-letter-spacing: 0.2px; + -moz-letter-spacing: 0.2px; + -ms-letter-spacing: 0.2px; + letter-spacing: 0.2px; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + background-color: #FFFFFF; + border: 1.5px solid #1355d0; + box-shadow: 0 2px 4px 0 #cccccc; + color: #1355d0; + -webkit-text-decoration: none; + text-decoration: none; + border-radius: 4px; + margin-bottom: 16px; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; +} + +.c2 *:nth-child(2) { + margin-left: 5px; +} + +.c2:hover { + box-shadow: 0 2px 4px 0 #cccccc; + background-color: #e5edfc; + border-color: #1355d0; + color: #1355d0; +} + +.c2:focus { + box-shadow: 0 2px 4px 0 rgba(19,85,208,0.5); + background-color: #FFFFFF; + border-color: #1355d0; + color: #1355d0; +} + +.c2:active { + box-shadow: 0 2px 4px 0 #4c4c4c; + background-color: #e5edfc; + border-color: #1355d0; + color: #1355d0; +} + +.c4 { + border: 0; + height: 0; + margin: 0; + opacity: 0; + overflow: hidden; + padding: 0; + position: absolute; + width: 0; +} + +.c5 .c3:checked ~ .c6 { + border-color: #1355d0; +} + +.c5 .c3:checked ~ .c6:after { + background-color: #1355d0; + display: block; +} + +.c5 .c3:focus ~ .c6 { + border-color: #1355d0; + box-shadow: 0 2px 6px 0 rgba(19,85,208,0.5); +} + +.c5 .c3:checked:disabled ~ .c6 { + background-color: #999999; + border-color: #999999; + box-shadow: inset 0 0 0 3.5px #FFFFFF; +} + +.c1 .c7 { + margin-left: 8px; + font-size: 17px; +} + +.c0 { + position: relative; + margin-bottom: 20px; + min-width: 250px; + width: 100%; + position: relative; +} + +
+
+ +
+
+ +
+
+ +
+
+`; + exports[` snapshot simple with options 1`] = ` +.c3 { + border: 0; + height: 0; + margin: 0; + opacity: 0; + overflow: hidden; + padding: 0; + position: absolute; + width: 0; +} + .c5 { background-color: #FFFFFF; border: 1.5px solid #999999; @@ -174,17 +727,6 @@ exports[` snapshot simple with options 1`] = ` width: 50%; } -.c3 { - border: 0; - height: 0; - margin: 0; - opacity: 0; - overflow: hidden; - padding: 0; - position: absolute; - width: 0; -} - .c1 { display: block; margin-bottom: 5px; @@ -226,13 +768,6 @@ exports[` snapshot simple with options 1`] = ` margin-bottom: 20px; min-width: 250px; width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; position: relative; } @@ -250,6 +785,7 @@ exports[` snapshot simple with options 1`] = ` name="foo" onChange={[Function]} type="radio" + value="Foo" /> snapshot simple with options 1`] = ` name="foo" onChange={[Function]} type="radio" + value="Bar" /> snapshot simple with options 1`] = ` name="foo" onChange={[Function]} type="radio" + value="Baz" /> error && diff --git a/stories/RadioGroup/sub-components/buttonGroup.jsx b/stories/RadioGroup/sub-components/buttonGroup.jsx index d7e45b962..4347bc55a 100644 --- a/stories/RadioGroup/sub-components/buttonGroup.jsx +++ b/stories/RadioGroup/sub-components/buttonGroup.jsx @@ -14,12 +14,15 @@ class Group extends React.Component { return ( this.setState({ value: opValue })} > - Tomato sauce - Mustard + + Tomato sauce + + + Mustard + Barbecue sauce Barbecue sauce Barbecue sauce From 5f7d376fb95869c40bb2f4e7ce543df275819c90 Mon Sep 17 00:00:00 2001 From: Daniel Silva Date: Tue, 2 Apr 2019 16:41:54 -0300 Subject: [PATCH 07/14] docs(Radio Button Group): Docs --- stories/RadioGroup/RadioGroup.story.jsx | 20 ++++++++++++++----- .../RadioGroup/sub-components/buttonGroup.jsx | 20 ++++++++++++++++++- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/stories/RadioGroup/RadioGroup.story.jsx b/stories/RadioGroup/RadioGroup.story.jsx index 438c8d1c3..0674887a4 100644 --- a/stories/RadioGroup/RadioGroup.story.jsx +++ b/stories/RadioGroup/RadioGroup.story.jsx @@ -62,11 +62,6 @@ stories.add('Radio group', () => (


- - - -
- @@ -95,9 +90,24 @@ stories.add('Radio group', () => ( + + + Button Group Skin +

+ It's possible to render radio elements as buttons, using{' '} + {''} +

+ +
+ + + +
+
+ diff --git a/stories/RadioGroup/sub-components/buttonGroup.jsx b/stories/RadioGroup/sub-components/buttonGroup.jsx index 4347bc55a..a0a0b5995 100644 --- a/stories/RadioGroup/sub-components/buttonGroup.jsx +++ b/stories/RadioGroup/sub-components/buttonGroup.jsx @@ -32,7 +32,25 @@ class Group extends React.Component { } const buttonGroup = { - code: `;`, + code: ` + +/* or */ + + + + Tomato sauce + + + Mustard + + + Barbecue sauce Barbecue sauce Barbecue sauce + +`, component: , }; From 9fb2bb1adc47dd18ff699712d23ed3150f093ecc Mon Sep 17 00:00:00 2001 From: Daniel Silva Date: Wed, 3 Apr 2019 12:05:37 -0300 Subject: [PATCH 08/14] docs(Radio Button Group): Docs --- stories/RadioGroup/RadioGroup.story.jsx | 15 ++++++- .../RadioGroup/sub-components/buttonGroup.jsx | 32 ++++++------- .../sub-components/buttonGroupInline.jsx | 45 +++++++++++++++++++ stories/RadioGroup/sub-components/index.jsx | 9 +++- 4 files changed, 82 insertions(+), 19 deletions(-) create mode 100644 stories/RadioGroup/sub-components/buttonGroupInline.jsx diff --git a/stories/RadioGroup/RadioGroup.story.jsx b/stories/RadioGroup/RadioGroup.story.jsx index 0674887a4..137649a0e 100644 --- a/stories/RadioGroup/RadioGroup.story.jsx +++ b/stories/RadioGroup/RadioGroup.story.jsx @@ -94,14 +94,25 @@ stories.add('Radio group', () => ( Button Group Skin

- It's possible to render radio elements as buttons, using{' '} - {''} + It's possible to render radio elements as buttons, using{' '} + {''} component or{' '} + type="button" prop.


+ +

+ It's also possible to render it inline, inline{' '} + prop. +

+ +
+ + +
diff --git a/stories/RadioGroup/sub-components/buttonGroup.jsx b/stories/RadioGroup/sub-components/buttonGroup.jsx index a0a0b5995..daaba99d8 100644 --- a/stories/RadioGroup/sub-components/buttonGroup.jsx +++ b/stories/RadioGroup/sub-components/buttonGroup.jsx @@ -1,6 +1,12 @@ import React from 'react'; import RadioGroup from '../../../components/RadioGroup'; +const options = [ + { value: 'tomato-sauce', label: 'Tomato sauce', icon: 'print' }, + { value: 'mustard', label: 'Mustard', disabled: true }, + { value: 'barbecue-sauce', label: 'Barbecue sauce' }, +]; + class Group extends React.Component { constructor(props) { super(props); @@ -16,23 +22,17 @@ class Group extends React.Component { name="groceries" value={value} onChange={({ value: opValue }) => this.setState({ value: opValue })} - > - - Tomato sauce - - - Mustard - - - Barbecue sauce Barbecue sauce Barbecue sauce - -
+ options={options} + type="button" + /> ); } } const buttonGroup = { - code: ` - + Tomato sauce - + Mustard - - Barbecue sauce Barbecue sauce Barbecue sauce + + Barbecue sauce `, component: , diff --git a/stories/RadioGroup/sub-components/buttonGroupInline.jsx b/stories/RadioGroup/sub-components/buttonGroupInline.jsx new file mode 100644 index 000000000..4c3b85fe2 --- /dev/null +++ b/stories/RadioGroup/sub-components/buttonGroupInline.jsx @@ -0,0 +1,45 @@ +import React from 'react'; +import RadioGroup from '../../../components/RadioGroup'; + +const options = [ + { value: 'tomato-sauce', label: 'Tomato sauce', icon: 'print' }, + { value: 'mustard', label: 'Mustard', disabled: true }, + { value: 'barbecue-sauce', label: 'Barbecue sauce' }, +]; + +class Group extends React.Component { + constructor(props) { + super(props); + + this.state = { value: undefined }; + } + + render() { + const { value } = this.state; + + return ( + this.setState({ value: opValue })} + options={options} + type="button" + inline + /> + ); + } +} + +const buttonGroup = { + code: ` +... +`, + component: , +}; + +export default buttonGroup; diff --git a/stories/RadioGroup/sub-components/index.jsx b/stories/RadioGroup/sub-components/index.jsx index 0d2b2885e..78d24baa1 100644 --- a/stories/RadioGroup/sub-components/index.jsx +++ b/stories/RadioGroup/sub-components/index.jsx @@ -2,5 +2,12 @@ import simpleRadioGroup from './simpleRadioGroup'; import propsRadioGroup from './propsRadioGroup'; import disabledRadio from './disabledRadio'; import buttonGroup from './buttonGroup'; +import buttonGroupInline from './buttonGroupInline'; -export { simpleRadioGroup, propsRadioGroup, disabledRadio, buttonGroup }; +export { + simpleRadioGroup, + propsRadioGroup, + disabledRadio, + buttonGroup, + buttonGroupInline, +}; From 64b6dbdf8f3ab7a2f295b1d78f2d83d8ea1865d6 Mon Sep 17 00:00:00 2001 From: Daniel Silva Date: Wed, 3 Apr 2019 12:40:50 -0300 Subject: [PATCH 09/14] docs(Radio Button Group): Doc examples --- .../RadioGroup/RadioButton.unit.test.jsx | 5 + .../RadioButton.unit.test.jsx.snap | 98 +++++++++++++++++++ components/shared/ButtonGroupLabel.jsx | 3 +- stories/RadioGroup/RadioGroup.story.jsx | 21 +++- .../RadioGroup/sub-components/buttonGroup.jsx | 19 ++-- .../sub-components/buttonGroupDisabled.jsx | 37 +++++++ .../sub-components/buttonGroupError.jsx | 44 +++++++++ .../sub-components/buttonGroupInline.jsx | 7 +- stories/RadioGroup/sub-components/index.jsx | 4 + 9 files changed, 221 insertions(+), 17 deletions(-) create mode 100644 stories/RadioGroup/sub-components/buttonGroupDisabled.jsx create mode 100644 stories/RadioGroup/sub-components/buttonGroupError.jsx diff --git a/components/RadioGroup/RadioButton.unit.test.jsx b/components/RadioGroup/RadioButton.unit.test.jsx index 85d2ca532..2bc479bbd 100644 --- a/components/RadioGroup/RadioButton.unit.test.jsx +++ b/components/RadioGroup/RadioButton.unit.test.jsx @@ -34,6 +34,11 @@ describe('', () => { expect(renderer.create(component).toJSON()).toMatchSnapshot(); }); + it('disabled with an error', () => { + const component = ; + expect(renderer.create(component).toJSON()).toMatchSnapshot(); + }); + it('children', () => { const component = Foo; expect(renderer.create(component).toJSON()).toMatchSnapshot(); diff --git a/components/RadioGroup/__snapshots__/RadioButton.unit.test.jsx.snap b/components/RadioGroup/__snapshots__/RadioButton.unit.test.jsx.snap index 5c35dfa9c..2ed87cce8 100644 --- a/components/RadioGroup/__snapshots__/RadioButton.unit.test.jsx.snap +++ b/components/RadioGroup/__snapshots__/RadioButton.unit.test.jsx.snap @@ -304,6 +304,104 @@ exports[` snapshot disabled 1`] = ` `; +exports[` snapshot disabled with an error 1`] = ` +.c1 { + display: block; + margin-bottom: 5px; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + cursor: not-allowed; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + font-size: 16px; + font-weight: bold; + height: 40px; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + padding: 0 16px; + -webkit-letter-spacing: 0.2px; + -moz-letter-spacing: 0.2px; + -ms-letter-spacing: 0.2px; + letter-spacing: 0.2px; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + background-color: rgba(204,204,204,0.4); + border: 1.5px solid #999999; + box-shadow: 0 2px 4px 0 #cccccc; + color: #999999; + -webkit-text-decoration: none; + text-decoration: none; + border-radius: 4px; + margin-bottom: 16px; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; +} + +.c1 *:nth-child(2) { + margin-left: 5px; +} + +.c2 { + border: 0; + height: 0; + margin: 0; + opacity: 0; + overflow: hidden; + padding: 0; + position: absolute; + width: 0; +} + +.c0 .c3 { + margin-left: 8px; + font-size: 17px; +} + +.c4 .c3 { + margin-left: 8px; + font-size: 17px; +} + +
+ +
+`; + exports[` snapshot error 1`] = ` .c1 { display: block; diff --git a/components/shared/ButtonGroupLabel.jsx b/components/shared/ButtonGroupLabel.jsx index c8f67f48d..37b5e73c1 100644 --- a/components/shared/ButtonGroupLabel.jsx +++ b/components/shared/ButtonGroupLabel.jsx @@ -10,7 +10,8 @@ export default styled(Label)` margin-bottom: 16px; display: inline-flex; - ${({ error, checked }) => + ${({ disabled, error, checked }) => + !disabled && error && css` color: ${Colors.ERROR['500']}; diff --git a/stories/RadioGroup/RadioGroup.story.jsx b/stories/RadioGroup/RadioGroup.story.jsx index 137649a0e..483a4c901 100644 --- a/stories/RadioGroup/RadioGroup.story.jsx +++ b/stories/RadioGroup/RadioGroup.story.jsx @@ -98,21 +98,38 @@ stories.add('Radio group', () => ( {''} component or{' '} type="button" prop.

-
+ +

It's also possible to render it inline, inline{' '} prop.

-
+ +
+ +

With an error message.

+
+ + + + +
+ +

Disabled options.

+
+ + + + diff --git a/stories/RadioGroup/sub-components/buttonGroup.jsx b/stories/RadioGroup/sub-components/buttonGroup.jsx index daaba99d8..7b61e6e27 100644 --- a/stories/RadioGroup/sub-components/buttonGroup.jsx +++ b/stories/RadioGroup/sub-components/buttonGroup.jsx @@ -2,9 +2,8 @@ import React from 'react'; import RadioGroup from '../../../components/RadioGroup'; const options = [ - { value: 'tomato-sauce', label: 'Tomato sauce', icon: 'print' }, - { value: 'mustard', label: 'Mustard', disabled: true }, - { value: 'barbecue-sauce', label: 'Barbecue sauce' }, + { value: 'with-icon', label: 'With an Icon', icon: 'thumb_up' }, + { value: 'default', label: 'Default' }, ]; class Group extends React.Component { @@ -19,7 +18,7 @@ class Group extends React.Component { return ( this.setState({ value: opValue })} options={options} @@ -41,14 +40,14 @@ const buttonGroup = { /* or */ - - Tomato sauce + + With an Icon - - Mustard + + Disabled - - Barbecue sauce + + Default `, component: , diff --git a/stories/RadioGroup/sub-components/buttonGroupDisabled.jsx b/stories/RadioGroup/sub-components/buttonGroupDisabled.jsx new file mode 100644 index 000000000..a3922b9ca --- /dev/null +++ b/stories/RadioGroup/sub-components/buttonGroupDisabled.jsx @@ -0,0 +1,37 @@ +import React from 'react'; +import RadioGroup from '../../../components/RadioGroup'; + +const options = [ + { + value: 'with-icon', + label: 'With an Icon', + icon: 'thumb_up', + disabled: true, + }, + { value: 'default-option', label: 'Default', disabled: true }, + { value: 'checked-option', label: 'Checked', disabled: true }, +]; + +const buttonGroup = { + code: `const options = ${JSON.stringify(options, null, 2)}; + + +... +`, + component: ( + this.setState({ value: opValue })} + options={options} + type="button" + /> + ), +}; + +export default buttonGroup; diff --git a/stories/RadioGroup/sub-components/buttonGroupError.jsx b/stories/RadioGroup/sub-components/buttonGroupError.jsx new file mode 100644 index 000000000..2df944dbc --- /dev/null +++ b/stories/RadioGroup/sub-components/buttonGroupError.jsx @@ -0,0 +1,44 @@ +import React from 'react'; +import RadioGroup from '../../../components/RadioGroup'; + +const options = [ + { value: 'with-icon', label: 'With an Icon', icon: 'thumb_up' }, + { value: 'default', label: 'Default' }, +]; + +class Group extends React.Component { + constructor(props) { + super(props); + + this.state = { value: undefined }; + } + + render() { + const { value } = this.state; + + return ( + this.setState({ value: opValue })} + options={options} + type="button" + error="Some message error" + /> + ); + } +} + +const buttonGroup = { + code: ` +... +`, + component: , +}; + +export default buttonGroup; diff --git a/stories/RadioGroup/sub-components/buttonGroupInline.jsx b/stories/RadioGroup/sub-components/buttonGroupInline.jsx index 4c3b85fe2..c257fbddb 100644 --- a/stories/RadioGroup/sub-components/buttonGroupInline.jsx +++ b/stories/RadioGroup/sub-components/buttonGroupInline.jsx @@ -2,9 +2,8 @@ import React from 'react'; import RadioGroup from '../../../components/RadioGroup'; const options = [ - { value: 'tomato-sauce', label: 'Tomato sauce', icon: 'print' }, - { value: 'mustard', label: 'Mustard', disabled: true }, - { value: 'barbecue-sauce', label: 'Barbecue sauce' }, + { value: 'with-icon', label: 'With an Icon', icon: 'thumb_up' }, + { value: 'default', label: 'Default' }, ]; class Group extends React.Component { @@ -19,7 +18,7 @@ class Group extends React.Component { return ( this.setState({ value: opValue })} options={options} diff --git a/stories/RadioGroup/sub-components/index.jsx b/stories/RadioGroup/sub-components/index.jsx index 78d24baa1..7a01cf491 100644 --- a/stories/RadioGroup/sub-components/index.jsx +++ b/stories/RadioGroup/sub-components/index.jsx @@ -3,6 +3,8 @@ import propsRadioGroup from './propsRadioGroup'; import disabledRadio from './disabledRadio'; import buttonGroup from './buttonGroup'; import buttonGroupInline from './buttonGroupInline'; +import buttonGroupError from './buttonGroupError'; +import buttonGroupDisabled from './buttonGroupDisabled'; export { simpleRadioGroup, @@ -10,4 +12,6 @@ export { disabledRadio, buttonGroup, buttonGroupInline, + buttonGroupError, + buttonGroupDisabled, }; From 9a80c6357cecaeb666dcb7c1fe78925f73e72634 Mon Sep 17 00:00:00 2001 From: Daniel Silva Date: Wed, 3 Apr 2019 16:39:23 -0300 Subject: [PATCH 10/14] fix(Radio Button Group): Focus style --- components/Button/buttonStyle.js | 103 +-- .../__snapshots__/Modal.unit.test.jsx.snap | 7 + components/RadioGroup/HiddenRadio.jsx | 14 - components/RadioGroup/Radio.jsx | 2 +- components/RadioGroup/RadioButton.jsx | 29 +- .../__snapshots__/Radio.unit.test.jsx.snap | 63 ++ .../RadioButton.unit.test.jsx.snap | 664 ++++++++++++------ .../RadioGroup.unit.test.jsx.snap | 510 ++++++++++---- components/shared/ButtonGroupLabel.jsx | 29 +- components/shared/HiddenRadio.jsx | 38 + .../sub-components/buttonGroupError.jsx | 4 +- 11 files changed, 1026 insertions(+), 437 deletions(-) delete mode 100644 components/RadioGroup/HiddenRadio.jsx create mode 100644 components/shared/HiddenRadio.jsx diff --git a/components/Button/buttonStyle.js b/components/Button/buttonStyle.js index e093292dd..95e08c247 100644 --- a/components/Button/buttonStyle.js +++ b/components/Button/buttonStyle.js @@ -36,21 +36,33 @@ const height = ({ size }) => { return `height: ${heights[size] || heights.medium};`; }; -const skin = props => { +const _interactiveStyle = (props, skinProp) => { const { - unselected, - selected, - disabled, - focused, - hovered, - decoration, - borderRadius, + [skinProp]: { shadow, background, border, color }, } = skins(props); + const { disabled } = props; + + return !disabled + ? ` + box-shadow: ${shadow}; + background-color: ${background}; + border-color: ${border}; + color: ${color}; + ` + : ''; +}; + +const hover = props => _interactiveStyle(props, 'hovered'); +const focus = props => _interactiveStyle(props, 'focused'); +const active = props => _interactiveStyle(props, 'selected'); - return `${` - background-color: ${ - props.disabled ? disabled.background : unselected.background - }; +const skin = props => { + const { unselected, disabled, decoration, borderRadius } = skins(props); + + return css` + background-color: ${props.disabled + ? disabled.background + : unselected.background}; border: 1.5px solid ${props.disabled ? disabled.border : unselected.border}; box-shadow: ${props.disabled ? disabled.shadow : unselected.shadow}; @@ -59,38 +71,10 @@ const skin = props => { ${decoration ? `text-decoration: ${decoration};` : ''} ${borderRadius ? `border-radius: ${borderRadius};` : ''} - `} - - ${ - !props.disabled - ? ` - &:hover { - box-shadow: ${hovered.shadow}; - background-color: ${hovered.background}; - border-color: ${hovered.border}; - color: ${hovered.color}; - } - - &:focus { - box-shadow: ${focused.shadow}; - background-color: ${focused.background}; - border-color: ${focused.border}; - color: ${focused.color}; - } - - &:active { - box-shadow: ${selected.shadow}; - background-color: ${selected.background}; - border-color: ${selected.border}; - color: ${selected.color}; - } - ` - : '' - } `; }; -export default css` +const DEFAULT_STYLE = css` align-items: center; ${props => `cursor: ${props.disabled ? 'not-allowed' : 'pointer'};`} display: flex; @@ -115,6 +99,43 @@ export default css` transition: all 0.2s ease-in-out; ${props => props.full && `width: 100%;`} +`; +const SKIN_STYLE = css` ${skin} `; +const HOVER_STYLE = css` + ${hover} +`; +const FOCUS_STYLE = css` + ${focus} +`; +const ACTIVE_STYLE = css` + ${active} +`; + +const BUTTON_STYLE = css` + ${DEFAULT_STYLE} + ${SKIN_STYLE} + + :hover { + ${HOVER_STYLE} + } + + :focus { + ${FOCUS_STYLE} + } + + :active { + ${ACTIVE_STYLE} + } +`; + +export { + DEFAULT_STYLE, + SKIN_STYLE, + HOVER_STYLE, + FOCUS_STYLE, + ACTIVE_STYLE, + BUTTON_STYLE as default, +}; diff --git a/components/Modal/__snapshots__/Modal.unit.test.jsx.snap b/components/Modal/__snapshots__/Modal.unit.test.jsx.snap index 030fed95a..fde1e7389 100644 --- a/components/Modal/__snapshots__/Modal.unit.test.jsx.snap +++ b/components/Modal/__snapshots__/Modal.unit.test.jsx.snap @@ -1006,6 +1006,13 @@ exports[` Snapshots should match the snapshot 1`] = ` [Function], " ", [Function], + ":hover{", + [Function], + "}:focus{", + [Function], + "}:active{", + [Function], + "}", " ", ".c12", "{", diff --git a/components/RadioGroup/HiddenRadio.jsx b/components/RadioGroup/HiddenRadio.jsx deleted file mode 100644 index bdd818f31..000000000 --- a/components/RadioGroup/HiddenRadio.jsx +++ /dev/null @@ -1,14 +0,0 @@ -import styled from 'styled-components'; - -export default styled.input.attrs({ - type: 'radio', -})` - border: 0; - height: 0; - margin: 0; - opacity: 0; - overflow: hidden; - padding: 0; - position: absolute; - width: 0; -`; diff --git a/components/RadioGroup/Radio.jsx b/components/RadioGroup/Radio.jsx index 78bb75587..ea199564d 100644 --- a/components/RadioGroup/Radio.jsx +++ b/components/RadioGroup/Radio.jsx @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import styled from 'styled-components'; import Colors from '../Colors'; import Label from '../shared/Label'; -import HiddenRadio from './HiddenRadio'; +import HiddenRadio from '../shared/HiddenRadio'; const RadioMark = styled.span` background-color: ${Colors.WHITE}; diff --git a/components/RadioGroup/RadioButton.jsx b/components/RadioGroup/RadioButton.jsx index cd8545a28..78adbb25f 100644 --- a/components/RadioGroup/RadioButton.jsx +++ b/components/RadioGroup/RadioButton.jsx @@ -2,8 +2,9 @@ import React from 'react'; import PropTypes from 'prop-types'; import styled from 'styled-components'; import ButtonGroupLabel from '../shared/ButtonGroupLabel'; -import HiddenRadio from './HiddenRadio'; +import HiddenRadio from '../shared/HiddenRadio'; import Icon from '../Icon'; +import uniqId from '../shared/uniqId'; const LockIcon = styled(Icon).attrs({ name: 'lock', @@ -41,27 +42,33 @@ const Radio = ({ value, checked, icon, + id, inline, ...rest }) => { const skin = checked ? 'primary' : 'secondary'; + const _id = id || uniqId('radio-button-'); return ( - onChange({ value, label }, e)} + value={value} skin={skin} + error={error} + {...rest} + /> + {icon && } - onChange({ value, label }, e)} - value={value} - {...rest} - /> {children || label} {disabled && } @@ -77,6 +84,7 @@ Radio.defaultProps = { disabled: false, error: false, icon: undefined, + id: undefined, inline: false, label: undefined, onChange: () => {}, @@ -88,6 +96,7 @@ Radio.propTypes = { disabled: PropTypes.bool, error: PropTypes.bool, icon: PropTypes.string, + id: PropTypes.string, inline: PropTypes.bool, label: PropTypes.string, onChange: PropTypes.func, diff --git a/components/RadioGroup/__snapshots__/Radio.unit.test.jsx.snap b/components/RadioGroup/__snapshots__/Radio.unit.test.jsx.snap index 15d2c76b3..1ac38474b 100644 --- a/components/RadioGroup/__snapshots__/Radio.unit.test.jsx.snap +++ b/components/RadioGroup/__snapshots__/Radio.unit.test.jsx.snap @@ -12,6 +12,27 @@ exports[` snapshot children 1`] = ` width: 0; } +.c2:focus ~ .c7 { + box-shadow: 0 2px 6px 0 rgba(19,85,208,0.5); + background-color: #1355d0; + border-color: #1355d0; + color: #FFFFFF; +} + +.c2:hover ~ .c7 { + box-shadow: 0 2px 4px 0 #cccccc; + background-color: #002f7b; + border-color: #002f7b; + color: #FFFFFF; +} + +.c2:active ~ .c7 { + box-shadow: 0 2px 4px 0 #4c4c4c; + background-color: #002f7b; + border-color: #002f7b; + color: #FFFFFF; +} + .c4 { background-color: #FFFFFF; border: 1.5px solid #999999; @@ -367,6 +388,27 @@ exports[` snapshot error 1`] = ` width: 0; } +.c2:focus ~ .c7 { + box-shadow: 0 2px 6px 0 rgba(19,85,208,0.5); + background-color: #1355d0; + border-color: #1355d0; + color: #FFFFFF; +} + +.c2:hover ~ .c7 { + box-shadow: 0 2px 4px 0 #cccccc; + background-color: #002f7b; + border-color: #002f7b; + color: #FFFFFF; +} + +.c2:active ~ .c7 { + box-shadow: 0 2px 4px 0 #4c4c4c; + background-color: #002f7b; + border-color: #002f7b; + color: #FFFFFF; +} + .c4 { background-color: #FFFFFF; border: 1.5px solid #999999; @@ -567,6 +609,27 @@ exports[` snapshot simple 1`] = ` width: 0; } +.c2:focus ~ .c5 { + box-shadow: 0 2px 6px 0 rgba(19,85,208,0.5); + background-color: #1355d0; + border-color: #1355d0; + color: #FFFFFF; +} + +.c2:hover ~ .c5 { + box-shadow: 0 2px 4px 0 #cccccc; + background-color: #002f7b; + border-color: #002f7b; + color: #FFFFFF; +} + +.c2:active ~ .c5 { + box-shadow: 0 2px 4px 0 #4c4c4c; + background-color: #002f7b; + border-color: #002f7b; + color: #FFFFFF; +} + .c4 { background-color: #FFFFFF; border: 1.5px solid #999999; diff --git a/components/RadioGroup/__snapshots__/RadioButton.unit.test.jsx.snap b/components/RadioGroup/__snapshots__/RadioButton.unit.test.jsx.snap index 2ed87cce8..18ddc913e 100644 --- a/components/RadioGroup/__snapshots__/RadioButton.unit.test.jsx.snap +++ b/components/RadioGroup/__snapshots__/RadioButton.unit.test.jsx.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[` snapshot checked 1`] = ` -.c1 { +.c3 { display: block; margin-bottom: 5px; -webkit-align-items: center; @@ -41,32 +41,32 @@ exports[` snapshot checked 1`] = ` display: inline-flex; } -.c1 *:nth-child(2) { +.c3 *:nth-child(2) { margin-left: 5px; } -.c1:hover { - box-shadow: 0 2px 4px 0 #cccccc; - background-color: #002f7b; - border-color: #002f7b; - color: #FFFFFF; +.c4:focus ~ .c2 { + box-shadow: 0 2px 4px 0 rgba(19,85,208,0.5); + background-color: #FFFFFF; + border-color: #1355d0; + color: #1355d0; } -.c1:focus { - box-shadow: 0 2px 6px 0 rgba(19,85,208,0.5); - background-color: #1355d0; +.c4:hover ~ .c2 { + box-shadow: 0 2px 4px 0 #cccccc; + background-color: #e5edfc; border-color: #1355d0; - color: #FFFFFF; + color: #1355d0; } -.c1:active { +.c4:active ~ .c2 { box-shadow: 0 2px 4px 0 #4c4c4c; - background-color: #002f7b; - border-color: #002f7b; - color: #FFFFFF; + background-color: #e5edfc; + border-color: #1355d0; + color: #1355d0; } -.c2 { +.c1 { border: 0; height: 0; margin: 0; @@ -77,7 +77,28 @@ exports[` snapshot checked 1`] = ` width: 0; } -.c0 .c3 { +.c1:focus ~ .c2 { + box-shadow: 0 2px 6px 0 rgba(19,85,208,0.5); + background-color: #1355d0; + border-color: #1355d0; + color: #FFFFFF; +} + +.c1:hover ~ .c2 { + box-shadow: 0 2px 4px 0 #cccccc; + background-color: #002f7b; + border-color: #002f7b; + color: #FFFFFF; +} + +.c1:active ~ .c2 { + box-shadow: 0 2px 4px 0 #4c4c4c; + background-color: #002f7b; + border-color: #002f7b; + color: #FFFFFF; +} + +.c0 .c5 { margin-left: 8px; font-size: 17px; } @@ -85,26 +106,28 @@ exports[` snapshot checked 1`] = `
-
`; exports[` snapshot children 1`] = ` -.c1 { +.c3 { display: block; margin-bottom: 5px; -webkit-align-items: center; @@ -144,43 +167,88 @@ exports[` snapshot children 1`] = ` display: inline-flex; } -.c1 *:nth-child(2) { +.c3 *:nth-child(2) { margin-left: 5px; } -.c1:hover { - box-shadow: 0 2px 4px 0 #cccccc; - background-color: #e5edfc; - border-color: #1355d0; - color: #1355d0; +.c1 { + border: 0; + height: 0; + margin: 0; + opacity: 0; + overflow: hidden; + padding: 0; + position: absolute; + width: 0; } -.c1:focus { +.c1:focus ~ .c2 { box-shadow: 0 2px 4px 0 rgba(19,85,208,0.5); background-color: #FFFFFF; border-color: #1355d0; color: #1355d0; } -.c1:active { +.c1:hover ~ .c2 { + box-shadow: 0 2px 4px 0 #cccccc; + background-color: #e5edfc; + border-color: #1355d0; + color: #1355d0; +} + +.c1:active ~ .c2 { box-shadow: 0 2px 4px 0 #4c4c4c; background-color: #e5edfc; border-color: #1355d0; color: #1355d0; } -.c2 { - border: 0; - height: 0; - margin: 0; - opacity: 0; - overflow: hidden; - padding: 0; - position: absolute; - width: 0; +.c4:focus ~ .c2 { + box-shadow: 0 2px 6px 0 rgba(19,85,208,0.5); + background-color: #1355d0; + border-color: #1355d0; + color: #FFFFFF; +} + +.c4:hover ~ .c2 { + box-shadow: 0 2px 4px 0 #cccccc; + background-color: #002f7b; + border-color: #002f7b; + color: #FFFFFF; +} + +.c4:active ~ .c2 { + box-shadow: 0 2px 4px 0 #4c4c4c; + background-color: #002f7b; + border-color: #002f7b; + color: #FFFFFF; +} + +.c5:focus ~ .c2 { + border-color: #ff2d4d; + box-shadow: 0 2px 6px 0 #ff2d4d; + background-color: #ffe5e9; + border-color: #ff2d4d; + color: #ff2d4d; +} + +.c5:hover ~ .c2 { + border-color: #ff2d4d; + box-shadow: 0 2px 6px 0 #ff2d4d; + background-color: #ffe5e9; + border-color: #ff2d4d; + color: #ff2d4d; } -.c0 .c3 { +.c5:active ~ .c2 { + border-color: #ff2d4d; + box-shadow: 0 2px 6px 0 #ff2d4d; + background-color: #ffe5e9; + border-color: #ff2d4d; + color: #ff2d4d; +} + +.c0 .c6 { margin-left: 8px; font-size: 17px; } @@ -188,26 +256,28 @@ exports[` snapshot children 1`] = `
-
`; exports[` snapshot disabled 1`] = ` -.c1 { +.c3 { display: block; margin-bottom: 5px; -webkit-align-items: center; @@ -247,11 +317,53 @@ exports[` snapshot disabled 1`] = ` display: inline-flex; } -.c1 *:nth-child(2) { +.c3 *:nth-child(2) { margin-left: 5px; } -.c2 { +.c5:focus ~ .c2 { + box-shadow: 0 2px 4px 0 rgba(19,85,208,0.5); + background-color: #FFFFFF; + border-color: #1355d0; + color: #1355d0; +} + +.c5:hover ~ .c2 { + box-shadow: 0 2px 4px 0 #cccccc; + background-color: #e5edfc; + border-color: #1355d0; + color: #1355d0; +} + +.c5:active ~ .c2 { + box-shadow: 0 2px 4px 0 #4c4c4c; + background-color: #e5edfc; + border-color: #1355d0; + color: #1355d0; +} + +.c6:focus ~ .c2 { + box-shadow: 0 2px 6px 0 rgba(19,85,208,0.5); + background-color: #1355d0; + border-color: #1355d0; + color: #FFFFFF; +} + +.c6:hover ~ .c2 { + box-shadow: 0 2px 4px 0 #cccccc; + background-color: #002f7b; + border-color: #002f7b; + color: #FFFFFF; +} + +.c6:active ~ .c2 { + box-shadow: 0 2px 4px 0 #4c4c4c; + background-color: #002f7b; + border-color: #002f7b; + color: #FFFFFF; +} + +.c1 { border: 0; height: 0; margin: 0; @@ -262,12 +374,12 @@ exports[` snapshot disabled 1`] = ` width: 0; } -.c0 .c3 { +.c0 .c4 { margin-left: 8px; font-size: 17px; } -.c4 .c3 { +.c7 .c4 { margin-left: 8px; font-size: 17px; } @@ -275,23 +387,25 @@ exports[` snapshot disabled 1`] = `
-