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>
)
Related
I have a bunch of grids which I would like to form them a way as I intended to do. Here is a picture of how they look now:
What I would like to do is to move "CL1" and "Author" in parallel but after "commiter 1". And then followed by "CL2" and "CL3" in linear order like they are now. My code is as following:
import { React } from "react";
import styled from "styled-components";
function App() {
return (
<>
<Input placeholder="commiter 1" />
<Input placeholder="Author" size="2em" />
<div>
<Input placeholder="CL1" />
</div>
<Input placeholder="CL2" />
<Input placeholder="CL3" />
</>
);
}
export default App;
const Input = styled.input.attrs(props => ({
// we can define static props
type: "text",
size: props.size || "1em",
}))`
color: palevioletred;
font-size: 1em;
border: 2px solid palevioletred;
border-radius: 3px;
margin: ${props => props.size};
padding: ${props => props.size};
`;
I am just started with CSS styling, and trying with styled-component as of now. Any idea on which tutorial I should look up into, or suggestions to other CSS tool would be appreciated as well!
something like styled you should use when styles a dynamically, when you don't now size of some images or same problem. In casual situation you should use .css/scss file.
And check this https://css-tricks.com/snippets/css/a-guide-to-flexbox/
I am creating 3 cards and I need you to be able to select one of them and it has a div inside when I select it and change the css, the example that I have the selected card is the second one and I would like the same to happen with the others but that only one can be selected at the same time
import React from "react";
import "./styles.css";
export default function App() {
return (
<div className="App">
<div className="card"></div>
<div className="card cardSelect">
<div className="select">select</div>
</div>
<div className="card"></div>
</div>
);
}
.card {
width: 5rem;
height: 5rem;
background: red;
margin: 1rem;
}
.cardSelect {
box-shadow: 2px 4px 30px 0px rgba(0, 0, 0, 0.75);
}
You can achieve this using an orchestrator, or a parent component.
I have created you a simpler example at code sandbox
The active card needs to be controlled from a higher instance. In this case it is the App component it self. But you can create a Cards and Card component to encapsulate it. e.g.
<Cards>
<Card />
<Card />
<Card />
</Cards>
Here is the code of the example in the code sandbox:
import React from "react";
import "./styles.css";
const cardStyle = {
width: "5rem",
height: "5rem",
background: "red",
margin: "1rem"
};
const cardSelect = {
boxShadow: "2px 4px 30px 0px rgba(0, 0, 0, 0.75)"
};
export default function App() {
const [selected, setSelected] = React.useState(0);
return (
<div className="App">
<div
style={{ ...cardStyle, ...(selected === 0 && cardSelect) }}
onClick={() => setSelected(0)}
>
{selected === 0 && <div className="select">select</div>}
</div>
<div
style={{ ...cardStyle, ...(selected === 1 && cardSelect) }}
onClick={() => setSelected(1)}
>
{selected === 1 && <div className="select">select</div>}
</div>
<div
style={{ ...cardStyle, ...(selected === 2 && cardSelect) }}
onClick={() => setSelected(2)}
>
{selected === 2 && <div className="select">select</div>}
</div>
</div>
);
}
What you need to do is to
Add a state in the app level selection somewhere, eg. `const [selection, setSelection] = useState('card-0')
Create a component for cards, e.g.
Render that component three times <CardComponent isSelected={selection === 'card-2'} />`
Inside Cardcomponent, add that class only if it is selected. className={"card " + prop.isSelected ? "cardSelect" : ""}
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...
}
`;
I am currently working on a shopping cart and I am trying to figure out how to have the modal appear once I click on the shopping cart icon. I have looked at the documentation for the semantic-ui for modals but it is vague as to how to get the modal to appear when clicking on something. I am using the semantic-ui class="ui modal" for the modal.
I was thinking of putting an onClick on the icon but was still confused as to how to go from there. Currently, I have the icon in another component and the shopping cart in another separate component. I want the items to appear inside of the pop-up modal which should be the shopping cart.
import React from 'react'
import { Icon } from 'semantic-ui-react';
const ShoppingCartIcon = () => {
return(
<Icon.Group size='big' className="shopping_cart_icon">
<Icon link name='shopping cart'/>
<Icon corner='top right'/>
</Icon.Group>
)
}
export default ShoppingCartIcon;
import React from 'react'
import Shirt from './Shirt';
class ShoppingCart extends React.Component {
render() {
const listShirts = this.props.shirts.map(shirt => {
return <Shirt key={shirt.id} {...shirt}/>
})
return(
<div className="ui modal">
<div className="content">
{listShirts}
</div>
</div>
)
}
}
export default ShoppingCart;
Currently, I do not have the functionality for adding items to the cart working yet. I just want to focus on getting the modal to show up once I click on the shopping cart icon
as far as I see, you are not using neither redux nor context api. you are passing props with props drilling.
so this is how you should organize your code step by step.
we render cartIcon component in the header.js. here is a classic header
Header.js
import CartDropdown from "../cart-dropdown/cart-dropdown.component";
class Header extends React.Component {
constructor(props) {
super(props);
state = { hidden: true, cartItems:[]};
}
toggleHidden() {
this.setState(() => ({ hidden: !this.state.hidden }));
}
render() {
return (
<div className="header">
<Link className="logo-container" to="/">
<Logo className="logo" />
</Link>
<div className="options">
<Link className="option" to="/shop">
SHOP
</Link>
<Link to="/contact" className="option">
CONTACT
</Link>
{/* <Link></Link> */}
<CartIcon />
</div>
{hidden ? null : (
<CartDropdown
toggle={this.toggleHidden}
cartItems={this.state.cartItems}
></CartDropdown>
)}
</div>
);
}
}
you said you have not set the addItem functionality yet. as you add items to the cartItems array you will display them in the cart.
now we need to set up the cartDropdown component.
const CartDropdown = ({ cartItems, toggleHidden }) => (
<div className="cart-dropdown">
<div className="cart-items">
{cartItems.length ? (
cartItems.map(item => <CartItem key={item.id} item={item} />)
) : (
<span className="empty-message"> Your cart is empty </span>
)}
</div>
<CustomButton
onClick={() => {
toggleHidden();
}}
>
GO TO CHECKOUT
</CustomButton>
</div>
);
here we need to add css for cartDropdown. I do not how you are dealing with your css. prop-types or scss but here is the css code so you can apply to your project.
css for cartDropdown component
.cart-dropdown {
position: absolute;
width: 240px;
height: 340px;
display: flex;
flex-direction: column;
padding: 20px;
border: 1px solid black;
background-color: white;
top: 80px;
right: 0;
z-index: 5;
.cart-items {
height: 240px;
display: flex;
flex-direction: column;
overflow: scroll;
}
.empty-message {
font-size: 18px;
margin: 50px auto;
}
button {
margin-top: auto;
}
}
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"/>