Reputation: 2004
I have a Button
component (in React) which can either be a button
or an a
element, depending on if a href
prop is passed to the component. Something similar to below:
const Button = ({ children, href, onClick }) => {
if(href) {
return <a href={href} onClick={onClick}>{children}</a>;
}
return <button type="button" onClick={onClick}>{children}</button>;
};
I previously used Sass to style these components, but am now attempting to move over to styled-components
. However, I have come across an issue where these two elements require the same styles, but the syntax of styled-components
would require me to create to separate variables - styled.button
and styled.a
, with duplicated styles for each.
I was wondering if there was a way of dynamically changing the element used in styled-components
, maybe based on props in the same way one can change individual CSS properties? I have attempted something along the lines of:
const StyledButton = styled((props) => props.href ? 'a' : 'button')`
...
`;
but no luck so far. Any advice would be greatly appreciated.
Upvotes: 7
Views: 11264
Reputation: 213
As in the other answers, you can create generic styles for this component, but from v4+, you can also use the as
property to make a single component polymorphic. (See polymorphic prop in Styled's documentation).
An example of this:
const SomeButton = styled.button`
border: red 1px solid;
`
function UsingSomeButtonAsALink(href) {
return <SomeButton as={'a'} href={href}>Text</SomeButton>
}
In older versions of Styled, there was a similar polymorphic ability via the .withComponent
API, but this was deprecated in v4 and removed completely in v6. The documentation no longer describes how to use this API.
Upvotes: 0
Reputation: 1
Using the css
helper is only justified when interpolating a function, not a string.
In your case, it is more reasonable to use the polymorphic props as
:
const Title = styled.h1`
...
`;
return (
<Title>Some title</Title>
<Title as='h2'>Some another title</Title>
)
Upvotes: 0
Reputation: 2604
I tried Joe Lloyd's answer but it didn't work because the function styled.xxx()
takes one parameter of type templateStringsArray
instead of template String
:
const buttonStyles = [
`
color: red;
...
`
]
const StyledA = styled.a(buttonStyles);
const StyledButton = styled.button(buttonStyles);
Upvotes: 0
Reputation: 22323
You can extract and pass styles as string args to a styled component.
const buttonStyles = `
color: red;
...
`
const StyledA = styled.a(buttonStyles);
const StyledButton = styled.button(buttonStyles);
import styled, { css } from ‘styled-components’;
const baseInputStyles = css`
padding: 0.5em;
`;
const StyledA = styled.a`
${baseInputStyles}
`;
const StyledButton = styled.button`
${baseInputStyles}
/* make changes as needed*/
`;
Upvotes: 15