I use Styled-Components with React.
My code looks like this:
const StyledLink = styled.a<StyledProps>`
font-size: ${(props) => pxToRem(props.fontSize!)};
//disabled state
${(props) =>
props.disabled &&
css`
color: grey;
pointer-events: none;
`}
`
const Link = ({href, disabled, fontSize = 16, children}: Props) => {
return(
<StyledLink href={href} fontSize={fontSize} disabled={disabled}>{children}</StyledLink>
)
}
Everything works fine, however when I inspect my elements I see:
<a href="#" font-size="16" disabled>Some Link</a>
I want fontSize and disabled to be props that target only Styled-Components. I don't want them to applied for React element.
Is there a better way of doing that without changing props names to something like styledFontSize and styledDisabled?
styled-components provides transient props for those who wants to avoid property passing down to DOM or React node where the property name should have $ (dollar sign) prefix.
Using $ transient props:
const StyledLink = styled.a<StyledProps>`
font-size: ${(props) => pxToRem(props.$fontSize!)};
//disabled state
${(props) =>
props.$disabled &&
css`
color: grey;
pointer-events: none;
`}
`
const Link = ({href, disabled, fontSize = 16, children}: Props) => {
return(
<StyledLink href={href} $fontSize={fontSize} $disabled={disabled}>{children}</StyledLink>
)
}
Related
Is it possible to use the spread operator with a styled component in React Native?
I have this component:
const StyledHeaderText = styled.Text`
fontFamily: ${props => props.theme.font};
fontSize: ${props => props.theme.fontSizeSubtitle};
color: ${props => (props.lightMode) ? props.theme.fontColor : props.theme.fontPrimaryColor}
`;
But lets say that in my theme, I have an object that has both the fontFamily and the fontSize, and I re use all over the app. I would like to be able to know if I can do something like this, which currently it is not working:
const StyledHeaderText = styled.Text`
...${props => props.theme.fontHeader};
color: ${props => (props.lightMode) ? props.theme.fontColor : props.theme.fontPrimaryColor}
`;
This would be useful too setting up elevation in iOS for example, since I have to setup 4 styles.
Thanks
You can use the css helper function to generate the specific css and return it as a template literal.
import styled, {css} from 'styled-components/native'
const GlobalStyles = css`
fontFamily: ${props => props.theme.font};
fontSize: ${props => props.theme.fontSizeSubtitle};
`
const StyledHeaderText = styled.Text`
${GlobalStyles}
// Other Styles
`
or conditionally as
const StyledHeaderText = styled.Text`
${props => props.theme.fontHeader ? GlobalStyles : 'fontSize: 14'}
// Other Styles
`
In React.js you can use the spread operator override multiple styles
Here is a link to a code example
const StyledText = styled.div`
/* Normal styles */
color: blue,
background-color: white,
/* Fields to override with object from props */
${({ styleOverrides }) => ({ ...styleOverrides })}
`;
You can also return objects directly from interpolations function, and they'll be treated as inline styles.
const StyledHeaderText = styled.Text`
${props => ({...props.theme.fontHeader})};
color: ${props => (props.lightMode) ? props.theme.fontColor props.theme.fontPrimaryColor}
`;
or
const StyledHeaderText = styled.Text`
${props => props.theme.fontHeader};
color: ${props => (props.lightMode) ? props.theme.fontColor props.theme.fontPrimaryColor}
`;
for more details : reference
To expand on previous answers you can also do the following:
import styled, {css} from 'styled-components/native'
// with theme
const GlobalStyles = css`
fontFamily: ${ ({theme}) => theme.font };
fontSize: ${ ({theme}) => theme.fontSizeSubtitle };
`
// Without theme using inherited props
const GlobalStyles = css`
fontFamily: ${ ({font}) => font };
fontSize: ${ ({fontSizeSubtitle}) => fontSizeSubtitle };
`
// if you wanted it to be conditional
const GlobalStyles = css`
fontFamily: ${ ({font}) => font || 'roboto' };
fontSize: ${ ({fontSizeSubtitle}) => fontSizeSubtitle || '14px' };
`
const StyledHeaderText = styled.Text`
${GlobalStyles}
// Other Styles
`
// same can also be done with regular styled components:
export const HeaderText = styled.p`
fontSize: ${ ({fontSizeSubtitle}) => fontSizeSubtitle || '14px' };
`
// Useage would be in your component would be like:
import react from react;
import { HeaderText } from '../component/styles'
export const FooComponent = memo(({ destructuredProps }) => {
// some other code
return (
<>
<HeaderText className={fooClass} fontSize='18px'> Here's my sample text! </HeaderText>
<>
)});
I am new to styled components. In my React code I have some conditional rendering to change some CSS depending on if I scroll my navbar with the following code:
const [colorChange, setColorchange] = useState(false)
const changeNavbarColor = () => {
if (window.scrollY >= 80) {
setColorchange(true)
} else {
setColorchange(false)
}
}
window.addEventListener("scroll", changeNavbarColor)
<nav className={colorChange ? "navbar colorChange" : "navbar"}>content</nav>
My problem is to write the styled component for this to work.
My normal CSS looked like this:
.navbar {
/*styles...*/
}
.navbar.colorChange {
/*styles...*/
}
I started by creating the following with some styles:
const Navbar = styled.nav`
/*styles...*/
`
But how do I share the styles that are common for both navbar and colorChange; I tried appending the following to the NavBar styled component:
const Navbar = styled.nav`
/*styles...*/
.colorChange{
/*styles...*/
}
`
And then when rendering the component in React, how do I convert this line to use the styled components instead?
<nav className={colorChange ? "navbar colorChange" : "navbar"}>content</nav>
You need pass colorChange state to NavBar component.
This is NavBar declaration
const NavBar = styled.nav`
//styled for nav bar
color: ${props => props.color}
`
And use it in component
<NavBar color={colorChange ? '#fff':'#ddd'}>{children}</NavBar>
Just pass prop as dynamic value
const Navbar = styled.nav`
// navbar common css
color: ${({ color}) => color};
`
<Navbar color={colorChange ? 'red':'transparent'} />
as you commented you have multiple styles I suggest below approach just pass on prop for isColorChange
const Navbar = styled.nav`
font-size: 13px; //common style
background: ${props => (props.isColorChange ? "#6495ED" : "#2b2b2b")};
background-color: ${props => (props.isColorChange ? "#6495ED" : "#2b2b2b")};
margin-top: ${props => (props.isColorChange ? "10px" : "20px")};
padding-top: ${props => (props.isColorChange ? "5px" : "10px")};
padding-bottom: ${props => (props.isColorChange ? "5px" : "10px")};
`;
<Navbar isColorChange={true / false}></Navbar>;
I am trying to make a conditional icon with styled-components. But I need to pass props like function params. Because I need to change the icon with the condition.
export const RadioCheck = ({checked}) => styled(checked ? FaCheckCircle : FaRegCircle)`
display: flex;
align-self: center;
margin: 0 2em;
font-size: 1em;
color: ${props => props.checked ? primary : `transparent`}
`
Is there any way for this or I need to create two different components and use them?
Seems to me like you should use the condition where you return the icon to decide which component to use.
Something like
return(
<div>
{checked ?
<FaCheckCircle
//... your props
/>
:
<FaRegCircle
//... props
/>
}
</div>
)
If it's helpful to you, it is possible to style a styled component, such as
const FirstComponent = styled.div`
//some styling
`
const SecondComponent = styled(FirstComponent)`
//some more styling
`
I'm new to React, trying to integrate some animations. I'm using Gatsby.js framework.
const LeadHeading = styled(animated.h1)`
font-weight: bold;
font-size: 3rem;
font-family: ${props => props.theme.fontSecondary};
margin-bottom: 0;
line-height: 2.5rem;
color: #FFF3D8;
const IndexPage = ({menuOpen}) => {
const h1Animation = useSpring({
opacity: menuOpen ? '0' : '1'
})
return (
<>
<Layout>
<Section className="hero is-fullheight">
<div className="hero-body container is-flex">
<LeadHeading
style={h1Animation}
>
some heading
</LeadHeading>
</div>
</Section>
</Layout>
</>
)
}
export default IndexPage
The menu status is managed in the "layout" component via the useState hook.
const [menuOpen, setMenuOpen] = useState(false)
Basically, I just want to fadeout the h1 when the menu pops up, since it doesn't look good due to the transparency of the menu.
Appreciate your help.
const LeadHeading = styled(animated.h1)`
font-weight: bold;
font-size: 3rem;
font-family: ${props => props.theme.fontSecondary};
margin-bottom: 0;
line-height: 2.5rem;
color: #FFF3D8;
`
const IndexPage = ({menuOpen}) => {
const h1Animation = useSpring({
opacity: menuOpen ? '0' : '1'
})
return (
<>
<Layout>
<Section className="hero is-fullheight">
<div className="hero-body container is-flex">
<LeadHeading
style={h1Animation}
>
some heading....
</LeadHeading>
</div>
</Section>
</Layout>
</>
)
}
export default IndexPage
EDIT// The menu status is managed in the "layout" component via useState hook.
But it should be possible, to pass the data to "IndexPage" right?
Ok I thought I can skip the animated part in the render method, since I use it above in the styled component variable. (sry I forgot to mention that in my previous post).
Your approach was one of my first approaches but it didnt work.
Actually, I don't understand how to use {withTheme} in styled component and its usage also. So anyone gives proper code with using {withTheme} in styled component.
withTheme is helping you to reach theme variables from your component props. When you define a theme you can normally use them in styled components but if you define your component with withTheme HOC you can use those variables in your component.
// Define our button, with the use of props.theme
const Button = styled.button`
color: ${props => props.theme.fg};
border: 2px solid ${props => props.theme.fg};
background: ${props => props.theme.bg};
`;
// Define our button, but with the use of component.props
const ThemeButton = (props) => (
<button style={{background: props.theme.bg, color: props.theme.fg, border: `1px solid ${props.theme.fg}`}}>
{`this button is using: ${props.theme.fg} and ${props.theme.bg}`}
</button>
)
const ButtonWithTheme = withTheme(ThemeButton);
// Define our `fg` and `bg` on the theme
const theme = {
fg: "palevioletred",
bg: "white"
};
<ThemeProvider theme={theme}>
<div>
<Button>Default Theme</Button>
<ButtonWithTheme></ButtonWithTheme>
</div>
</ThemeProvider>
You can check in here https://codesandbox.io/s/zealous-sky-kgjqj?fontsize=14