Styled-Components Pass Props For Condition - reactjs

I am trying to make a conditional icon with styled-components. But I need to pass props like function params. Because I need to change the icon with the condition.
export const RadioCheck = ({checked}) => styled(checked ? FaCheckCircle : FaRegCircle)`
display: flex;
align-self: center;
margin: 0 2em;
font-size: 1em;
color: ${props => props.checked ? primary : `transparent`}
`
Is there any way for this or I need to create two different components and use them?

Seems to me like you should use the condition where you return the icon to decide which component to use.
Something like
return(
<div>
{checked ?
<FaCheckCircle
//... your props
/>
:
<FaRegCircle
//... props
/>
}
</div>
)
If it's helpful to you, it is possible to style a styled component, such as
const FirstComponent = styled.div`
//some styling
`
const SecondComponent = styled(FirstComponent)`
//some more styling
`

Related

styled-components — how to use :not() selector on a prop?

Let's say I have an element with a property "selected":
<Button selected>
Text
</Button>
const Button = styled.div`
&:not(???) {
color: red;
}
`;
How do I select all instances of Button which don't have the "selected" property?
Maybe there is another way to do what I'm trying to achieve?
Сlarification edit:
I actually need to use :not together with :hover, like this:
const Button = styled.div`
&:not(???):hover {
color: red;
}
`;
styled-components uses some template magic to allow you to access passed props like so:
const Button = styled.div`
color: ${props => props.selected ? "color when selected" : "red"};
`;
With styled-components, this tends to be the more idiomatic way of setting things based on props rather than using CSS selectors.
That's how you can do it:
const Button = styled.div`
${props => !props.selected && css`
:hover {
color: red;
}`
}
`;
Don't forget to import css from styled-components;

Styled component ReactJs

export const RedHeader = styled.div`
color: red;
border: 1px solid blue;
background-color: gray;
`;
function Header(className) {
return (
<RedHeader className={className}>
this is styled component example
<p>test</p>
</RedHeader>
)
}
export default Header;
I have red the cdocumentation but i can't figure out, why should we use className as a props and after that in className={className}?
When using styled components, there should be no need to use className (which renders as class attribute in HTML) anymore. In your example, you pass className to the styled component, but the styled component does not use it in any way.
You can pass properties to your styled components if you want dynamic styling like you would do with class names in classic CSS.
Example with style that depends on a class name:
const RedHeader = styled.div`
color: red;
&.active {
color: blue;
}
`
Example with props:
const RedHeader = styled.div`
color: ${props => props.active ? 'blue' : 'red'}
`
function Header({ active }) {
return (
<RedHeader active={active}>
example
</RedHeader>
)
}

How to use {withTheme} in styled component.? any one give real-time example please

Actually, I don't understand how to use {withTheme} in styled component and its usage also. So anyone gives proper code with using {withTheme} in styled component.
withTheme is helping you to reach theme variables from your component props. When you define a theme you can normally use them in styled components but if you define your component with withTheme HOC you can use those variables in your component.
// Define our button, with the use of props.theme
const Button = styled.button`
color: ${props => props.theme.fg};
border: 2px solid ${props => props.theme.fg};
background: ${props => props.theme.bg};
`;
// Define our button, but with the use of component.props
const ThemeButton = (props) => (
<button style={{background: props.theme.bg, color: props.theme.fg, border: `1px solid ${props.theme.fg}`}}>
{`this button is using: ${props.theme.fg} and ${props.theme.bg}`}
</button>
)
const ButtonWithTheme = withTheme(ThemeButton);
// Define our `fg` and `bg` on the theme
const theme = {
fg: "palevioletred",
bg: "white"
};
<ThemeProvider theme={theme}>
<div>
<Button>Default Theme</Button>
<ButtonWithTheme></ButtonWithTheme>
</div>
</ThemeProvider>
You can check in here https://codesandbox.io/s/zealous-sky-kgjqj?fontsize=14

How to inherit style from another component?

I want to take styling from the component 'Tab' which is a react-router-dom Navlink and apply it to my new component 'DropdownTab' which is a 'div'. How can I inherit the styling without making it a NavLink? I want to do this to avoid duplicate lines of code.
const Tab = styled(NavLink)`
padding: 0 20px;
height: ${variables.height};
line-height: ${variables.height};
`;
// Should be the component 'Menu' and is now the component NavLink
const DropdownTab = styled(Tab)`
`;
Perhaps you can use as?
const DropdownTab = styled(props => <Tab as="div" {...props} />)`
/* additional styles */
`;
That's ugly though, so maybe you can just extract the common styles into a variable:
const commonStyles = `
/* common styles */
`
const Tab = styled(NavLink)`${commonStyles}`
const DropdownTab = styled('div')`${commonStyles}`
If you have prop-based style in your component (i.e color: ${props => props.color}, you'd need to use css helper:
import styled, { css } from 'styled-components'
const commonStyles = css`
color: ${({ isActive }) => isActive ? 'red' : 'blue' };
`
...
Why is DropdownTab a div?
Based on your code, DropdownTab is a Tab. You've used the extending styles concept of styled-components and you've done it right.

Best way to style a component?

I have two solutions to style my component. Which one is the better choice?
First option is to set everything in the styled component.
Second option is to use many container and styles one by one containers.
First option:
export const BaseContainer = styled.div`
span {
color: #E0E0E0;
}
i {
margin-right: 16px;
}
`;
<BaseContainer data-testid="base">
<i className="icon-share" />
<span> {base} </span>
</BaseContainer>
Second option:
export const BaseContainer = styled.div`
color: #E0E0E0;
`;
export const IconContainer = styled.div`
margin-right: 16px;
`;
<IconContainer>
<i className="icon-share" />
</IconContainer>
<BaseContainer data-testid="base">
{base}
</BaseContainer>
I would go for the second option as the first option ties together 2 elements in one div and if you would want to use the same css properties in another case would require refactoring.
But be aware that your second option is not really a small difference from the first:
In your first option you have one div with one i and one span inside of it and you are applying style to i and span correspondingly.
In your second option you have 2 separate div one with one i and the other with just a content and you are applying style to both div instead.
That said, the best solution would be to actually style the span and i individually, something like
const StyledSpan = styled.span`
color: #E0E0E0;
`
const StyledIcon = styled.i`
margin-right: 16px;
`
And then use them as:
<div data-testid="base">
<StyledIcon className="icon-share" />
<StyledSpan>{base}</StyledSpan>
</div>
I think it's a bit opinion based, but I would approach this a manner like this:
const IconContainer = styled.i`
margin-right:16px;
`;
const Icon = ({
iconType,
...props}) => <IconContainer className={ `icon-${iconType}` } {...props } />;
const BaseContainer = styled.div`
color: #E0E0E0;
`;
const LabelledIcon = ({ iconType, ...props }) => <BaseContainer>
<Icon iconType={ iconType } />
{ props.children }
</BaseContainer>;
// usage:
<LabelledIcon iconType="share"> icon label text </LabelledIcon>

Resources