Focus on naming is very important.
Styled components as the name suggests are for styling the native DOM elements or custom components.
attrs is for mentioning the attributes of that very same DOM element in the attrs constructor without the need to even mention it in actual component call.
What above line means is you can do
<Input placeholder="A small text input" />
with
const Input = styled.input.attrs(({ type }) => ({
type: type || "password"
}))`
align-items: center;
display: flex;
margin: 1.5vh 0;
`
See that component usage <Input .../> doesn't have type prop anywhere. It came from your attribute constructor function(static)
You couldn't have done this otherwise in your style rules because these are just the string literal of your CSS properties.
It saved you from writing type='password' in every usage of
<Input type='password' ... />
Bonus:
Now, that's a specific input component with type attribute of password. What if you wish to have a general input (styled component) with any value of type attribute?
Tada!
const Input = styled.input.attrs(({ type }) => ({
type: type || "password",
...
Your type is now dynamic i.e. it will take whatever input type prop you specify from your usage of component and render the input as that type (text, password, file etc. ) or if you skip the type prop it will pick up default of password. You can use as much conditional logic as you want up there.
Example:
<Input .../> // renders type="password"
<Input type="text" .../>
<Input type="email" .../>
Hope that answers your question.
Answer from HalfWebDev on Stack OverflowFocus on naming is very important.
Styled components as the name suggests are for styling the native DOM elements or custom components.
attrs is for mentioning the attributes of that very same DOM element in the attrs constructor without the need to even mention it in actual component call.
What above line means is you can do
<Input placeholder="A small text input" />
with
const Input = styled.input.attrs(({ type }) => ({
type: type || "password"
}))`
align-items: center;
display: flex;
margin: 1.5vh 0;
`
See that component usage <Input .../> doesn't have type prop anywhere. It came from your attribute constructor function(static)
You couldn't have done this otherwise in your style rules because these are just the string literal of your CSS properties.
It saved you from writing type='password' in every usage of
<Input type='password' ... />
Bonus:
Now, that's a specific input component with type attribute of password. What if you wish to have a general input (styled component) with any value of type attribute?
Tada!
const Input = styled.input.attrs(({ type }) => ({
type: type || "password",
...
Your type is now dynamic i.e. it will take whatever input type prop you specify from your usage of component and render the input as that type (text, password, file etc. ) or if you skip the type prop it will pick up default of password. You can use as much conditional logic as you want up there.
Example:
<Input .../> // renders type="password"
<Input type="text" .../>
<Input type="email" .../>
Hope that answers your question.
The goal of .attrs is so it can be passed down from your props. So you can use props inside your styled, and you can create placeholders, or change colors depending of the props etc...
For example :
const InputText = styled.input.attrs({
type: 'text',
placeholder: props => props.placeholder || 'Please fill',
})`
padding: 6px 12px;
`;
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 */
}
`
You can remove the className prop and add a prop isIndented={props.linkIndentHome} props.linkIndentHome is a bool that holds true or false, to represent if its indented or not.
Pass the prop to the Li component and use it there to take the decision. Something like as follow:
const Li = styled.li`
border-bottom: 1px dotted #D3D3D3;
text-indent: 3rem;
...other styles
${props => props.isIndented && `
border-bottom: 1px dotted
...whatever other styles for indentation
`}
`
if you want default className use this , in my case my project was typescript too so i had too specify types too
let Container = styled.div.attrs<LayoutProps|
SpaceProps|HTMLAttributes<any>>(props=>{
return {className: `${props.className} container`}
})`
${layout}
${flex}
${space}