How to apply Styled Component styles to a custom React component? - javascript

I have a Styled Component called StyledButton and a React component called AddToCart. I want to apply the styled from StyledButton to AddToCart.
I have already tried the following:
import styled from "styled-components";
import AddToCart from "./AddToCart";
import StyledButton from "./styles/StyledButton";
const StyledAddToCart = styled(AddToCart)`
${StyledButton}
`;
What I want to do is already in the documentation at https://www.styled-components.com/docs/basics#styling-any-components but this applies new styles to the component. The problem is that I want to use existing styled from a Styled Component (StyledButton)
From the documentation:
// This could be react-router-dom's Link for example
const Link = ({ className, children }) => (
<a className={className}>
{children}
</a>
);
const StyledLink = styled(Link)`
color: palevioletred;
font-weight: bold;
`;
render(
<div>
<Link>Unstyled, boring Link</Link>
<br />
<StyledLink>Styled, exciting Link</StyledLink>
</div>
);
I would really like to have the styles from StyledButton applied to StyledAddToCart without copying the styles manually.

You can share styling with the css util:
// import styled, {css} from 'styled-components'
const {css} = styled;
const Link = (props) => <a {...props} />
const sharedBtnStyle = css`
color: green;
border: 1px solid #333;
margin: 10px;
padding: 5px;
`;
const StyledButton = styled.button`
${sharedBtnStyle}
`;
const AddToCartBtn = styled(Link)`
${sharedBtnStyle}
color: red;
`;
function App() {
return (
<div>
<StyledButton>styled button</StyledButton>
<div />
<AddToCartBtn>styled link</AddToCartBtn>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/styled-components/dist/styled-components.min.js"></script>
<div id="root"/>

Related

ResizableBox is displaying nothing

I'm experimenting with react-resizable, but this extremely basic example will simply display the text XYZ in the browser, but will otherwise be blank with no error messages. I am expecting a resizable box.
import { ResizableBox } from 'react-resizable';
import 'react-resizable/css/styles.css';
ReactDOM.render(
<div>
<ResizableBox className="box" width={200} height={200} axis="y">
<span className="text">XYZ</span>
</ResizableBox>
</div>,
document.getElementById("root")
);
I derived this test case from the longer example here.
EDIT: And here is the codesandbox: https://codesandbox.io/s/suspicious-bogdan-08f01?file=/src/App.js
You can apply CSS styles with the className property. Here is a working example:
import React from "react";
import { ResizableBox } from "react-resizable";
import "react-resizable/css/styles.css";
import "./style.css";
const Box = () => {
return (
<ResizableBox
className="box borderBlack"
width={200}
height={200}
axis="y"
>
<span className="text">XYZ!!</span>
</ResizableBox>
);
};
export default Box;
style.css file:
.borderBlack {
border: 1px solid black;
}

How to override material-ui css with styled component?

I'm still a beginner with the ui-material. And I would like to custom my own Button Component with styled-component.
The problem is to override the css according to the button variations, for example if it is primary or secondary:
Here's my code into codesandbox.io
import React from "react";
import PropTypes from "prop-types";
import { CButton } from "./styles";
const CustomButton = ({ children, color }) => {
return (
<div>
<CButton variant="contained" color={color}>
{children}
</CButton>
</div>
);
};
CustomButton.propTypes = {
children: PropTypes.node,
color: PropTypes.oneOf(["primary", "secondary"])
};
export default CustomButton;
import styled, { css } from "styled-components";
import Button from "#material-ui/core/Button";
export const CButton = styled(Button)`
height: 80px;
${({ color }) =>
color === "primary"
? css`
background-color: green;
`
: color === "secondary" &&
css`
background-color: yellow;
`}
`;
import React from "react";
import CustomButton from "./CustomButton";
const App = () => {
return (
<div>
<div
style={{
marginBottom: "10px"
}}
>
<CustomButton color="primary">Primary</CustomButton>
</div>
<div>
<CustomButton color="secondary">Secondary</CustomButton>
</div>
</div>
);
};
export default App;
Could you tell me how I can get my styling to override the ui-material?
Thank you in advance.
It looks like there's a nice example on how to do this in the material-ui docs: https://material-ui.com/guides/interoperability/#styled-components
One thing you seem to be missing is the StylesProvider, which allows your styles to override the default material styles. This seems to work... I don't deal with the conditional in your example, but I don't think that's part of your problem here.
const MyStyledButton = styled(Button)`
background-color: red;
color: white;
`;
export default function App() {
return (
<StylesProvider injectFirst>
<div className="App">
<MyStyledButton color="primary">Foo</MyStyledButton>
</div>
</StylesProvider>
);
}
Here's a codesandbox: https://codesandbox.io/s/infallible-khorana-gnejy

React hooks - set state of Parent from child via function

guys I am just learning React and I decide to do try to build Hero Database and I encounter a problem.
When I click on any of Heroes, Bio state and Display state updates with data about the hero and modal window pop up with more information about him. But I don't know how to close it. I have Modal as a separate component and when I am trying calling the function (updateDisplay) from child component. which should set State of Display to False it just doesn't work :/
Heroes.js
import React, { useState } from "react";
import Hero from "./Hero";
import styled from "styled-components";
function Heroes(props) {
const [Bio, setBio] = useState([]);
const [Display, setDisplay] = useState(false);
const SingleHeroCont = styled.div`
display: flex;
flex-direction: column;
margin-top: 10px;
padding: 10px;
align-items: center;
`;
const content = props.data.map((Hero) => (
<SingleHeroCont
onClick={() => {
setBio(Hero);
setDisplay(true);
}}
key={Hero.id}
>
<h1>{Hero.name}</h1>
<img src={Hero.images.sm} alt="Sorry guys"></img>
</SingleHeroCont>
));
const updateDisplay = () => {
setDisplay(false);
};
return (
<div className="heroes_cont">
<Hero updateDisplay={updateDisplay} Display={Display} BioData={Bio} />
{content}
</div>
);
}
export default Heroes;
Hero.js
import React from "react";
import styled from "styled-components";
function Hero({ Display, updateDisplay, BioData }) {
const HeroAbsolute = styled.div`
display: ${(props) => (props.showBio ? "block" : "none")};
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(0, 255, 255, 0.5);
`;
return (
<HeroAbsolute showBio={Display}>
<div className="hero_bio_cont">
<h1>{BioData.name}</h1>
<button onClick={() => updateDisplay}>Close</button>
<div className="hero_bio_appearance">
<div>
<img></img>
<div>
<h2>{BioData.powerstats?.power}</h2>
<h2></h2>
<h2></h2>
</div>
</div>
</div>
</div>
</HeroAbsolute>
);
}
export default Hero;
<button onClick={() => updateDisplay}>Close</button>
As I see, the above code is not working to call updateDisplay function.
Correct usage would be
<button onClick={() => updateDisplay()}>Close</button>
Or
<button onClick={updateDisplay}>Close</button>
Please refer to the arrow function tutorial for the second case.

react styled components style inner elements

I have a problem on which I cannot find a simple solution. So this is my Header:
const Header = ({ title }) => {
return (
<div className={styles.Header}>
<h1>{title}</h1>
<button>
{EXIT}
</button>
</div>
);
};
How can I apply custom styles with styled-components for h1 and button elements? I tried
const CustomHeader = styled(Header)`
${h1} ${button}
`;
const h1 = styled(h1)`
max-width: 500px
`
const button = styled(button)`
padding-left: 100px
`
but this is not working, I get an error in terminal.
I also tried this:
return (
<CustomHeader>
<div className={styles.Header}>
<h1>{title}</h1>
<button>
{EXIT}
</button>
</div>
</CustomHeader>
);
};
const CustomHeader = styled(Header)`
h1 {
max-width: 500px;
}
button {
padding-left: 100px;
}
`;
Any help will be appreciated.
First you need to define styled component in your React function and create a wrapper like following:
// added demo css here for h1 tag, you can add your own
const CustomHeader = styled.div`
h1 {
font-family: Poppins;
font-size: 14px;
font-weight: 600;
font-stretch: normal;
font-style: normal;
line-height: 1.5;
letter-spacing: 0.02px;
text-align: left;
color: #0f173a;
}
`;
Then wrap your return inside the CustomHeader wrapper.
const Header = ({ title }) => {
return (
<CustomHeader>
<h1>{title}</h1>
<button>
{EXIT}
</button>
</CustomHeader>
);
};
You can add any tag inside CustomHeader that you want to customize.
You're almost there.
Its not working because you are setting className directly on div element of your Header component.
According to the styled-component documentation:
The styled method works perfectly on all of your own or any third-party components, as long as they attach the passed className prop to a DOM element.
https://styled-components.com/docs/basics#styling-any-component
So, in your case you need to:
const Header = ({ title, className }) => {
return (
<div className={className}>
<h1>{title}</h1>
<button>EXIT</button>
</div>
);
};
const CustomHeader = window.styled(Header)`
h1 {
max-width: 500px;
}
button {
padding-left: 100px;
}
`;
const App = () => {
return (
<React.Fragment>
<Header className='' title={"title"} />
<CustomHeader title={"title"} />
</React.Fragment>
);
};
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="//unpkg.com/styled-components#4.0.1/dist/styled-components.min.js"></script>
<div id="root"></div>
So, i set Header like this:
const Header = ({ title, className }) => {
return (
<div className={className}>
And where i did <Header className='' title={"title"} /> you can do like this:
<Header className={styles.Header} title={"title"} />
// Code
const Header = ({ title }) => {
return (
<Header>
<h1>{title}</h1>
<button>
{EXIT}
</button>
</Header>
);
};
// Styles
const Header = styled.div`
h1{
styles...
}
button{
styles...
}
`;

How to make resuable styled-components using Bootstrap4

I am new to styled-components and I really like the concept. However I face currently some difficulties when I try to refactor a Component with styled components. I have a bootstrap Card in which I compose some reusable Forms such as Text Inputs and Buttons. Simplified MyComponent.js looks like this:
const StyledCard = styled.div`
background: #008080;
color: white;
border-radius: 5px;
border: solid #008080;
`;
render() {
return(
<StyledCard classname = "card">
<article className="card-body">
<ButtonForm
name=''
label=''
/>
<form>
<TextInput
name=""
label=""
/>
</form>
</article>
</StyledCard>
);
}
};
This is working fine, however if I want to make the StyledCard reusable in a separate file (let´s call it CardForm.js) it doesn´t work as expected. CardForm.js:
const StyledCard = styled.div`
background: #008080;
color: white;
border-radius: 5px;
border: solid #008080;
`;
const CardForm = () => {
return (
<StyledCard className="card">
<article className="card-body">
</article>
</StyledCard>
);
};
export default CardForm
And then if CardForm is importet in MyComponent.js like so:
import CardForm from '../Templates/Card';
render() {
return(
<CardForm>
<ButtonForm
name=''
label=''
/>
<form>
<TextInput
name=""
label=""
/>
</form>
</CardForm>
);
}
};
It doesn´t Work meaning the other Form elements inside CardForm do not get rendered. What am i doing wrong here?
Try this for CardForm. Put children inside the article. Otherwise children will override article.
const CardForm = ({children}) => (
<StyledCard className="card">
<article className="card-body">
{children}
</article>
</StyledCard>
)

Categories

Resources