I am trying to implement a radio button set in React using Styled components using this pen as an example however the sibling selector is tripping me up. How to turn this
.radio-input:checked ~ .radio-fill {
width: calc(100% - 4px);
height: calc(100% - 4px);
transition: width 0.2s ease-out, height 0.2s ease-out;
}
.radio-input:checked ~ .radio-fill::before {
opacity: 1;
transition: opacity 1s ease;
}
into css in a styled component?
Can anyone point out my mistake or make a quick pen demo? Thanks! Here is my full code:
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import { colors } from '../../../theme/vars';
export class RadioGroup extends React.Component {
getChildContext() {
const { name, selectedValue, onChange } = this.props;
return {
radioGroup: {
name, selectedValue, onChange,
},
};
}
render() {
const { Component, name, selectedValue, onChange, children, ...rest } = this.props;
return <Component role="radiogroup" {...rest}>{children}</Component>;
}
}
RadioGroup.childContextTypes = {
radioGroup: PropTypes.object,
};
RadioGroup.propTypes = {
name: PropTypes.string,
selectedValue: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.bool,
]),
children: PropTypes.node.isRequired,
Component: PropTypes.oneOfType([
PropTypes.string,
PropTypes.func,
PropTypes.object,
]),
};
RadioGroup.defaultProps = {
name: '',
selectedValue: '',
Component: 'div',
};
// eslint-disable-next-line react/no-multi-comp
export class Radio extends React.Component {
render() {
const { name, selectedValue } = this.context.radioGroup;
const { onChange, value, labelText } = this.props;
let checked = false;
if (selectedValue !== undefined) {
checked = (value === selectedValue);
}
console.log('value: ', value);
console.log('checked: ', checked);
console.log('selectedValue: ', selectedValue);
return (
<Root>
<Input
type="radio"
name={name}
value={value}
checked={checked}
aria-checked={checked}
onChange={onChange}
/>
<Fill />
{/* <div style={{ marginLeft: '25px' }}>{labelText}</div> */}
</Root>
);
}
}
Radio.contextTypes = {
radioGroup: PropTypes.object,
};
Radio.propTypes = {
onChange: PropTypes.func,
value: PropTypes.string,
labelText: PropTypes.string,
};
Radio.defaultProps = {
onChange: () => {},
value: '',
labelText: '',
};
const Root = styled.div`
width: ${props => props.size ? props.size : 20}px;
height: ${props => props.size ? props.size : 20}px;
position: relative;
&::before {
content: '';
border-radius: 100%;
border: 1px solid ${props => props.borderColor ? props.borderColor : '#DDD'};
background: ${props => props.backgroundColor ? props.backgroundColor : '#FAFAFA'};
width: 100%;
height: 100%;
position: absolute;
top: 0;
box-sizing: border-box;
pointer-events: none;
z-index: 0;
}
`;
const Fill = styled.div`
background: ${props => props.fillColor ? props.fillColor : '#A475E4'};
width: 0;
height: 0;
border-radius: 100%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
transition: width 0.2s ease-in, height 0.2s ease-in;
pointer-events: none;
z-index: 1;
&::before {
content: '';
opacity: 0;
width: calc(20px - 4px);
position: absolute;
height: calc(20px - 4px);
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border: 1px solid ${props => props.borderActive ? props.borderActive : '#A475E4'};
border-radius: 100%;
}
`;
const Input = styled.input`
opacity: 0;
z-index: 2;
position: absolute;
width: 100%;
height: 100%;
margin: 0;
cursor: pointer;
&:focus {
outline: none;
}
&:checked {
${Fill} {
width: calc(100% - 8px);
height: calc(100% - 8px);
transition: width 0.2s ease-out, height 0.2s ease-out;
&::before {
opacity: 1;
transition: opacity 1s ease;
}
}
}
`;
and the usage of the component:
<RadioGroup name="setYAxis" onChange={e => this.toggleSetYAxis(e)} selectedValue={this.state.setYAxis}>
<Radio value="autoscale" labelText="Autoscale" />
<Radio value="manual" labelText="Manual" />
</RadioGroup>
I created a codesandbox to fix the css issue and the state management problem. The provided code is simpler and does not rely on an outdated React context API (doc here)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With