Create variable from props and reuse in code block with Styled Components? - styled-components

Ive got a basic styled component working. When the prop isHere is passed then the background is blue.
const Item = styled.ul`
${props => console.log(props.theme.colorGroupSelected)};
${props => (props.isHere ? `background:` + 'blue' : null)};
`;
Instead of blue I need to use the colour colorGroupSelected from my theme but I cant get it to work, I keep getting a syntax error.
const Item = styled.ul`
${props => (props.isHere ? `background:` + props => props.theme.colorGroupSelected : null)};
`;
My code is getting quite hard to read. Is it possible to destructure a variable within a styled block? Something like this:
${const colorGroupSelected = (props => return props.theme.colorGroupSelected)};
${props => (props.isHere ? `background:` + colorGroupSelected : null)};

This works but doesn't destructure the variable:
${props => (props.isHere ? `background:` + props.theme.colorGroupSelected : null)};

Related

Use Props in Styled Component to Change Style *Name* (Not Value)

Styled Components let you use props in your CSS, eg.:
styled.whatever`
margin: ${props => props.bigMargin ? '20px' : '5px'}
`;
However, I just tried to use the props in the style name instead:
styled.whatever`
margin-${props => props.leftmargin ? 'left' : 'right'}: 10px;
`;
and when I do that, in the Chrome debugger it looks like:
margin-right: ;
: 1em;
Is it not possible to change your style names using props, or am I just doing it wrong somehow?
The only way I could get it to work was to put both the name and value into the props-controlled part:
${({ leftmargin }) =>
leftmargin ? `margin-left: 1em` : `margin-right: 1em`}};
This works, but if anyone has a better answer (a "DRY-er" one), I'll happily accept it.

Background: url() using .attrs() function

I'm trying to display a different background depending on props with .attrs();
I have the following;
const Heart = styled.div.attrs(props => ({
background: `url(${props => props.filled ? "./media/heart-filled.png" : "./media/heart-empty.png"})`
}))`
//rest of styles here.
`;
However, it doesn't display anything. How exactly does this function work?
I don't know why you're trying to use .attrs here, but it's used to attache some props to a styled component.
https://styled-components.com/docs/api#attrs
To make your code work, you could try:
const Heart = styled.div.attrs(props => ({/* Some aditional props here ! */}))`
background: url(${props => (props.filled ? "./media/heart-filled.png" : "./media/heart-empty.png")}); /* props that you pass into your component can be used here */
/* rest of styles here. */
`;
https://codesandbox.io/s/condescending-brown-lx0lf?file=/src/App.js

Retrieve extended styles

My code is:
styled(Button)`
color: ${(props: any) => COLOR_I_CHOOSE}
`
I was following the "extending styles" section in the docs - https://www.styled-components.com/docs/basics#extending-styles
Button is a custom styled component. I want to pass in a color so it overrides the internal setting of the color to COLOR_I_CHOOSE. I have control over the internals. In the internals I am trying to detect if any styled overrides were provided and use that.
Internally I set the CSS like this:
const primaryChildre
nCSS = css`
color: ${(props: any) => {
console.log('props:', props);
// TODO: test if props has override on color and use that
// PSEUDOCODE: if (props.styleExtensions.color) return props.styleExtensions.color
return props.inverse
? props.theme.ns().colors.brand
: props.theme.ns().colors.white;
}};
`;
I logged out props here, but can't figure out how to get that. I want to do as the pseudocode comment in the above.
<Button> Hello</Button> // default color
The following will override the default color of Button if the passed color is not red.
const MyRedTextButton = styled(Button)`
color: ${(props: any) => props.color === 'red' ? 'inherit' : props.color}
`
Then:
<MyRedTextButton color="red"> Hello </MyRedTextButton> // color of 'Hello' = the color of <Button/>
<MyRedTextButton color="blue"> Hello </MyRedTextButton> // color of 'Hello' = blue
Does this solve your problem?

Problem with passing functional prop to styled components element. Is that posssible at all?

I try to pass the prop being a function (returning boolean) call to Styled Components with no effect.It looks like there is no length applied at all.
I have also tried syntax where "lenth" is fixed and only its value is function return, but stick to this version as clearer for me. also (props.length) without clear comparision and many other combinations.
That is how my styled element is styled
export const header = {
cell: styled.th`
background-color: rgba(188, 107, 63, 0.3);
vertical-align: bottom;
border: none;
padding: 0.75rem;
cursor: pointer;
vertical-align-middle;
${props => ((props.length === true) ? 'length: 30%;' : 'length: 13%;')};
`,
};
That is my function that returns desired prop
const isThisFirstOrSecondColumn = x => x === 0 || x === 1;
That is how my header.cell component is applied (part only, it's a little longer)
return (
<tr onClick={handleSort}>
{headers.map((item, index) => (
<header.cell
length={isThisFirstOrSecondColumn(index)}
key={item}
length is no valid css property and therefore your length prop has no effect. Also you would want only pass the values like this:
width: ${props => props.length ? '30%' : '13%'};
Otherwise you would have to use
${props => props.length ? css`width: 30%;` : css`width: 13%;`}
vertical-align-middle; is also not valid css. Other than that your code looks okay.

How to write props properly in styled-components?

I need to change background based on condition if props.src exist. First part works fine, but place where it has props => props.src not getting rendered properly.
Result is:
You only need props.src rather than the function props => props.src in your url:
background: ${props => props.src === "" ? "#eff1f2" : `url(${props.src}) no-repeat center`};
Styled components won’t execute the nested inner function so it just gets stringified.

Resources