From 9a80c6357cecaeb666dcb7c1fe78925f73e72634 Mon Sep 17 00:00:00 2001 From: Daniel Silva Date: Wed, 3 Apr 2019 16:39:23 -0300 Subject: [PATCH] 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`] = `
-