I'm using styled-components with styled-icons. I have:
import { Facebook } from 'styled-icons/feather/Facebook'
import { Twitter } from 'styled-icons/feather/Twitter'
import { Instagram } from 'styled-icons/feather/Instagram'
...
const FacebookIcon = styled(Facebook)`
width: 10px;
color: black;
`
const TwitterIcon = styled(Twitter)`
width: 10px;
color: black;
`
const InstagramIcon = styled(Instagram)`
width: 10px;
color: black;
`
...
render () {
return (
<Fragment>
<FacebookIcon />
<TwitterIcon />
<InstagramIcon />
</Fragment>
)
}
What would be a good way to DRY out this code?
So I can use these icons like:
<Icon name='Facebook' />
or
{ renderIcon(Facebook) }
You could do this:
import React from "react";
import ReactDOM from "react-dom";
import styled from "styled-components";
import { Facebook } from "styled-icons/feather/Facebook";
const IconWrapper = styled.div`
width: 10px;
color: black;
`;
const App = () => {
return (
<React.Fragment>
<IconWrapper>
<Facebook />
</IconWrapper>
</React.Fragment>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
CodeSandbox here.
Related
I have a webpage that looks like this:
This is my _app.tsx file:
import '../styles/globals.css'
import type { AppProps } from 'next/app'
import { createTheme } from '#arwes/design'
import { ThemeProvider, Global, css } from '#emotion/react'
import { globalStyles } from '../shared/styles.js'
function MyApp({ Component, pageProps }: AppProps) {
const theme = createTheme();
return (
<ThemeProvider theme={theme}>
{globalStyles}
<div style={{
marginBottom: theme.space(2),
borderBottom: `${theme.outline(2)}px solid ${theme.palette['primary'].main}`,
padding: theme.space(2),
backgroundColor: theme.palette.neutral.elevate(2),
textShadow: `0 0 ${theme.shadowBlur(1)}px ${theme.palette['primary'].main}`,
color: theme.palette['primary'].main
}}>
Futuristic Sci-Fi UI Web Framework
</div>
<Component {...pageProps} />
</ThemeProvider>
)
}
export default MyApp
And this is shared/styles.js:
import { css, Global, keyframes } from '#emotion/react'
import styled from '#emotion/styled'
export const globalStyles = (
<Global
styles={css`
html,
body {
margin: 0;
background: papayawhip;
min-height: 100%;
font-size: 24px;
}
`}
/>
)
export const blueOnBlack = (theme) => css`
marginBottom: ${theme.space(2)};
borderBottom: ${theme.outline(2)}px solid ${theme.palette['primary'].main};
padding: ${theme.space(2)};
backgroundColor: ${theme.palette.neutral.elevate(2)};
textShadow: 0 0 ${theme.shadowBlur(1)}px ${theme.palette['primary'].main};
color: ${theme.palette['primary'].main};
`
Notice that blueOnBlack is an attempt to put the Futuristic Sci-Fi UI Web Framework style into its own importable variable.
The problem is that when I put blueOnBlack into the _app.tsx as the style for the Futuristic Sci-Fi UI Web Framework div tag, it fails.
This is _app.tsx with blueOnBlack imported:
import '../styles/globals.css'
import type { AppProps } from 'next/app'
import { createTheme } from '#arwes/design'
import { ThemeProvider, Global, css } from '#emotion/react'
import { globalStyles, blueOnBlack } from '../shared/styles.js'
function MyApp({ Component, pageProps }: AppProps) {
const theme = createTheme();
return (
<ThemeProvider theme={theme}>
{globalStyles}
<div style={blueOnBlack(theme)}>
Futuristic Sci-Fi UI Web Framework
</div>
<Component {...pageProps} />
</ThemeProvider>
)
}
export default MyApp
The resulting webpage looks like this,
It's almost right... but it dropped the background color. Why is it different?
I changed shared/styles.js from:
import { css, Global, keyframes } from '#emotion/react'
import styled from '#emotion/styled'
export const globalStyles = (
<Global
styles={css`
html,
body {
margin: 0;
background: papayawhip;
min-height: 100%;
font-size: 24px;
}
`}
/>
)
export const blueOnBlack = (theme) => css`
marginBottom: ${theme.space(2)};
borderBottom: ${theme.outline(2)}px solid ${theme.palette['primary'].main};
padding: ${theme.space(2)};
backgroundColor: ${theme.palette.neutral.elevate(2)};
textShadow: 0 0 ${theme.shadowBlur(1)}px ${theme.palette['primary'].main};
color: ${theme.palette['primary'].main};
`
to this:
import { css, Global, keyframes } from '#emotion/react'
import styled from '#emotion/styled'
export const globalStyles = (
<Global
styles={css`
html,
body {
margin: 0;
background: papayawhip;
min-height: 100%;
font-size: 24px;
}
`}
/>
)
export const blueOnBlack = (theme) => styled.div={
marginBottom: theme.space(2),
borderBottom: theme.outline(2) + 'px solid' + theme.palette['primary'].main,
padding: theme.space(2),
backgroundColor: theme.palette.neutral.elevate(2),
textShadow: '0 0 ' + theme.shadowBlur(1) + 'px ' + theme.palette['primary'].main,
color: theme.palette['primary'].main
}
And then it ran and gave me the correct styling including the black background on the text. Notice that I'm using styled.div instead of css
I'm using styled-components with react. When I tried importing my component into my App.js. It gives an Uncaught Error of an undefined component.
Here is my styled-component, Header.js:
import React from "react";
import styled from "styled-components";
import { ReactComponent as LogoSVG } from "./logo.svg";
export const Logo = styled(LogoSVG)`
height: auto;
max-width: 760px;
width: 100%;
`;
export const Header = styled.header`
box-sizing: border-box;
display: flex;
pointer-events: none;
position: fixed;
width: 100vw;
z-index: 1;
justify-content: center;
padding: 30px;
`;
const HeaderComponent = () => (
<Header>
<Logo title="LavaLab Logo "/>
</Header>
);
export default HeaderComponent;
Here is App.js where I import my component:
import React from "react";
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { GlobalStyle } from "./styles.js";
import HeaderComponent from "./Components/Header";
const App = () => {
return (
<div>
<GlobalStyle />
<HeaderComponent />
</div>
);
};
const root = createRoot(document.getElementById("root"));
root.render(
<StrictMode>
<App />
</StrictMode>
);
This is the updated error.
Am I missing something?
NavStyles.js
import styled from 'styled-components';
export const Nav = styled.navwidth: 100%; ;
export const NavMenuMobile = styled.ul`
height: 80px;
.navbar_list_class {
font-size: 2rem;
background-color: red;
}
${props => props.navbar_list_props && `
font-size: 2rem;
background-color: gray;
`}
`;
Navbar.js
import React from 'react'
import {Nav, NavMenuMobile} from "./NavStyles";
const Navbar = () => {
return (
<Nav>
{/* work no problem */}
<NavMenuMobile navbar_list_props>Nav Bar props</NavMenuMobile>
{/* not work How to use..? */}
<NavMenuMobile className="navbar_list_class">Nav Bar class</NavMenuMobile>
</Nav>
)
}
export default Navbar
<Nav>
<NavMenuMobile className={navbar_list_props}>Nav Bar props</NavMenuMobile>
</Nav>
Try This
Looks like you are setting styles for the children within NavMenuMobile with the class "navbar_list_class".
Should work with &.navbar_list_class
export const NavMenuMobile = styled.ul`
height: 80px;
&.navbar_list_class {
font-size: 2rem;
background-color: red;
}
`;
I'm actually having trouble doing CSS with the styled component in React. Given below is the code snippet
import React from 'react';
import { Navbar, Container, Row, Col } from 'reactstrap';
import styled from 'styled-components';
const Styles = styled.div`
.navbar {
background-color: black;
position: absolute;
bottom: 0;
width: 100%;
}
.h1 {
color: white;
}
`;
const Footer = () => {
return (
<Styles>
<Navbar>
<Container>
<Row>
<Col sm={{ size: 4 }}>
<h1>Hi</h1>
</Col>
</Row>
</Container>
</Navbar>
</Styles>
);
};
export default Footer;
What I want to do is to change the color of the h1 tag to white but the above custom CSS is not working. I've tried background-color too, but still the issue persists.
With styled-components, you shouldn't use classes for styling elements. You should use separated wrappers for components, it's the main point. I think you wanted to do something like this:
import React from 'react';
import { Navbar, Container, Row, Col } from 'reactstrap';
import styled from 'styled-components';
const StyledNavbar = styled(Navbar)`
background-color: black;
position: absolute;
bottom: 0;
width: 100%;
`;
const Header = styled.h1`
color: white;
`;
const Footer = () => {
return (
<StyledNavbar>
<Container>
<Row>
<Col sm={{ size: 4 }}>
<Header>Hi</Header>
</Col>
</Row>
</Container>
</StyledNavbar>
);
};
export default Footer;
you used .h1 the class, not h1 the tag, in your css.
https://styled-components.com/docs/basics#pseudoelements-pseudoselectors-and-nesting
I have button.js:
import React from "react";
import styled from "styled-components";
const StyledButton = styled.TouchableOpacity`
border: 1px solid #fff;
border-radius: 10px;
padding-horizontal: 10px;
padding-vertical: 5px;
`;
const StyledButtonText = styled.Text`
color: #fff;
font-size: 12;
`;
export default ({ children }) => (
<StyledButton>
<StyledButtonText>{children.toUpperCase()}</StyledButtonText>
</StyledButton>
);
And its usage:
import React, { Component } from "react";
import styled from "styled-components";
import Button from "./button";
const StyledNavView = styled.View`
justify-content: flex-end;
flex-direction: row;
background: #000;
padding-horizontal: 10px;
padding-vertical: 10px;
`;
const StyledTodayButton = styled(Button)`
margin: 10px;
`;
export default class Nav extends Component {
render() {
return (
<StyledNavView>
<StyledTodayButton>Today</StyledTodayButton>
<Button>Previous</Button>
</StyledNavView>
);
}
}
Problem is, the margin I apply in StyledTodayButton is actually never applied. Have I misunderstood extending styles in Styled Components?
There are 2 ways to make it work:
extend button style:
const StyledTodayButton = Button.extend'margin: 10px'
pass prop to button:
const Button = styled.button'
/* ...your props */
margin: ${props => props.withMargin ? '10px' : '0px'};
and then call in render method you can invoke it with:
<Button withMargin {...restProps} />