I am writing a React application with styled components, creating a library of reusable components for my application, but I encounter the problem of inheritance between sister components when trying to give a property to a label that is next to my input when the input is required, but it does not work. I have tried with:
// Form.js
import { StyledLabel, StyledInput } from './styles.js'
<StyledLabel>Mi Label 1</StyledLabel>
<StyledInput required/>
// ./styles.js
import styled from 'styled-components'
export const StyledInput = styled.input`
border: 1px #dddd solid;
`
export const StyledLabel = styled.label`
font-size: 10px;
${StyledInput}['required'] + & {
&::after {
content: '*'
}
}
`
The result only returns the form without the *
Does anyone know how I can detect from Styled Components when an input has the required HTML attribute, and show the *
Pseudo-selectors in styled-components work just like they do in CSS. (or rather, Sass).
So you can do what you want this way:
const Wrapper = styled.div`
label {
&:after {
content: "${p => p.required && "*"}";
color: red;
}
}`;
const Form = () => {
return (
<Wrapper required>
<label>Mi Label 1</label>
<input />
</Wrapper>
);
};
But if you want don't want to pass props of the input element to its parent you can
do it this way:
const Wrapper = styled.div`
display: flex;
flex-direction: row-reverse;
align-items: center;
`;
const Example = styled.input`
+ label {
&:after {
content: "${p => p.required && "*"}";
color: red;
}
}
`;
const Form = () => {
return (
<Wrapper required>
<Example />
<label>My Label 1</label>
</Wrapper>
);
};
more info in resources:
Before and After pseudo classes used with styled-components
https://github.com/styled-components/styled-components/issues/388
https://github.com/styled-components/styled-components/issues/74
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/
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.
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...
}
`;
is it possible to make selector for child component prop in styled components?
<Accordion>
<Checkbox checked='false' />
<Text>Text to be hidden when checked is false</Text>
</Accordion>
I would like to access the prop something like this:
const Accordion = styled.div`
& > ${Checkbox}[checked='false'] ~ ${Text} {
display: none;
}
`;
Is it possible and if so, how should I do it?
You are trying to use Attribute selectors, so you need to define valid attributes on Checkbox component like data-*.
If you trying to use component's property, you have to lift the state up (see Text with "State from Parent").
const Checkbox = styled.div``;
const Text = styled.div``;
const Accordion = styled.div`
& > ${Checkbox}[data-checked="true"] ~ ${Text} {
color: palevioletred;
font-weight: 600;
&:last-child {
color: ${prop => (prop.checked ? `blue` : `orange`)};
}
}
& > ${Text}[title="example"]{
border: 1px solid black;
}
`;
const App = () => {
return (
<Accordion checked>
<Checkbox data-checked="true" checked="true">
I'm Check box
</Checkbox>
<Text title="example">With attr gives border</Text>
<Text>Without attr</Text>
<Text>State from Parent</Text>
</Accordion>
);
};
I am trying to add class names to a React Component to make it easier for me to customize that component using Styled Components. Here is a simplified outline of the component:
const SignupForm = props => (
<form>
<Input className="input" />
<Button className="button" />
</form>
)
And here is how I would like to use it:
import { SignupForm } from '../path/to/signup-form'
<Form />
...
const Form = styled(SignupForm)`
.input {
/* Custom Styles */
}
.button {
/* Custom Styles */
}
`
However, this does not work. Only if I create a wrapper Component will it work - like this:
import { SignupForm } from '../path/to/signup-form'
<FormWrapper>
<SignupForm/>
<FormWrapper>
...
const FormWrapper = styled.div`
.input {
/* Custom Styles */
}
.button {
/* Custom Styles */
}
`
I'm wondering whether or not there is a way to access the .input and .button classes without having to create a wrapper class, i.e. via the actual imported class itself? If so, how?
You need to provide className for the wrapper/container as styled-component injecting the styles through it:
const SignupForm = ({ className }) => (
<form className={className}>
<input className="input" />
<button className="button">Button</button>
</form>
);
const Form = styled(SignupForm)`
.input {
background-color: palegreen;
}
.button {
background-color: palevioletred;
}
`;
Just add extra atrribute className by using attrs to existing styled component.
const FormWrapper = styled.div.attrs({
className: 'SignupForm',
})`
.input {
/* Custom Styles */
}
.button {
/* Custom Styles */
}
`