What I did:
I'm passing some props to functional component Stat.jsx.
What I expected:
I need to pass some background gradient color codes as a string type prop to the Stat.jsx component to make custom color elements.
What happened:
Props aren't passing to the Stat.jsx, also props object is empty.
Stat.jsx
import React from 'react';
import styled from 'styled-components';
const Stat = styled.div`
display: flex;
align-items: center;
justify-content: center;
padding: 0 2.5em;
width: auto;
height: 2.5em;
border-radius: 0.5em;
box-shadow: 0 5px 25px rgba(0, 0, 0, 0.2);
background: linear-gradient(160deg, ${(props) => console.log(props) });
font-size: 1.8em;
font-family: Rubik-Medium;
color: #fff;
`;
// console.log(props) is returning object: { children: "1000", theme: {} }
export default ({ value }) => <Stat>{value}</Stat>;
Stats.jsx
import React from 'react';
import Stat from './Stat';
import styled from 'styled-components';
const Stats = styled.div`
display: flex;
`;
export default () => (
<div>
<Stats>
<Stat value="1000" background="#F4D03F, #16A085" />
</Stats>
</div>
);
Quick Fix
Because you don't pass the background prop to the actual Stat component:
export default (props) => <Stat {...props}>{props.value}</Stat>;
Explanation
A better way to illustrate the issue is by renaming your components:
import React from 'react';
import styled from 'styled-components';
const StyledStat = styled.div`
display: flex;
align-items: center;
justify-content: center;
padding: 0 2.5em;
width: auto;
height: 2.5em;
border-radius: 0.5em;
box-shadow: 0 5px 25px rgba(0, 0, 0, 0.2);
background: linear-gradient(160deg, ${(props) => console.log(props) });
font-size: 1.8em;
font-family: Rubik-Medium;
color: #fff;
`;
export default function Stat(props){
const { value } = props;
return (
<StyledStat {...props}>
{value}
</StyledStat>;
};
Styled components props comes from the ThemeProvider usually, this is why you see a theme props while console.logging inside your styled.div
Usually in App.js you have something like that:
// src/App.jsx
import React from 'react'
import { ThemeProvider } from 'styled-components';
const theme: {
colors: {
primary: blue,
}
}
const App = () => (
<ThemeProvider theme={theme}>
<Stat />
</ThemeProvider>
)
export default App;
you can access these attributes with
${(props) => props.theme.colors.primary }
because styled-components provides its theme props to every StyledComponents (there is a Context Provider/consumer thing behind)
import React from 'react';
import styled from 'styled-components';
const Stat = styled.div`
display: flex;
align-items: center;
justify-content: center;
padding: 0 2.5em;
width: auto;
height: 2.5em;
border-radius: 0.5em;
box-shadow: 0 5px 25px rgba(0, 0, 0, 0.2);
background: linear-gradient(160deg, ${(props) => props.theme.colors.primary} });
font-size: 1.8em;
font-family: Rubik-Medium;
color: #fff;
`;
Related
I have a main page, with a button component i create to reuse in my project. My issue is when i add the onClick event to my external component, the click event is not working, but is i create the same button inside my main page, the click event works just fine
Button Component
import React from "react";
import styled from "styled-components";
const BigButton = (props): JSX.Element => {
return <>{props.red ? <BigBtn red={props.red}>{props.val}</BigBtn> : <BigBtn>{props.val}</BigBtn>}</>;
};
export default BigButton;
const BigBtn = styled.button`
font-style: normal;
font-weight: 500;
font-size: 12px;
line-height: 15px;
color: #f5f5f5;
width: 78px;
height: 30px;
background: ${(props) => (props.red ? "#BD2129" : "#2e3034")};
border: ${(props) => (props.red ? "initial" : "1px solid #494b4f")};
border-radius: 2px;
display: flex;
align-items: center;
justify-content: center;
`;
This works on main page
<button onClick={buttonClose}>Close</button>
Button Component on main page - This doesn't work on main page
<BigButton val="Cancel" onClick={handleClose} />
Close function
const handleClose = (e) => {
e.preventDefault();
props.onClose();
};
Your component does not look correct. You do not have button inside the component and onClick event. You should update like this
import React from "react";
import styled from "styled-components";
const BigButton = (props): JSX.Element => {
const handleClick = () => {
props.onClick()
}
return <>{props.red ?
<BigBtn red={props.red}>
<button onClick={handleClick}>
{props.val}
</button>
</BigBtn> :
<BigBtn>
<button onClick={handleClick}>
{props.val}
</button>
</BigBtn>}
</>
};
export default BigButton;
const BigBtn = styled.button`
font-style: normal;
font-weight: 500;
font-size: 12px;
line-height: 15px;
color: #f5f5f5;
width: 78px;
height: 30px;
background: ${(props) => (props.red ? "#BD2129" : "#2e3034")};
border: ${(props) => (props.red ? "initial" : "1px solid #494b4f")};
border-radius: 2px;
display: flex;
align-items: center;
justify-content: center;
`;
So this could honestly be as simple as just over looking it and staring for so long and being new to react but on my section component I'm loading in my backgroundImg prop wont load the image and I cant figure it out. My pictures are in the public folder and my code is in the src components folder
Also, I can get images to load in the file just not when I'm calling them through prop
Home.js This is where I am calling my component and trying to load the file in through the prop type
import React from 'react'
import styled from 'styled-components'
import Section from './Section'
function Home() {
return (
<Container>
<Section
title="Model S"
description="Order Online for Touchless Delivery"
backgroundImg='/public/pictures/model-s.jpg'
leftBtnText="Custom Order"
rightBtnText="Existing Inventory"
/>
<Section
title="Model E"
description="Order Online for Touchless Delivery"
backgroundImg=".\Pictures\model-e.jpg"
leftBtnText="Custom Order"
rightBtnText="Existing Inventory"
/>
<Section />
<Section />
</Container>
)
}
export default Home
//Home and styled help you stlye the component without using css
const Container = styled.div`
height: 100vh;
`
Section.js The component for the Screen
import React from 'react'
import styled from 'styled-components'
//props are just parameters you can set when calling the component
function Section(props) {
return (
<Wrap bgImg={props.backgroundImg}>
<ItemText>
<h1>{props.title}</h1>
<p>{props.description}</p>
</ItemText>
<Buttons>
<ButtonGroup>
<LeftButton>
{props.leftBtnText}
</LeftButton>
<RightButton>
{props.rightBtnText}
</RightButton>
</ButtonGroup>
<DownArrow src='/Pictures/down-arrow.svg' />
</Buttons>
</Wrap>
)
}
export default Section
const Wrap = styled.div`
width: 100vw;
height: 100vh;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
`
const ItemText = styled.div`
padding-top: 15vh;
text-align: center;
`
const ButtonGroup = styled.div`
display: flex;
margin-bottom: 30px;
#media (max-width: 786px){
flex-direction: column;
}
`
const LeftButton = styled.div`
background-color: rgba(23, 26, 32, 0.8);
height: 40px;
width: 256px;
color: white;
display: flex;
justify-content: center;
align-items: center;
border-radius: 100px;
opacity: 0.85;
text-transform: uppercase;
font-size: 12px;
cursor: pointer;
margin: 8px;
`
const RightButton = styled(LeftButton)`
background: white;
opacity: 0.65;
color: black;
`
const DownArrow = styled.img`
margin-top: 20px;
height: 40px;
overflow-x: hidden;
animation: animateDown infinite 1.5s;
`
const Buttons = styled.div`
`
Thanks for the help.
I haven't tested this, but it looks like you didn't use the Wrap bgImg prop in the styled component. There is background-size, background-position, background-repeat, but not background-image using the prop.
Example:
background-image: ${props => props.bgImg || ''};
https://styled-components.com/docs/basics#passed-props
Error:
./src/card.js
Attempted import error: 'Bottom' is not exported from './styles/cards.style'.
card.js
import React from 'react'
import {
Bottom,
Color,
Text,
Image
} from "./styles/cards.style";
function Card(props) {
return (
<div>
<Bottom>
<Color />
<Text>{props.text}</Text>
<Text>{props.text}</Text>
</Bottom>
<Image
alt=""
src={props.image}
/>
</div>
);
}
export default Card;
cards.style
import styled from "styled-components";
export default {
colors: {
black: "rgba(0,0,0,1)",
brandPrimary: "rgba(238,120,36,1)",
brandPrimaryLight: "rgba(255,184,8,1)",
brandTertiary: "rgba(0,65,125,1)",
darkSlateGray: "rgba(51,51,51,1)",
white: "rgba(255,255,255,1)"
},
fonts: {
uiMainContent: {
family: "Poppins",
size: "15px",
weight: "300",
lineHeight: "21px"
},
uiSubContent: {
family: "Poppins",
size: "13px",
weight: "300",
lineHeight: "20px"
}
}
};
export const Bottom = styled.div`
width: 100%;
height: calc(100% - 20px);
background-color: ${props => props.theme.colors.white};
border-radius: 4px;
padding: 0 0 20px;
display: flex;
flex-direction: column;
align-items: flex-start;
position: relative;
`;
export const Color = styled.div`
height: 120px;
background-color: ${props =>
props.theme.colors.brandPrimary};
margin-bottom: 16px;
border-radius: 4px 4px 0px 0px;
align-self: stretch;
`;
export const Text = styled.p`
color: ${props => props.theme.colors.black};
margin-left: 16px;
letter-spacing: 0.1px;
font-family: ${props =>
props.theme.fonts.uiSubContent.family};
font-size: ${props =>
props.theme.fonts.uiSubContent.size};
font-weight: ${props =>
props.theme.fonts.uiSubContent.weight};
line-height: ${props =>
props.theme.fonts.uiSubContent.lineHeight};
&:not(:last-of-type) {
margin-bottom: 4px;
}
`;
export const Image = styled.img`
width: 150px;
height: 92px;
position: absolute;
left: 29px;
top: 14px;
`;
I am trying to build cards in reactjs. I usually stick to scss however cannot use props with scss which I will have to use later to dynamically generate components. Not sure what is wrong here as I did export Button. Please can someone shed some insight you see what is so blatantly wrong it is causing this error.
in that case you have an export default as the first thing of you code, if you are exporting more than one thing from the same file, you should stick to exporting each const/function by itself and not having any export default
If you are using ReactJS/NextJS I would really recommend creating a global theme that you normally write and import with the application, so you could have things like
// global.js
const GlobalStyle = createGlobalStyle`
* {
box-sizing: border-box;
}
:root {
--black: rgba(0,0,0,1);
--brandPrimary: rgba(238,120,36,1);
...
...
`
}
Take a look here, it should help you a lot.
I am trying to create a floating label select component, So the select box will have a label on click of that it will show a dropdown options. Like this With an icon and override the native browser options.
I was able to achieve using input field, but i am not able to understand how to create such a like component.
Dropdown.js
import React from "react";
import {
DropdownWrapper,
StyledSelect,
StyledOption,
StyledLabel
} from "./style";
export function Dropdown(props) {
return (
<DropdownWrapper onChange={props.onChange}>
<StyledLabel htmlFor={props.id}>{props.formLabel}</StyledLabel>
<StyledSelect id={props.id} name={props.id}>
{props.children}
</StyledSelect>
</DropdownWrapper>
);
}
export function Option(props) {
return <StyledOption selected={props.selected}>{props.value}</StyledOption>;
}
Style.js
import styled from "#emotion/styled";
export const DropdownWrapper = styled.div`
display: flex;
flex-flow: column;
justify-content: flex-start;
`;
export const StyledSelect = styled.select`
height: 100%;
padding: 0.5rem 0;
margin-bottom: 1rem;
border: none;
border-bottom: 1px solid black;
outline: none;
-webkit-appearance: none;
-moz-appearance: none;
text-indent: 1px;
text-overflow: "";
`;
export const StyledOption = styled.option`
color: ${(props) => (props.selected ? "lightgrey" : "black")};
`;
export const StyledLabel = styled.label`
margin-bottom: 1rem;
`;
Any help appreciated, here is what i have tried so far. link
i am new to TS and I have been asked to move existing JS code base to ts. I have styled component which looks like this (style.js)
import styled from "styled-components";
export const Container = styled.div`
${({ flex }) => flex && `flex: ${flex};`}
${({ flex }) => flex && `display: flex;`}
flex-direction: column;
`;
export const Label = styled.label`
display: inline-block;
color: #95aac9;
font-size: 12px;
`;
export const DefaultInput = styled.input`
border: 1px solid #dfe0eb;
background-color: transparent;
padding: 10px 12px;
border-radius: 4px;
height: 35px;
color: #888888;
font-weight: 500;
&:focus {
outline: none;
}
`;
export const GrayInput = styled.input`
border: none;
background-color: #ebf2fb;
border: 1px solid #e1e9f5;
border-radius: 5px;
padding: 5px 10px;
&:focus {
outline: none;
}
`;
I was writting types for the file where I am importing this
import React from "react";
import Label from "components/atoms/Label";
import { DefaultInput, GrayInput, NormalInput, Container } from "./styles";
export default function Input({flex, theme, ...props}:{flex:string, theme}) {
return (
<Container flex={props.flex}>
{props.label && <Label>{props.label}</Label>}
{(!props.theme || props.theme === "light") && <DefaultInput {...props} />}
{props.theme === "gray" && <GrayInput {...props} />}
{props.theme === "normal" && <NormalInput {...props} />}
</Container>
);
}
but I can't figure the type for the {...props] in export default function Input({flex, theme, ...props}:{flex:string, theme}) { and how to write it
I think this should do the work:
export default function Input({flex, theme, ...props}:{flex:string; theme: string; [rest: string]: any })
You should also use flex and theme variables directly instead of props.flex and props.theme, because you already destructured them from the passed object (props) and therefore they are not available(defined) there anymore.