React create one styled components for two different icons? - reactjs

So I am using react icons and I have two different icons that I am styling with styled components. My issue is that they essentially have the exact same styles, but the only difference is which icon I am choosing to style.
I don't know how to combine both icons into one styled component
Here is my code
const backArrow = styled(IoArrowBack)`
width: 50px;
height: 50px;
`;
const forwardArrow = styled(IoArrowForward)`
width: 50px;
height: 50px;
`;
Since I am using styled components, I just pass the icon into the () based on which one I want to style. The issue is I have over 12 lines of the exact same styles for both icons. It doesn't make sense to repeat the exact styles
How would I create one styled component, but display two different icons?
Example concept like this
const arrowIcon = styled(IoArrowBack, IoArrowForward)`
width: 50px;
height: 50px;
`
But then the issue occurs if I were to add them to my JSX
Cause then how would I even add the code?
I can't do
<arrrowIcon>Back arrow</arrowIcon>
<arrrowIcon>Forward arrow</arrowIcon>
So it wouldn't know which icon is which.
Is this even possible with styled components, or would I just have to copy and paste the same styles for each icon?

This piece of code is a bit weird to me, I think this is not a valid code
const arrowIcon = styled(IoArrowBack, IoArrowForward)`
width: 50px;
height: 50px;
`
However you can do a trick to get a shared style
const sharedIconStyle = css`
width: 50px;
height: 50px;
`
And
const styledArowBack= styled(IoArrowBack)`
${sharedIconStyle}
`
const styledArrowForward = styled(IoArrowForward)`
${sharedIconStyle}
`;

Could you just do it with React?
import React from "react";
import "./styles.css";
import { ReactComponent as icon1 } from "./icons/1.svg";
import { ReactComponent as icon2 } from "./icons/2.svg";
export default function App() {
return (
<div className="App">
<SizedIcon Icon={icon1} />
<SizedIcon Icon={icon2} />
</div>
);
}
const SizedIcon = ({ size = 50, Icon }) => {
console.log(typeof Icon);
return (
<div>
<Icon width={size} height={size} />
</div>
);
};

What I did is wrapped the icons in a div and styled the div, for example change the icon colors to red:
const IconStyles = styled.div`
color: red;
`
<IconStyles>
<IoArrowBack />
</IconStyles>
<IconStyles>
<IoArrowForward />
</IconStyles>
If you want to change the size of the icons then add a font-size in the div containing the icons, that is how I personally do it.

Related

React - Trying to pass SVG fill color as a prop while using svg as data in background image property?

I wish to dynamically change the fill color of a svg pattern that I'm using as a background image property in a container. I am doing this through using the data uri and directly injecting the SVG code as a value in a styled component. Currently it won't recognise the prop and the pattern just disappears. This works when I sue the fill color as a static value. Is it the way I wrote it?
Here some code -
import React, { useState } from "react";
import styled from "styled-components";
import './App.css';
const Container = styled.div`
height: 50vh;
width: 100%;
background-color: ${props => props.bg};
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='${props => props.color}' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3e%3c/svg%3e");
background-size: cover;
`;
function App() {
const [color, setColorChosen] = useState("green");
const [bgChosen, setbgChosen] = useState("yellow");
return (
<>
<Container bg={bgChosen} color={color}>
</Container>
</>
);
}
export default App;
I am not sure why it's not working for you, it works for me.
Are you using JS or TS? can I see the error message too?

Access props inside the styled component using MUI

I'm trying to create a custom button component using MUI on a React JS project. I've checked the docs and I discovered that I can do this using styled components. All worked well with the code presented below. The problem is that I want to create a more "customizable" component. I have inside my theme file 2 sets of colors (primary and secondary). The fact is that I want to create a button that is able to take a prop for this set of colors (primary / secondary).
import * as React from 'react';
import ButtonUnstyled, {
buttonUnstyledClasses,
ButtonUnstyledProps,
} from '#mui/core/ButtonUnstyled';
import { styled } from '#mui/system';
import { theme } from '../../theme';
const CustomButtonRoot = styled('button')(`
background-color: ${theme.palette[props.type].main};
padding: 15px 20px;
border-radius: 10px;
color: #fff;
`);
interface TodoButtonProps {
unstyledProps: ButtonUnstyledProps,
type?: 'primary' | 'secondary'
}
function CustomButton(props: TodoButtonProps) {
return <ButtonUnstyled {...props} component={CustomButtonRoot} />;
}
export default CustomButton
The question is: How I can include this prop inside the styled component code?
Pass a callback. In this callback the first argument is the props of the styled component. You can also use the style object instead of template string. More detail in this answer.
const CustomButtonRoot = styled("button")(
({ theme, myColor }) => `
padding: 15px 20px;
border-radius: 10px;
color: ${myColor};
`
);
<CustomButton myColor="red">abc</CustomButton>

Div with two syled components

I am pretty new to styled components, and I am trying to convert a site with vanilla css to styled components. My issue is that I have a div with with multiple classes, but I don't know how do to render my Gatsby frontend using styled components
For example the following snippet:
<div className="section-center hero-center">
</div>
I started by creating two styled components files like so:
import styled from "styled-components"
export const SectionCenter = styled.div`
width: 90vw;
margin: 0 auto;
max-width: 1170px;
`
and the second component:
import styled from "styled-components"
export const HeroCenter = styled.div`
height: 100%;
display: grid;
align-items: center;
`
In my Hero.js component I do my import statements
import React from "react"
import * as styled from '../styled'
const Hero = () => {
return (
<styled. SectionCenter>
<styled.HeroCenter>
// content goes here
</styled.HeroCenter>
</styled.SectionCenter >
)
}
export default Hero
This is what I have so far, but it's not the way the original div was, with one div having two styles. Is there another way to accomplish that? To have two styles on one div similar to vanilla css?
Styles can be extended. So if heroCenter is a custom version of SectionCenter, you can do something like:
import styled from "styled-components"
export const SectionCenter = styled.div`
width: 90vw;
margin: 0 auto;
max-width: 1170px;
`
export const HeroCenter = styled(SectionCenter)`
width: 100vw;
`
Then Hero.js can use just the HeroCenter component. More details in official docs.

utility classes in styled component react

hi I am using styled componant in react
const H4 = styled.h4`
font-size: 15px;
letter-spacing: 0.38px;
line-height: 1.33;
color: red;
padding: 20px;
`;
<H4>Small header</H4>
it will give exsact style in H4 tag. but how can I override this padding with utility classes like m-b-10 it will give margin-bottom:10px
something like this <H4 m-b-10>small header</H4>
same time I need to use this utility class whereever I want. in css I can simply write
m-b-10{margin-bottom:10px !important};
how can achieve this things on styled componenet?
One of the best solutions is to use https://styled-system.com/, it plays well with Styled Components and other libraries like Emotion and it offers what you need, to use utility-classes in the component definition.
Example:
import styled from 'styled-components'
import { color, space, fontSize } from 'styled-system'
// Set default styles and add styled-system functions to your component
const Box = styled.div`
/*defaut styles */
color: white;
font-size: 25px;
padding: 20px;
/* configurable properties */;
${color};
${space};
${fontSize};
`;
And to use it:
<Box bg="black" >
Lorem Ipsum
</Box>
<Box bg="black" color="green" fontSize="12px" p="10px">
Lorem Ipsum
</Box>
That code, will render this:
It also supports Media-Querys, Themes etc..
You can play with this CodeAndSandbox where it is been used with Styled Components https://codesandbox.io/s/styled-components-with-styled-system-njr17
You can use variables like
const m-b-10 = '20px';
const H4 = styled.h4`
padding: ${m-b-10};
`;
You can define such variables in a separate file and import them to styles components
You can define utility classes in the top component of your React tree. The example uses Gatsby.js, but you can easily adapt it for other React framework.
// src/components/layout.js
const GlobalStyles = createGlobalStyles`
html {
/* Put your CSS variables here*/
}
.m-b-10 {
margin-bottom: 10px;
}
`
Then make whatever defined in createGlobalStyles available for access in child components.
// src/components/layout.js
export default function Layout({ children }) {
return (
<React.Fragment>
<GlobalStyle />
{children}
</React.Fragment>
)
}
// src/pages.index.js
import Layout from "../components/layout"
const H4 = styled.h4`
font-size: 15px;
letter-spacing: 0.38px;
line-height: 1.33;
color: red;
padding: 20px;
`;
const IndexPage = () => {
return (
<Layout>
<H4 className="m-b-10" />
</Layout>
)
}

pass background url as prop to styled component

I have the following code:
// #flow
import React from 'react';
import { Route } from 'react-router-dom';
import Split from '../../components/grouping/Split';
import CenterBox from '../../components/grouping/CenterBox';
import styled from 'styled-components';
type Props = {
routes: Array<Object>,
background: String
};
export default ({ routes, background }: Props) =>
(<div>
<Split push="right" alignItems="center" height={50} pad={{ horizontal: 20 }}>
<div />
<div>This feature will be available soon!</div>
</Split>
<DashboardContent background={background}>
<CenterBox>
<div style={{ transform: 'translateY(50%)' }}>
<CenterBox height={300} width={500} backgroundColor="#FFFFFF">
This feature is not included as part of the design beta and will be available soon
</CenterBox>
</div>
</CenterBox>
</DashboardContent>
</div>);
const DashboardContent = styled.div`
background: url(${props => props.background}) no-repeat top
center;
background-size: 100%;
min-height: 100vh;
`;
I would like to pass background as a prop to my styled component so that when it is passed a link to an image file it sets it as a background, the code compiles but the background does not show up. What am I doing wrong?
Changing your background property to be a function that returns a string will fix your issue.
background: ${props => `url(${props.background}) no-repeat top center`};
Is this going to work out fine?
const DashboardContent = styled.div`
background: url(${props => props.background}) no-repeat top center;
`
<DashboardContent background={`https://xxxx/xxxx${background}`}/>
This worked for me!
import styled from 'styled-components';
import img from './img/background.gif';
const Content = styled.div`
background-image: url(${img});
`;

Resources