How to use styled-components in React? - reactjs

Please forgive my confusion and newbiness. I'm trying to export a styled Button. Totally dazed and confused. Please help. I don't really want to export 2 buttons, as shown, but a single Button with the styles from the props, and the given styles as the default, I think :(
import React, {Component} from 'react'
import ReactDOM from 'react-dom'
import styled, { css } from 'styled-components'
export default class Button extends React.Component {
btn: Btn = (props) => {
styled.button`
border-radius: 3px;
padding: 0.25em 1em;
margin: 0 1em;
background: transparent;
color: palevioletred;
border: 2px solid palevioletred;
${props => props.primary && css`
background: palevioletred;
color: white;
`}
`
}
render(
<Btn>Normal Button</Btn>
<Btn primary>Primary Button</Btn>
)
}
And my App element in case it's relevant
import React, { Component } from 'react'
import 'containers/App.css'
import Button from 'components/Button'
export default class App extends Component {
render() {
return (
<div>
<p>
<Button primary="primary" label="Button Help" />
</p>
</div>
)
}
}

Define your Styled Button as follows
import React from 'react';
import styled, {css} from 'react-emotion';
const StyledButton = styled('button')`
border-radius: 3px;
padding: 0.25em 1em;
margin: 0 1em;
background: transparent;
color: palevioletred;
border: 2px solid palevioletred;
`;
const primary = css`
background: black;
color: white;
`;
export default class Button extends React.Component {
render() {
return (
<div>
<StyledButton className={this.props.primary && `${primary}`}>
{this.props.label}
</StyledButton>
</div>
);
}
}
and in app element use buttton as follows
import React, { Component } from 'react'
import 'containers/App.css'
import Button from 'components/Button'
export default class App extends Component {
render() {
return (
<div>
<p>
<Button label="Button Help" /> // for normal Styled Button
<Button primary label="Button Primary" /> // for Primary Styled Button
</p>
</div>
)
}
}

Related

Component content not imported when importing styled components

I am building a site using React and have decided to use Styled Components. I have a component that is styled with Styled Components and is receiving a prop from my homepage where I am using an instance of this component. I have the styling being pulled into the homepage, but it is not pulling in the content of the component. When if I just pull in the whole component it pulls in the content fine, but it doesn't allow me to pass the prop, but if I import the component styling it doesn't pull in the content of the component, but the prop passes properly. So I need some help with how to pull in the content and styling and get the prop to pass.
I am pretty new to Gatsby and Styled Components so thanks for any help.
My Component Code
import React from 'react'
import styled from "styled-components"
import { useStaticQuery, graphql } from 'gatsby'
export const WhyChooseSection = styled.section`
border-bottom: 1px solid var(--charcoal);
`
export const WhyChooseH2 = styled.h2`
display: ${(props) => props.displayH2};
text-align: center;
`
export const WhyChooseContent = styled.div`
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
width: 100%;
max-width: 1160px;
margin: 0 auto;
padding-top: 40px;
padding-bottom: 40px;
column-gap: 100px;
row-gap: 30px;
#media(min-width: 992px) {
justify-content: space-between;
column-gap: 0;
}
.why-icon {
width: 180px;
height: 145px;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 20px;
p {
margin-bottom: 0;
font-size: 19px;
font-weight: var(--font-bold);
}
}
`
export function WhyChooseIcons() {
const data = useStaticQuery(graphql`
{
whyChooseIcons: allWp {
nodes {
acfOptionsOfficeSettings {
whyChooseInteriorDetails {
whyChooseIcons {
whyChooseIconGraphic {
altText
id
sourceUrl
}
whyChooseIconTitle
}
}
}
}
}
}
`)
return (
<>
{data.whyChooseIcons.nodes.map((node, index) => (
<WhyChooseSection key={index}>
<WhyChooseH2>Why Choose Interior Details?</WhyChooseH2>
<WhyChooseContent>
{node.acfOptionsOfficeSettings.whyChooseInteriorDetails.whyChooseIcons && node.acfOptionsOfficeSettings.whyChooseInteriorDetails.whyChooseIcons.map((item) => (
<div className='why-icon' key={item.whyChooseIconGraphic.id}>
<img src={item.whyChooseIconGraphic.sourceUrl} alt={item.whyChooseIconGraphic.altText} />
<p>{item.whyChooseIconTitle}</p>
</div>
))}
</WhyChooseContent>
</WhyChooseSection>
))}
</>
)
}
export default WhyChooseIcons
My Homepage Code
import * as React from "react"
// import styled from "styled-components"
import { graphql } from 'gatsby'
import Seo from "../components/seo"
import Hero from '../components/heroComponent'
import { WhyChooseSection } from '../components/whyChooseIcons'
import { WhyChooseH2 } from '../components/whyChooseIcons'
import { WhyChooseContent } from '../components/whyChooseIcons'
import HomeProducts from '../components/homeProducts'
import HomeTestimonials from '../components/testimonials'
import HomeNewHomes from '../components/homeNewHomes'
import HomeFamilyTreatment from '../components/homeFamilyTreatment'
import HomeSolutions from '../components/homeSolutions'
import HomeMotorization from '../components/motorizationComps'
import HomeBrands from '../components/homeBrands'
import CTAOne from '../components/ctaOne'
const IndexPage = (hero) => {
const heroData = hero.data.homeHero
return (
<>
{heroData.edges.map(({ node }, index) => (
<Hero key={index} heroTitle={node.template.homePage.heroH1} heroSubTitle={node.template.homePage.heroParagraph} heroBg={node.template.homePage.heroBackground.gatsbyImage} heroBtnOneText={node.template.homePage.heroButton1Text} heroBtnOneURL={node.template.homePage.heroButton1Url} heroBtnTwoText={node.template.homePage.heroButton2Text} heroBtnTwoURL={node.template.homePage.heroButton2Url} />
))}
<WhyChooseSection>
<WhyChooseH2 displayH2="none"></WhyChooseH2>
<WhyChooseContent></WhyChooseContent>
</WhyChooseSection>
<HomeProducts />
<HomeTestimonials />
<HomeNewHomes />
<HomeFamilyTreatment />
<HomeSolutions />
<HomeMotorization />
<HomeBrands />
<CTAOne />
</>
)
}
export default IndexPage
export const Head = () => <Seo title="Home" />
export const HeroContent = graphql`
{
homeHero: allWpPage(filter: {template: {templateName: {eq: "Home Template"}}}) {
edges {
node {
template {
... on WpHomeTemplate {
homePage {
heroH1
heroParagraph
heroButton1Text
heroButton1Url
heroButton2Text
heroButton2Url
heroBackground {
gatsbyImage(placeholder: BLURRED, width: 1920)
altText
}
}
}
}
}
}
}
}
`
Since you only want to pass a prop into your <WhyChooseIcons> component and that the component itself renders its own content, there is no need to provide any children node to it in the consuming parent.
Simply update your <WhyChooseIcons> component to accept a prop that it will pass to its inner child. Let's name it displayH2 and we can simply pass it into the <WhyChooseH2> component by doing this: <WhyChooseH2 displayH2={displayH2}>. So your component definition now looks like this:
export function WhyChooseIcons({ displayH2 }) {
// Rest of the component logic here
return (
<>
{data.whyChooseIcons.nodes.map((node, index) => (
<WhyChooseSection key={index}>
<WhyChooseH2 displayH2={displayH2}>Why Choose Interior Details?</WhyChooseH2>
{/* Other content here */}
</WhyChooseSection>
))}
</>
)l
};
Then in the file where you consume this component, it is just a matter of passing "none" to the prop:
<WhyChooseSection displayH2="none">
HOWEVER this feel like a XY problem to me, because all you want is to control the conditional rendering of this component. What you can do is to create a prop on your component that determines whether <WhyChosseH2> should be rendered or not.
export const WhyChooseH2 = styled.h2`
text-align: center;
`
export function WhyChooseIcons({ shouldHideH2 }) {
return (
<>
{data.whyChooseIcons.nodes.map((node, index) => (
<WhyChooseSection key={index}>
{!shouldHideH2 && <WhyChooseH2>Why Choose Interior Details?</WhyChooseH2>}
{/* Other content here */}
</WhyChooseSection>
))}
</>
)
}
Then you can just control H2 rendering with a true/false boolean:
{/* To show it, just don't set the prop */}
<WhyChooseIcons />
{/* To hide it, both ways are valid */}
<WhyChooseIcons shouldHideH2 />
<WhyChooseIcons shouldHideH2={true} />

Can't style #mui Avatar icon with styled-components

I'm playing around with styled-components and having troubles working with material-ui. So thats the code:
import React from "react";
import styled from "styled-components";
import ChatIcon from "#mui/icons-material/Chat";
import MoreVertIcon from "#mui/icons-material/MoreVert";
import { Avatar} from "#mui/material";
function Sidebar() {
return (
<Container>
<Header>
<UserAvatar className={"override"} />
<IconsContainer>
<IconButton>
<ChatIcon />
</IconButton>
<IconButton>
<MoreVertIcon />
</IconButton>
</IconsContainer>
</Header>
</Container>
);
}
export default Sidebar;
const Container = styled.div``;
const Header = styled.div`
display: flex;
position: sticky;
top: 0;
background-color: white;
z-index: 1;
justify-content: space-between;
align-items: center;
padding: 15px;
height: 80px;
border-bottom: 1px solid whitesmoke;
`;
const UserAvatar = styled(Avatar)`
height: 60px;
`;
const IconsContainer = styled.div`;
The styled div is working completely fine, but when I import 'Avatar' from #mui and try to add some styling named UserAvatar, it is completely ignoring what I'm writing down.
I think that with mui they have their own version of styled for styled components. https://mui.com/system/styled/
It appears they want you to use it rather than styled-components
import Button from '#mui/material/Button';
import { styled } from '#mui/material/styles';
const CustomButton = styled(Button)({
// your custom styles go here
}) as typeof Button;
see the import from import { styled } from '#mui/material/styles';;

How to add style to a component with styled component react?

I'm trying to add style to a component.
It works fine with a component imported from the material-ui library, but it doesn't work when it comes to my original component(that is not used in any library).
Here is the code for style with styled-component
import styled from "styled-components";
import List from "./List";
import AcUnitIcon from "#mui/icons-material/AcUnit";
export const ListCotainer = styled(List)` // doesn't apply style
margin: 100px;
color: pink;
`;
export const Container = styled.div` // applies style
font-family: sans-serif;
text-align: center;
background-color: red;
`;
export const Icon = styled(AcUnitIcon)` // applies style
background-color: blue;
margin: 100px;
padding: 20px;
${Container}:hover & {
background-color: green;
}
`;
App.js
import { ListCotainer, Container, Icon } from "./styles";
export default function App() {
return (
<Container>
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<ListCotainer />
<Icon />
</Container>
);
}
List.js (regular component with no library)
import React from "react";
const List = () => {
return (
<div>
<h1>Hello styled component</h1>
</div>
);
};
export default List;
Is there any way I can add style to the List component?
you need to create styled CSS same as you have created for Container in your App.js. i have update your code it should work for you.
styles.js
import styled from "styled-components";
import AcUnitIcon from "#mui/icons-material/AcUnit";
export const ListCotainer = styled.div`
margin: 100px;
width: 200px;
color: pink;
`;
export const Container = styled.div`
font-family: sans-serif;
text-align: center;
background-color: red;
`;
export const Icon = styled(AcUnitIcon)`
background-color: blue;
margin: 100px;
padding: 20px;
${Container}:hover & {
background-color: green;
}
`;
List.js
import React from "react";
import { ListCotainer } from "./styles";
const List = () => {
return (
<ListCotainer>
<h1>Hello styled component</h1>
</ListCotainer>
);
};
export default List;
App.js
import { Container, Icon } from "./styles";
import List from "./List";
export default function App() {
return (
<Container>
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<List />
<Icon />
</Container>
);
You may not be able to style like this component and what you are applying to the style material component is a svg/icon that you can apply to icons and img with style components.
style.js
import styled from "styled-components";
import AcUnitIcon from "#mui/icons-material/AcUnit";
export const ListCotainer = styled.div`
margin: 100px;
width: 200px;
color: pink;
`;
export const Container = styled.div`
font-family: sans-serif;
text-align: center;
background-color: red;
`;
export const Icon = styled(AcUnitIcon)`
background-color: blue;
margin: 100px;
padding: 20px;
${Container}:hover & {
background-color: green;
}
`;
App.js
import { Container, Icon } from "./styles";
import List from "./List";
export default function App() {
return (
<Container>
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<List />
<Icon />
</Container>
);
}
List.js
import React from "react";
import { ListCotainer } from "./styles";
const List = () => {
return (
<ListCotainer>
<h1>Hello styled component</h1>
</ListCotainer>
);
};
export default List;

React input and label not displaying in browser

I am new to coding with React and having trouble displaying my form. I am especially having problems displaying the label and input in the browser, only the topbar and logo displays. There are also no errors in the console. I would really appreciate any advice on how to fix this problem.
Form.js:
import React, { Component } from 'react';
import classes from './Form.module.css';
class Form extends Component {
constructor(props) {
super(props);
this.state = {
username: ''
};
}
handleUsernameChange = (event) => {
this.setState({
username: event.target.value
});
};
render() {
return (
<div className={classes.Form}>
<label>Username</label>
<input
type="text"
value={this.state.username}
onChange={this.handleUsernameChange}
></input>
</div>
);
}
}
export default Form;
Form.module.js:
.input{
outline: none;
padding: 16px 22px;
border: 1px solid #dadce0;
font-size:18px;
border-radius:5px;
}
.input:focus{
border: 2px solid royalblue;
}
.label{
color: #8d8d8d;
position: absolute;
top: 27px;
left: 55px;
background: #ffffff;
transition: 300ms;
transform: translate(-50%, -50%)}
App.js
import React from 'react';
import './App.css';
import Topbar from './Topbar';
import Form from './Form';
function App() {
return (
<div className="App">
<Topbar />
<Form />
</div>
);
}
export default App;
Thanks in advance!
I changed the contents in Form.module.js to
.Form > input{
.Form > label{
and now both the label and input displays in the browser.

Why my styled component not work with text-decoration?

I'm trying to remove underline for my Link in react by using styled-components
if I use style={{textDecoration: "none"}} it will work but when I use text-decoration: none; in my styled components it won't work:
here is my js code:
import React from "react";
import styled from "styled-components";
import { Link } from "#reach/router";
import { CSSTransition, TransitionGroup } from "react-transition-group";
const StyleNavbarContainer = styled.nav`
background-color: #333333;
width: 100%;
color: #d6d6d6;
position: fixed;
text-align: center;
top: 0;
`;
const AppleLogo = styled.div`
font-size: 20px;
display: inline-block;
`;
const StyleLinkList = styled.ul`
display: inline-block;
`;
const StyledLink = styled(Link)`
padding: 12px 10px;
color: #d6d6d6;
text-decoration: none;
`;
const Navbar = (props) => {
return (
<>
<StyleNavbarContainer>
<AppleLogo>
<i class="fab fa-apple"></i>
</AppleLogo>
<StyleLinkList>
<StyledLink to="/">Mac</StyledLink>
</StyleLinkList>
</StyleNavbarContainer>
</>
);
};
export default Navbar;
add my App.jsx file here is the code:
import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import Navbar from "./components/Navbar";
function App() {
return (
<div className="App">
<Navbar />
</div>
);
}
export default App;
Need to remove import "bootstrap/dist/css/bootstrap.min.css"; from App.jsx

Resources