Skip to content

Commit

Permalink
Update: refactored AnswerGroup styles
Browse files Browse the repository at this point in the history
  • Loading branch information
Darrken committed Feb 25, 2019
1 parent d178c1b commit ec2779c
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 117 deletions.
2 changes: 1 addition & 1 deletion packages/es-components/package.json
@@ -1,6 +1,6 @@
{
"name": "es-components",
"version": "19.0.11-alpha",
"version": "19.0.12-alpha",
"description": "React components built for Exchange Solutions products",
"repository": "https://github.com/wtw-im/es-components",
"main": "bundle/main.min.js",
Expand Down
Expand Up @@ -4,25 +4,32 @@ import genId from '../../util/generateAlphaName';
import { useTheme } from '../../util/useTheme';

const AnswerLabel = styled.label`
flex-grow: 1;
@media (min-width: ${props => props.theme.screenSize.desktop}) {
flex-grow: 0;
min-width: ${props => props.itemWidth};
}
`;

const AnswerDisplay = styled.div`
background-color: ${props => props.style.bgColor};
border-color: transparent;
box-shadow: 0 4px 0 0 ${props => props.style.boxShadowColor};
color: ${props => props.style.textColor};
flex-grow: 1;
font-weight: ${props => props.buttonSize.fontWeight || 'normal'};
font-size: ${props => props.buttonSize.fontSize};
line-height: ${props => props.buttonSize.lineHeight};
margin-bottom: 4px;
margin-top: 0;
padding-top: ${props => props.buttonSize.paddingTop};
padding-bottom: ${props => props.buttonSize.paddingBottom};
text-align: center;
text-transform: ${props =>
props.buttonSize.textTransform ? props.buttonSize.textTransform : 'none'};
transition: background-color 250ms linear, color 250ms linear;
&:hover {
background-color: ${props => props.style.hoverBgColor};
color: ${props => props.style.hoverTextColor};
}
transition: background-color 250ms linear, color 250ms linear,
box-shadow 250ms linear;
user-select: none;
&:active {
background-color: ${props => props.style.activeBgColor};
Expand All @@ -32,47 +39,35 @@ const AnswerLabel = styled.label`
margin-top: 4px;
}
@media (min-width: ${props => props.theme.screenSize.desktop}) {
flex-grow: 0;
min-width: ${props => props.itemWidth};
&:hover {
background-color: ${props => props.style.hoverBgColor};
color: ${props => props.style.hoverTextColor};
}
&[disabled] {
cursor: not-allowed;
opacity: 0.65;
> * {
pointer-events: none;
}
}
`;

const OutlineAnswerLabel = styled(AnswerLabel)`
border: 2px solid ${props => props.selected.borderColor};
box-shadow: none;
const OutlineAnswerDisplay = styled(AnswerDisplay)`
background-color: ${props =>
props.isChecked ? props.style.hoverBgColor : props.style.bgColor};
border: 2px solid ${props => props.style.borderColor};
box-shadow: ${props => (props.isChecked ? '0 0 0 0' : 'none')}
${props => props.isChecked && props.style.boxShadowColor};
box-sizing: border-box;
color: ${props =>
props.isChecked ? props.style.hoverTextColor : props.style.textColor};
margin: 0;
&:active {
background-color: ${props => props.selected.activeBgColor};
color: ${props => props.selected.activeTextColor};
margin: 0;
}
&:first-child {
border-radius: 4px 0 0 4px;
}
&:first-child + label {
border-left: none;
}
&:last-child {
border-left: none;
border-radius: 0 4px 4px 0;
}
&:not(:first-child):not(:last-child) {
border-left: 1px;
}
`;

const AnswerDisplay = styled.span`
display: block;
padding-top: ${props => props.buttonSize.paddingTop};
padding-bottom: ${props => props.buttonSize.paddingBottom};
user-select: none;
`;

const AnswerInput = styled.input`
Expand All @@ -81,26 +76,8 @@ const AnswerInput = styled.input`
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap; /* added line */
white-space: nowrap;
width: 1px;
&:checked + span {
background-color: ${props => props.selected.bgColor};
box-shadow: 0 4px 0 0 ${props => props.selected.boxShadowColor};
color: ${props => props.selected.textColor};
}
&:checked + span:active {
box-shadow: 0 0 0 0 transparent;
}
`;

const OutlineAnswerInput = styled(AnswerInput)`
&:checked + span {
background-color: ${props => props.selected.hoverBgColor};
box-shadow: 0 0 0 0 ${props => props.selected.boxShadowColor};
color: ${props => props.selected.hoverTextColor};
}
`;

function AnswerButton({
Expand All @@ -111,56 +88,33 @@ function AnswerButton({
selectedType,
size,
isOutline,
checked,
...radioProps
}) {
const id = radioProps.id || genId();
const isChecked = radioProps.checked || radioProps.defaultChecked;
const theme = useTheme();
let style = theme.buttonStyles.button.variant[styleType];
let selected = theme.buttonStyles.button.variant[selectedType];
let buttonSize = theme.buttonStyles.button.size[size];

if (isOutline) {
style = theme.buttonStyles.outlineButton.variant[styleType];
selected = theme.buttonStyles.outlineButton.variant[selectedType];
buttonSize = theme.buttonStyles.outlineButton.size[size];
}

const labelProps = {
itemWidth,
const buttonStyle = isOutline ? 'outlineButton' : 'button';
const buttonSize = theme.buttonStyles[buttonStyle].size[size];
const style = isChecked
? theme.buttonStyles[buttonStyle].variant[selectedType]
: theme.buttonStyles[buttonStyle].variant[styleType];

const buttonProps = {
disabled: radioProps.disabled,
isChecked,
style,
selected,
buttonSize
};

let button = (
<AnswerLabel {...labelProps}>
<AnswerInput
type="radio"
name={name}
id={id}
{...radioProps}
{...labelProps}
/>
<AnswerDisplay buttonSize={buttonSize}>{children}</AnswerDisplay>
const Display = isOutline ? OutlineAnswerDisplay : AnswerDisplay;

return (
<AnswerLabel itemWidth={itemWidth} htmlFor={id}>
<AnswerInput type="radio" name={name} id={id} {...radioProps} />
<Display {...buttonProps}>{children}</Display>
</AnswerLabel>
);

if (isOutline) {
button = (
<OutlineAnswerLabel {...labelProps}>
<OutlineAnswerInput
type="radio"
name={name}
id={id}
{...radioProps}
{...labelProps}
/>
<AnswerDisplay buttonSize={buttonSize}>{children}</AnswerDisplay>
</OutlineAnswerLabel>
);
}

return button;
}

export default AnswerButton;
@@ -1,36 +1,59 @@
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import styled, { css } from 'styled-components';

const outlineStyles = css`
> label:first-child > div {
border-radius: 4px 0 0 4px;
}
> label:last-child > div {
border-left: none;
border-radius: 0 4px 4px 0;
}
> label:not(:first-child):not(:last-child) > div {
border-left: 1px;
}
`;

const AnswerSet = styled.div`
display: flex;
flex-wrap: nowrap;
${props => props.isOutline && outlineStyles};
`;

function AnswerGroup({
name,
disableAllOptions,
children,
itemWidth,
styleType,
selectedType,
selectedValue,
isOutline,
...rest
}) {
const renderButtons = () =>
React.Children.map(children, (child, index) => {
const key = `${name}-option-${index + 1}`;
const disabled = disableAllOptions || child.props.disabled;
const checked = selectedValue === child.props.value;
return React.cloneElement(child, {
key,
name,
itemWidth,
styleType,
selectedType,
isOutline,
disabled,
defaultChecked: checked,
...rest
});
});

return <AnswerSet>{renderButtons()}</AnswerSet>;
return <AnswerSet isOutline={isOutline}>{renderButtons()}</AnswerSet>;
}

AnswerGroup.propTypes = {
Expand All @@ -46,15 +69,21 @@ AnswerGroup.propTypes = {
/** Set the button size, sizes come from theme (buttonStyles) */
size: PropTypes.string,
/** Set if the items should have a flat outline style */
isOutline: PropTypes.bool
isOutline: PropTypes.bool,
/** Disable all radio buttons */
disableAllOptions: PropTypes.bool,
/** Selected option for the answer group */
selectedValue: PropTypes.any
};

AnswerGroup.defaultProps = {
styleType: 'default',
selectedType: 'success',
size: 'default',
itemWidth: '75px',
isOutline: false
isOutline: false,
disableAllOptions: false,
selectedValue: undefined
};

export default AnswerGroup;
Expand Up @@ -5,19 +5,19 @@ const AnswerButton = require('./AnswerButton').default
function AnswerGroupExample() {
const [activity, setActivity] = React.useState('nothing')
const [answer, setAnswer] = React.useState('nothing')
function handleRadioChange(event) {
setActivity(event.target.value)
setAnswer(event.target.value)
}
return (
<>
<AnswerGroup name="yes-no-question" onChange={handleRadioChange} >
<AnswerGroup name="yes-no-question" onChange={handleRadioChange} selectedValue={answer}>
<AnswerButton value="yes">Yes</AnswerButton>
<AnswerButton value="no">No</AnswerButton>
</AnswerGroup>
<p>You've selected: {activity}</p>
<p>You've selected: {answer}</p>
</>
)
};
Expand All @@ -30,22 +30,21 @@ You can apply different button styles using the `styleType`, `size`, and `select
```
const AnswerButton = require('./AnswerButton').default
function AnswerGroupExample() {
const [activity, setActivity] = React.useState('nothing')
const [answer, setAnswer] = React.useState('nothing')
function handleRadioChange(event) {
setActivity(event.target.value)
setAnswer(event.target.value)
}
return (
<>
<AnswerGroup name="household-type" size="sm" styleType="warning" selectedType="success" itemWidth="200px" onChange={handleRadioChange} >
<AnswerGroup name="household-type" size="sm" styleType="warning" selectedType="success" itemWidth="200px" onChange={handleRadioChange} selectedValue={answer}>
<AnswerButton value="single" isOutline>Single</AnswerButton>
<AnswerButton value="married" isOutline>Married</AnswerButton>
<AnswerButton value="head" isOutline>Head of Household</AnswerButton>
</AnswerGroup>
<p>You've selected: {activity}</p>
<p>You've selected: {answer}</p>
</>
)
};
Expand All @@ -58,22 +57,21 @@ Setting the `isOutline` property will apply a flat style to each `AnswerButton`
```
const AnswerButton = require('./AnswerButton').default
function AnswerGroupExample() {
const [activity, setActivity] = React.useState('nothing')
const [answer, setAnswer] = React.useState('nothing')
function handleRadioChange(event) {
setActivity(event.target.value)
setAnswer(event.target.value)
}
return (
<>
<AnswerGroup name="household-type" styleType="primary" selectedType="primary" itemWidth="200px" onChange={handleRadioChange} isOutline >
<AnswerGroup name="household-type" styleType="primary" selectedType="primary" itemWidth="200px" onChange={handleRadioChange} isOutline selectedValue={answer}>
<AnswerButton value="left">Left</AnswerButton>
<AnswerButton value="middle">Middle</AnswerButton>
<AnswerButton value="right">Right</AnswerButton>
</AnswerGroup>
<p>You've selected: {activity}</p>
<p>You've selected: {answer}</p>
</>
)
};
Expand Down

0 comments on commit ec2779c

Please sign in to comment.