Adding props on styled components getting opposite result - css

I have created styled components and Im changing a text color by passing props.
<Button variant = 'colour' type="submit" form="myForm" className="submit-btn">
Submit
</Button>
export const FindFormModal = styled(Modal)`
.submit-btn {
width: 35%;
padding: 12px;
color:${props => props.variant === 'colour' ? 'blue' : 'green'}
border-radius: 3px;
font-weight: 500;
font-size: 16px;
margin: 0px 0 10px 0;
}
`
In this if variant === 'colour' then show blue but I'm getting green. If i do variant !== 'colour' then I get blue.
Isn't have to be working opposite?

You don't usually want to be using className along with styled components.
export const FindFormModal = styled(Modal)`
width: 35%;
padding: 12px;
color:${props => props.variant === 'colour' ? 'blue' : 'green'};
border-radius: 3px;
font-weight: 500;
font-size: 16px;
margin: 0px 0 10px 0;
`
<Button variant = 'colour' type="submit" form="myForm">
Submit
</Button>

Related

Is there a way to change the background color of a parent element when a radio button is clicked without jQuery?

The code structure looks somewhat like this
function RenderOptions() {
return allOptions.map((val) => {
return (
<>
<label htmlFor={val}>
<input
type="radio"
name="options"
id={val}
value={val}
className="check-btn"
/>{" "}
<span className="text-inner">{val}</span>
</label>{" "}
</>
);
});
}
Didn't put a div since I didn't want to spend some time finding how to align the buttons in rows.
CSS
.check-btn {
opacity: 0;
position: relative;
top: 2px;
}
label {
border-radius: 10px;
font-family: Inter;
font-style: normal;
font-weight: 600;
font-size: 12px;
line-height: 12px;
text-align: center;
width: 100%;
transition: 0.3s ease;
background: #f5f7fb;
border: 0.794239px solid #4d5b9e;
box-sizing: border-box;
border-radius: 7.94239px;
padding-top: 5px;
padding-bottom: 5px;
padding: 5px 10px 5px 10px;
}
label:hover {
background-color: #d6dbf5;
cursor: pointer;
}
.text-inner {
position: relative;
right: 10px;
}
I'm trying to change the background color of the parent label when the radio button is checked. Can do it the CSS way or the React way provided only 1 button from each sets color changes.
and if another option is clicked ->
TL;DR. See the CodePen sample I prepared for you here, and the snippet below.
In this example, I simply used the useState hook to keep track of the current radio selection, and applied its value as data attribute to label tag. Then you can use CSS to style it as needed.
const App = () => {
const [chosenOne, setChosenOne] = React.useState();
const list = ["Alec Baldwin", "Bruce Willis", "Dwayne Johnson", "Jamie Fox"];
return (
<div>
{list.map((person, i) => (
<label key={i} htmlFor={person} data-chosen={chosenOne === person}>
<input type="radio" name="options" id={person} value={person} className="check-btn" onChange={(e) => setChosenOne(e.target.value)}/>
<span className="text-inner">{person}</span>
</label>
))}
</div>
)
}
.check-btn {
opacity: 0;
position: relative;
top: 2px;
}
label {
border-radius: 10px;
font-family: Inter;
font-style: normal;
font-weight: 600;
font-size: 12px;
line-height: 12px;
text-align: center;
width: 100%;
transition: 0.3s ease;
background: #f5f7fb;
border: 0.794239px solid #4d5b9e;
box-sizing: border-box;
border-radius: 7.94239px;
padding-top: 5px;
padding-bottom: 5px;
padding: 5px 10px 5px 10px;
}
label:hover, label[data-chosen="true"] {
background-color: #d6dbf5;
cursor: pointer;
}
.text-inner {
position: relative;
right: 10px;
}
label + label {
margin-left: .5rem;
}
You could do that with CSS or the style prop in React.
I'm assuming your storing the state of the radio buttons somewhere?
When you map through the array, you can check if the current radio button's value is equal to the value of the current state. If they are the same, you can add the class or style to style the label.

Reactjs Styled-components not working properly

I have a styled checkbox and I want to set its background to white when checked:false and to green when checked:true
But the problem is background color is always staying green and i dont know why.
The react component in which I'm using this checkbox component is acting right,Its just background color that i cant adjust
Any suggestions please?
const CheckboxContainer = styled.div`
display: inline-block;
vertical-align: middle;
`
const Icon = styled.svg`
fill: none;
stroke: white;
stroke-width: 2px;
`
const HiddenCheckbox = styled.input.attrs({ type: 'checkbox' })`
border: 0;
clip: rect(0 0 0 0);
clippath: inset(50%);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
white-space: nowrap;
width: 1px;
`
const StyledCheckbox = styled.div`
display: inline-block;
width: 16px;
height: 16px;
background: #ffffff;
border-radius: 3px;
transition: all 150ms;
margin-top: 10px;
${HiddenCheckbox}:focus + & {
background: ${({ checked }) => (checked ? '#06ba63' : '#ffffff')};
}
${Icon} {
visibility: ${({ checked }) => (checked ? 'visible' : 'hidden')};
}
`
const Checkbox = ({ className, checked, ...props }) => (
<CheckboxContainer className={className}>
<HiddenCheckbox checked={checked} {...props} />
<StyledCheckbox checked={checked}>
<Icon viewBox="0 0 24 24">
<polyline points="20 6 9 17 4 12" />
</Icon>
</StyledCheckbox>
</CheckboxContainer>
)
export default Checkbox
you should check for checked instead of focus of the checkbox :
${HiddenCheckbox}:checked + & {
background: ${({ checked }) => (checked ? '#06ba63' : '#ffffff')};
}
If both Hidden and Styled checkboxes are get the same value from checked, you only need to use the value of checked passed to StyledCheckbox (like you do with Icon):
const StyledCheckbox = styled.div`
display: inline-block;
width: 16px;
height: 16px;
background: #ffffff;
border-radius: 3px;
transition: all 150ms;
margin-top: 10px;
background: ${({ checked }) => (checked ? '#06ba63' : '#ffffff')};
${Icon} {
visibility: ${({ checked }) => (checked ? 'visible' : 'hidden')};
}
`
The other option is only to apply the style if HiddenCheckbox is checked via CSS selectors:
const StyledCheckbox = styled.div`
display: inline-block;
width: 16px;
height: 16px;
background: #ffffff;
border-radius: 3px;
transition: all 150ms;
margin-top: 10px;
background: white;
${Icon} {
visibility: hidden;
}
${HiddenCheckbox}:checked + & {
background: #06ba63;
}
${HiddenCheckbox}:checked + & > ${Icon} {
visibility: visible;
}
`

Overriding a styled-component with new styled-component?

I have a three styled-components StyledBanner and StyledTitle and WarningBanner.
I am looking to overwrite StyledBanner color through WarningBanner but is is not working out and the return Component always fall back to the div color.
How can I restyle a styled-component?
const StyledBanner = styled.div`
background-color: ${theme.colors.blue_2};
padding: 15px;
display: flex;
flex-direction: column;
border-radius: 4px;
width: 100%;
`;
const StyledTitle = styled(PG)`
font-size: 1.125rem;
font-weight: bold;
padding: 0px 0px 15px 0px;
colors: ${theme.colors.blue_2}
`
const WarningBanner = styled(StyledBanner)`
background-color: ${theme.colors.banner_yellow}
${StyledTitle}{
colors: ${theme.colors.textColor}
`
...
return (<WarningBanner> //still showing theme.colors.blue_2
{title ? <StyledTitle> //still showing theme.colors.blue_2
{title}
</StyledTitle> : null}
</WarningBanner>)
You have a minor typo in your posted code (the CSS property you want to set is color, not plural). Otherwise, your approach is perfectly valid.
Working example: https://codepen.io/mattlubner/pen/XWrvQLP
const theme = {
colors: {
red: '#f00',
greed: '#0f0',
blue: '#00f',
yellow: '#ff0',
},
};
const StyledBanner = window.styled.div`
background-color: ${theme.colors.blue};
padding: 15px;
display: flex;
flex-direction: column;
border-radius: 4px;
width: 100%;
`;
const StyledTitle = window.styled.h1`
font-size: 1.125rem;
font-weight: bold;
padding: 0px 0px 15px 0px;
color: ${theme.colors.blue};
`;
const WarningBanner = window.styled(StyledBanner)`
background-color: ${theme.colors.yellow};
${StyledTitle} {
color: ${theme.colors.green};
`;
ReactDOM.render(
<WarningBanner>
<StyledTitle>Example Title</StyledTitle>
</WarningBanner>,
document.getElementById('root'),
);

Content of div gets shifted to the left after a scale animation

I have a div in which, after applying a scale() transform (using react-spring) to it on mouseOver and mouseLeave, the div's contents shift 1 or 2 pixels to the left after returning to the original scale(1) position.
Gif of div's behavior
Here's the Card component (using styled-components):
const Card = styled.div`
position: relative;
display: block;
width: 100%;
text-align: left;
margin: 16px 0 32px 0;
padding: 14px 24px 16px 24px;
border: 1px solid hsla(0, 0%, 92%, 1);
border-radius: 8px;
color: ${props => props.theme.black};
background: #fff;
transition: transform 0.18s ease-in-out, box-shadow 0.18s ease-in-out;
span {
font-family: ${props => props.theme.headerFont};
text-transform: uppercase;
font-weight: 500;
font-size: 14px;
letter-spacing: 0.1em;
text-align: left;
color: #0c344b;
opacity: 0.45;
b {
font-size: 12px;
}
}
${media.tablet`
padding: 12px 30px 22px 30px;
`}
`
And here's where it's being rendered:
export default function Article({
date = '',
title = '',
timeToRead = '',
excerpt = '',
slug = ''
}) {
const [hover, setHover] = useState(false)
const props = useSpring({
transform: `scale(${hover ? 1.05 : 1})`,
borderRadius: `8px`,
boxShadow: `${hover ? `1px 1px 14px #ededed` : `0px 2px 8px #f0f0f0`}`,
config: {
mass: 1,
tension: 350,
friction: 40
}
})
return (
<Link to={slug}>
<animated.div style={props}>
<Card
onMouseOver={() => setHover(true)}
onMouseLeave={() => setHover(false)}
>
<span>{date}</span>
<span
css={`
float: right;
`}
>
<b role="img" aria-label="Time to read">
🕙
</b>{' '}
{timeToRead} min
</span>
<h2
css={`
margin: 0;
font-weight: 800;
font-size: 1.4em;
padding: 4px 0 8px 0;
`}
>
{title}
</h2>
<p
css={`
margin: 0;
line-height: 26px;
font-size: 16px;
`}
dangerouslySetInnerHTML={{ __html: excerpt }}
/>
</Card>
</animated.div>
</Link>
)
}
Any insight would be deeply appreciated!
EDIT: I should add that, if I leave the mouseOut scale around 1.0, i.e. 1.00001 or 0.99999, the contents do not shift as was described. Ideally I want to fix this without resorting to this hack, but if I leave it this way, should I expect a performance hit?

Is there a way to modify '&:before/:after' to give a dynamic property?

A styled-component that has &:before attribute that I want to give access to a dynamic color property. But I'm lost to how to apply that.
I've Tried passing the props to <Hover /> and it works. But the Triangle in &:before cannot access that.
const Hover = styled.div`
padding:7px;
margin: -102px auto;
border-style: solid;
border-radius: 15px;
border-width: 3px;
text-align: left;
font-weight: 400;
font-size: 19px;
color: #000000;
font-family: sans-serif;
position: absolute;
left:-15px;
z-index:10;
&:before {
content: "";
width: 0px;
height: 0px;
position: absolute;
border-left: 10px solid ;
border-right: 10px solid transparent;
border-top: 10px solid ;
border-bottom: 10px solid transparent;
left: 19px;
bottom: -19px;
z-index:10;
}
`;
As a single styled-component the following class is:
class MarkerHover extends Component {
render() {
const {color, children}= this.props
return (
<Hover style={{backgroundColor: color }}>
{...children}
</Hover>
);
}
}
export default MarkerHover;
I expect to have a whole colored Window after successfully passing the color props to the &:before division.
As the documentation of Styled Components states (see https://www.styled-components.com/docs/basics#passed-props) you can read passed props:
const Hover = styled.div`
color: ${props => props.color};
`;
when you pass them like this:
<Hover color="#f00" />
You can use that same prop in your pseudo-element as well:
const Hover = styled.div`
color: ${props => props.color};
&::before {
background: ${props => props.color};
}
`;
So don't use the style attribute on your styled component, but pass regular props.
If you want to apply a CSS rule only after a certain condition, you can do that like this:
const Hover = styled.div`
color: #ccc;
&::before {
content: "";
padding: 16px;
${props => props.withBg ? `background-color: ${props.withBg}` : ''}
}
`;
With background:
<Hover withBg="#f00" />
Without background:
<Hover />

Resources