Emotion.js how to do composition / conditional styling in react-native? - reactjs

https://github.com/emotion-js/emotion/tree/master/packages/native
gives example
style={css`
border-radius: 10px;
`}
However, I can't figure out how I can do composition as done in https://emotion.sh/docs/composition with react-native
<div css={[danger, base]}>
Nor I can't do conditional styling as done in https://emotion.sh/docs/styled
const Button = styled.button`
color: ${props =>
props.primary ? 'hotpink' : 'turquoise'};
`
Even if I could do, they use two different methods one using css one using styled . How can I get the two at the same time with react-native?

Question 1: How to do composition in emotion/native in React Native?
It's really simple all you need to is use style property like so:
const style1 = css`
font-size: 40px;
`
const color = css`
color: red;
`
// And then in your component you can pass the all your style objects
// in an array to style property
<Text style={[fontSize, color]}>Hello world</Text>
Question 2: Conditional style in emotion/native in React Native?
const Description = styled.Text`
font-size: ${props => props.fontSize !== undefined ? props.fontSize : "40px"};
color: hotpink;
`
<Description fontSize={"60px"}>
Change code in the editor and watch it change on your phone! Save to get a shareable url.
</Description>
Here's a working exampe as a snack

Related

How to change other element when hover by using 'styled'

I'm new to Mui and trying to apply animation to components.
What I want to do is, I have four same component and each has its own image.
<MyComponent>some images...</MyComponent>
<MyComponent>some images...</MyComponent>
<MyComponent>some images...</MyComponent>
<MyComponent>some images...</MyComponent>
const MyComponent = styled("div")((theme) => ({
//... some styles.
// scale up when hovered
'&:hover': {
transform: "scale(1.2)",
marginRight: "20px",
}
}));
If I hover a <MyComponent>, I want to scale up hovered one, and scale down others.
Is there any ways to defined such action by using styled???
I would set a state then use a conditional to change styles .. IE
const [hoverState, setHoverState] = useState(false);
<MyComponent
onMouseOver={setHoverState(true)}
onMouseOut={setHoverState(false)}
style={hoverState ? {transform: "scale(1.2)",marginRight: "20px",} : ''}
>
some images...
</MyComponent>
You can do this with css and styled-components.
Note that the styled function is not meant to be called directly, but passed a template literal. Inside the template literal, you can write regular css expressions.
codesandbox
const MyComponent = styled.div`
transform: scale(1);
margin-right: 0px;
:hover {
transform: scale(1.2);
margin-right: 20px;
}
`;

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;

Trying to access a custom prop in styled components

Hi I'm trying to access a custom prop in a styled-component.I know that this is a very basic thing but I can't figure it out. I think that it has something to do with the way how I access my theme.
It does not throw any error but the margin-bottom value is just not showing up in the printed css.
Can you point me in a direction? Thanks!
import StyledWrapper from './productCardStyles';
<StyledWrapper spaceBelow={spaceBelow}>
hello world
</StyledWrapper>
//productCardStyles.js
export default styled('div')(
({ theme }) => `
background: red;
margin-bottom: ${props => (props.spaceBelow ? '25px' : '0')};
`);
Thank you very much for your time.
I assume you are using ThemeProvider in the higher order component. You can access theme by just using props.theme...
Update your productCardStyles.js
import styled from 'styled-components'
const wrapper = styled.div`
background: red;
margin-bottom: ${props => (props.spaceBelow ? '25px' : '0')};
color: ${props => props.theme.primaryColor} // to access theme
`
export default wrapper

Question about mixing styled-components with material-ui

Hello I am a react newbie and new to styling as well :)
I am trying to style the material-ui Button component with styled components
I am doing this by overriding global class names, I know material-ui introduced global class names like MuiButton-root etc
I am not clear on the use of "&" in parent selector, for example:
const StyledButton = styled(Button)`
&.MuiButton-root {
width: 500px;
}
.MuiButton-label {
color: ${props => props.labelColor};
justify-content: center;
}
`;
The above code works and can achieve the following:
The Button has a width of 500px
The label has a color of red (labelColor is passed in as a prop)
Please see sandbox below for full code
Question:
Why do I need "&" selector for the MuiButton-root, whereas for the MuiButton-label I don't?
Also is this the best way to style material-ui with styled components?
Please see the following sandbox: https://codesandbox.io/embed/practical-field-sfxcu
The '&' selector is used to target the classes and neighbouring elements/classes. Take a look at cssinjs. Its the underlying system behind MUI's styling.
But in short to answer your question;
const StyledButton = styled(Button)`
&.MuiButton-root { //this targets any class that is added to the main component [1]
width: 500px;
}
.MuiButton-label { //in css-in-js this is effectively '& .MuiButton-label [2]
color: ${props => props.labelColor};
justify-content: center;
}
[1] Targets main classes on component
<StyledButton className='test bob'> << this element is targeted
</StyledButton>
[2] Targets child elements either through class or element type. Note the space between & and the actual class.
<StyledButton className='test bob'>
<span className='MuiButton-label'>test</span> << this element is targeted instead
</StyledButton>
You can also use the element tag directly
span {
color: ${props => props.labelColor};
justify-content: center;
}

Passing in same prop to multiple styled components

I have 3 React Components that are all being passed the same prop isNewListingsHeader. I am using Styled Components for CSS styling. I'm wondering if there is a cleaner way of passing this prop into the 3 different styled components SortBarWrapper, SortOptionsWrapper, and SortOptionsWrapper so that I don't have to define isNewListingsHeader each time.
// Styled Components
const SortBarWrapper = styled.div`
position: relative;
${props => !props.isNewListingsHeader && `
height: 100px;
`}
`
const SortLineWrapper = styled.div`
width: 100%;
${props => !props.isNewListingsHeader && `
position: absolute;
bottom: 0;
`}
`
const SortOptionsWrapper = styled.div`
box-sizing: border-box;
${props => !props.isNewListingsHeader && `
padding-bottom: 24px;
padding-top: 32px;
`}
`
render () {
return (
<SortBarWrapper isNewListingsHeader={this.props.isNewListingsHeader}>
<SortLineWrapper isNewListingsHeader={this.props.isNewListingsHeader}>
<SortOptionsWrapper isNewListingsHeader={this.props.isNewListingsHeader}>
// Display Sort Options
</SortOptionsWrapper>
</SortLineWrapper>
</SortBarWrapper>
)
}
What you are doing is not incorrect but I can understand you wanting to DRY up your code. I am not going to say what is the "right" way because there is technically no correct way, just ways you prefer to do it based on your stack (for example, are you using Redux or any other state management?).
This medium post covers several methods of deep nesting components.
Explore that and pick which works for you. But for the sake of this conversation - you are doing it correctly and in the "React way."
We can use context api. Create a provider and Consumer. Wrap all the components inside the provider, Provider accepts a value prop and the data in this prop is available to all the child consumers. And can use them inside consumer.
“Why you should consider the new Context API in React? — A deep dive” by Mahesh Haldar https://link.medium.com/zrYj36RnhU

Resources