Using ThemeProvider on Styled-Components UI Library - reactjs

I'm creating a UI library which uses Styled-components and i have a component like this
const Title = styled('div')`
color: ${({ theme }) => theme.sender.color};
font-size: 0.9rem;
padding: 0.5rem 0.3rem 0.5rem;
span {
color: ${({ theme }) => theme.sender.color};
background: ${({ theme }) => theme.sender.botBackground};
border-radius: 0.2rem;
padding: 0.2rem 0.4rem;
text-transform: uppercase;
}
`;
I need to implement in another project, importing the component from my UI Library. I've done all the process to build the library and set it up to be used as a library using rollup and babel.
<ThemeProvider theme={customTheme}>
<Title />
</ThemeProvider>
however when i try to use the ThemeProvider in the project, the theme prop is not being passed down and i'm getting an error because it's trying to get sender from undefined
Any ideas of why this is happening?

A cleaner implementation might look something like this:
const Title = styled('div')`
color: ${ props => props.sender.color};
`;
<ThemeProvider theme={defaultMessageBubbleTheme}>
<Title />
</ThemeProvider>

Related

How to properly type the theme passed as prop to the styled() method on Material UI? (TypeScript)

I'm using Material UI with its styled function to stylize components, such as:
const MyThemeComponent = styled("div")(({ theme }) => `
color: ${theme.palette.primary.contrastText};
background-color: ${theme.palette.primary.main};
padding: ${theme.spacing(1)};
borderRadius: ${theme.shape.borderRadius};
`);
It works, but the typing does not, showing the fields, after written, as of type any. So, we're left without autocomplete, suggestions or error checking.
How can I have the typing working properly within the styled() method?
demo
Fixed it by using the Emotion / Styled-Components format instead of the MUI format shown in the documentation.
const MyThemeComponent = styled("div")`
color: ${({ theme }) => theme.palette.primary.contrastText};
background-color: ${({ theme }) => theme.palette.primary.main};
padding: ${({ theme }) => theme.spacing(2)};
border-radius: ${({ theme }) => theme.shape.borderRadius}px;
`;
fixed demo
does that work for you https://codesandbox.io/s/themeusage-material-demo-forked-pikixf.
I can't really test it properly if the autocomplete is working in the codesandbox.

How to make Styled components generic to receive parameters?

I'm trying to use Styled Components with React FC. I want to display few details inside a div container, which all has the same stylings. Instead of writing hard coded such as Name: Height: Weight: etc. in the h-tags, can I do it in a more generic way to pass the text as parameter?
This is the way I have implemented, but I am thinking there should be some better way to do it. Like giving a parameter to the Styled component.
const CardContentContainer= styled.div`
margin: 4px;
padding: 4px;
text-align: left;
font-size: 14px;
`;
const CardContentDetails = styled.h3`
font-weight: normal;
color: #fff;
margin: 8px;
white-space: nowrap;
`;
this is the code inside the return:
return (
<CardContentContainer>
<CardContentDetails>
Name: {ItemDetails?.name}
</CardContentDetails>
<CardContentDetails>
Height:{ItemDetails?.height}
</CardContentDetails>
<CardContentDetails>
Weight:{ItemDetails?.weight}
</CardContentDetails>
</CardContentContainer>
);
You cant pass such props to Styled components because the main point of SC is to apply a custom style to that component. To make it receive some custom props, you have to wrap it inside another component like so...
const StyledTextField = styled(TextField)`
margin-bottom: 1rem;
width: 20em;
`;
const Comp: React.FC<{ title: string }> = ({ title }) => (
<StyledTextField>{title}</StyledTextField>
);
return (
<Comp title="some title" />

Can you overwrite styles in Material UI using css/scss?

At the moment I'm using SCSS, as it is easy to use with NextJS. I really like how this system works, using the SCSS modules, and so I would also like to use it when using Material-UI. Material-UI uses JSS, which is a lot of boilerplate to write every time. Additionally, I prefer not to work with two ways of styling (SCSS modules and JSS). I already changed the order of CSS injection, so that I can use my SCSS modules on Material-UI components. However, I'm wondering if there is a way to overwrite styles of Material-UI components using SCSS modules? I have tried the following and a few similar things, but nothing seemed to work:
import styles from "./Login.module.scss";
import Button from "#material-ui/core/Button";
function Login() {
return (
<section>
<Button className={styles.button} variant="contained" color="primary">
Verify
</Button>
</section>
);
}
export default Login;
.button {
padding: 10px;
margin-bottom: 10px;
.MuiButton-containedPrimary {
border: 2px solid red;
background-color: red;
}
}
Below is the correct syntax:
.button {
padding: 10px;
margin-bottom: 10px;
&:global(.MuiButton-containedPrimary) {
border: 2px solid red;
background-color: red;
}
}
The example above has two key changes:
Using :global(.MuiButton-containedPrimary). Without using :global, CSS modules will transform the MuiButton-containedPrimary into a class name unique to this module and then it won't match what Material-UI puts on the button.
Adding the & in front effectively creates a selector like .button.MuiButton-containedPrimary matching an element with both classes on it. Your original syntax would treat .MuiButton-containedPrimary as a descendant selector and only match elements with that class that are a descendant of the button rather than the button itself.
You can use makeStyles of #material-ui. And pass to classes to override CSS default of material-ui.
import { makeStyles } from "#material-ui/styles";
const useStyle = makeStyles(() => ({
root: {
padding: "10px",
marginBottom: "10px",
},
containedPrimary: {
border: "2px solid red",
backgroundColor: "red"
}
}))
function Login() {
const classes = useStyle();
return (
<section>
<Button classes={classes} variant="contained" color="primary">
Verify
</Button>
</section>
);
}

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

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

Resources