I have a draggable icon. But onClick is not working on that icon.
import styled from "#emotion/styled"
import Draggable from 'react-draggable';
import { BsPlusCircle } from 'react-icons/bs';
const StartWrapper = styled.div`
position: absolute;
bottom: 74px;
display: block;
margin: 0 auto;
width: calc(100% - 24px);
font-family: Montserrat, sans-serif;
font-size: 14px;
font-style: normal;
font-weight: 500;
letter-spacing: 0em;
text-align: center;
color: rgba(91, 91, 91, 0.69);
border: 1px solid white;
height: 170px;
line-height: 170px;
`
export const App = ( ) => {
const show = () => {
console.log("Show");
}
return (
<StartWrapper onClick={()=> start()}>
<Draggable>
<BsPlusCircle onClick={() => show()} />
</Draggable>
</StartWrapper>
)
}
The start function works. But the show function does not work. Any help will be greatly appreciated.
Looks like you need to pass a ref to the StartWrapper and Draggable components
import styled from "#emotion/styled";
import { useRef } from "react";
import Draggable from "react-draggable";
import { BsPlusCircle } from "react-icons/bs";
const StartWrapper = styled.div`
position: absolute;
bottom: 74px;
display: block;
margin: 0 auto;
width: calc(100% - 24px);
font-family: Montserrat, sans-serif;
font-size: 14px;
font-style: normal;
font-weight: 500;
letter-spacing: 0em;
text-align: center;
color: rgba(91, 91, 91, 0.69);
border: 1px solid white;
height: 170px;
line-height: 170px;
`;
export const App = () => {
const ref = useRef(null); //ADD THIS
const show = () => {
console.log("Show");
};
return (
//Then pass refs to StartWrapper and Draggable
<StartWrapper ref={ref} onClick={() => console.log("Hello")}>
<Draggable ref={ref}>
<BsPlusCircle onClick={() => show()} />
</Draggable>
</StartWrapper>
);
};
This works for me in codesanbox
findDOMNode is deprecated in StrictMode. findDOMNode was passed an instance of DraggableCore which is inside StrictMode
Related
I am using StyledComponents stying framework and This is my regular react component
const SelectButton = ({className,children, ...rest}) => {
return (
<select className = {className}{...rest}>
{children}
</select>
);
}
I want to turn this component into styled component by calling styled() function and for that purpose I have attached className prop to DOM element of my react component (SelectButton).
export const StyledSelectButton = styled(SelectButton);
But instead of putting the css in this styled component, I want to inherit from different styled component which is StyledButton.js, which has following css properties.
export const StyledButton = styled(Button).attrs(({ type }) => ({
type: type || "button",
}))
display: inline-block;
height: auto;
padding: 0.8rem 2rem;
border: none;
border-radius: 6px;
font-weight: 500;
font-size: 1.6rem;
text-decoration: none;
text-transform: capitalize;
cursor: pointer;
overflow: hidden;
background-color: ${({ primary }) => (primary ? "#646ff0" : "#cccdde")};
color: ${({ primary }) => (primary ? "white" : "#646681")};
.__select {
color: #585858;
font-family: Poppins;
padding: 1rem;
border: none;
background-color: #cccdde;
width: 150px;
cursor: pointer;
};
How can I achieve that?
I have tried doing this way , but I am repeating my code.
export const StyledSelectButton = styled(SelectButton)
display: inline-block;
height: auto;
padding: 0.8rem 2rem;
border: none;
border-radius: 6px;
font-weight: 500;
font-size: 1.6rem;
text-decoration: none;
text-transform: capitalize;
cursor: pointer;
overflow: hidden;
background-color: ${({ primary }) => (primary ? "#646ff0" : "#cccdde")};
color: ${({ primary }) => (primary ? "white" : "#646681")};
&__select {
color: #585858;
font-family: Poppins;
padding: 1rem;
border: none;
background-color: #cccdde;
width: 150px;
cursor: pointer;
}
You can do something like this,
import styled, {css} from "styled-components";
import { StyledButton } from './Button';
const style = css`
color: #585858;
font-family: Poppins;
padding: 1rem;
border: none;
background-color: #cccdde;
width: 150px;
cursor: pointer;
`;
Using function declaration method:
export function StyledSelectButton({ className, children, ...rest }){
return (
<select className={className} {...rest}>
{children}
</select>
);
};
To turn this component into a styled component, pass it to the styled() function.
StyledSelectButton = styled(StyledButton).attrs((props) => ({
as: "select"
}))`
${style}
`;
Sup guys i have a problem, i would like to do an animated accordion, it should to have a transition animated when it opens and collapse, and in icon switching
I'm creating by myself an accordion in react + typescript but this transition doesnt works and idk why, code below:
This my index.tsx
import { useState } from "react";
import { AccordionButton, AccordionContent, Wrapper } from "./styles";
import { AccordionProps } from "./interfaces";
import { BsChevronDown, BsChevronUp } from "react-icons/bs";
export default function Accordion({ title, text }: AccordionProps) {
const [isOpen, setIsOpen] = useState(false);
const handleClick = () => {
setIsOpen(!isOpen);
returnIcon();
};
const returnIcon = () => {
return isOpen ? <BsChevronUp /> : <BsChevronDown />;
};
return (
<Wrapper>
<AccordionButton onClick={handleClick}>
{title} {returnIcon()}
</AccordionButton>
<AccordionContent isOpen={isOpen}>
<p>{text}</p>
</AccordionContent>
</Wrapper>
);
}
and this is my styled component below:
import styled from "styled-components";
import { AccordionContentProps } from "./interfaces";
export const AccordionButton = styled.button`
background-color: #606582;
color: #ffffff;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.6s;
&:hover {
background-color: #60658295;
}
> svg {
float: right;
}
`;
export const AccordionContent = styled.div<AccordionContentProps>`
display: ${(props) => (props.isOpen === false ? "none" : "block")};
padding: 0 18px;
background-color: white;
overflow: hidden;
`;
export const Content = styled.div`
padding: 10px 0px;
flex-wrap: wrap;
max-width: 750px;
margin-right: auto;
margin-left: auto;
#media only screen and (max-width: 600px) {
max-width: 80%;
}
`;
export const Wrapper = styled.div`
padding: 10px 0px;
`;
I've tried to add this code but still doesnt working
-webkit-transition: all 0.4s ease-in;
-moz-transition: all 0.4s ease-in;
-o-transition: all 0.4s ease-in;
transition: all 0.4s ease-in;
Try to replace the return block with the following:
return (
<Wrapper>
{isOpen && <AccordionButton onClick={handleClick}>
{title} <BsChevronUp />
</AccordionButton>}
{!isOpen && <AccordionButton onClick={handleClick}>
{title} <BsChevronDown />
</AccordionButton>}
<AccordionContent isOpen={isOpen}>
<p>{text}</p>
</AccordionContent>
</Wrapper>)
and we can also delete the function returnIcon - we don't need it
Although I have updated the todo status, the checkbox effect is not working correctly, as if no effect has been applied, what could be the reason for this? I don't think there is a problem with the api file, but the api request is taking a long time.I think it's because css doesn't render again, I can't think of anything else..
Thank you for helping
import React from "react";
import { useDispatch } from "react-redux";
import { toggleTodos } from "../redux/slice/thunkActions";
import styled from "styled-components";
const Content = styled.div`
color: #fff;
text-transform: capitalize;
`;
const Options = styled.div`
display: flex;
align-items: center;
justify-content: center;
gap: 2rem;
`;
const EditButton = styled.button`
cursor: pointer;
background-color: #ff6b81;
padding: 0.7rem 2rem;
color: #fff;
border-radius: 0.5rem;
font-weight: bold;
`;
const InputWrapper = styled.label`
position: relative;
`;
const Input = styled.input`
position: absolute;
left: -99999px;
top: -99999px;
&:checked + span {
background-color: #1890ff;
transition: 1s;
&:before {
left: calc(100% - 0.2rem);
transform: translateX(-100%);
}
}
`;
const Slider = styled.span`
display: flex;
width: 5rem;
height: 2.5rem;
cursor: pointer;
border-radius: 10rem;
background-color: #fcebb6;
transition: background-color 0.4s;
&:before {
content: "";
position: absolute;
top: 0.2rem;
left: 0.2rem;
width: 2.1rem;
height: 2.1rem;
border-radius: 2.1rem;
transition: 1s;
background-color: #fff;
}
`;
const Todo = ({ todo }) => {
const dispatch = useDispatch();
const handleChange = (todo) => {
dispatch(toggleTodos(todo));
};
return (
<li>
<Content>{todo.content}</Content>
<Options>
<EditButton type="button">Edit</EditButton>
<InputWrapper htmlFor={`todoContent${todo.id}`}>
<Input
id={`todoContent${todo.id}`}
type={"checkbox"}
onChange={() => handleChange(todo)}
checked={todo && todo.isCompleted}
/>
<Slider />
</InputWrapper>
</Options>
</li>
);
};
export default Todo;
This question already has answers here:
Using styled-components with props and TypeScript
(8 answers)
Closed 1 year ago.
I'm new to React with Typescript and Styled-Component and I came across this issue. I created a 'Header' component and I was trying to pass the state whenever the button is clicked into the HeaderStyled as a probs to change the CSS style depends on the state but I got error.
import React, {useState} from 'react'
import HeaderStyled from './Header_styled';
const Header = () => {
const [open,setOpen] = useState(false);
return (
<HeaderStyled open={open}>
<img src="/images/logo.svg" alt="sunnyside_logo" />
<ul>
<li>About</li>
<li>Services</li>
<li>Projects</li>
<li><button>CONTACT</button> </li>
</ul>
<div onClick={() => setOpen(!open)}>
<div></div>
<div></div>
<div></div>
</div>
</HeaderStyled>
)
}
export default Header;
Here is my HeaderStyled component
const HeaderStyled = styled.div `
background-color: ${theme.primaryBlue};
display: flex;
justify-content: flex-end;
padding: 20px 20px;
align-items: center;
ul {
position: absolute;
background-color: white;
top: 6%;
width: 80%;
height: 25%;
right: 10%;
display: flex;
flex-direction: column;
padding: 0px;
align-items: center;
justify-content: space-around;
transform: ${({open}) => open ? 'translateX(0)': 'translateX(120%)'};
li {
padding: 0px;
a {
color: #0000002e;
}
}
button {
background-color: yellow;
color: black;
}
}
The error I got from HeaderStyled
Have a look in the Styled Components docs for Typescript - Using custom props
import React, { useState } from "react";
import styled from "styled-components";
interface Props {
open: boolean;
}
const HeaderStyled = styled.div<Props>``;
const Header = () => {
const [open, setOpen] = useState(false);
return <HeaderStyled open={open}></HeaderStyled>;
};
export default Header;
The way to do it in TS is to define a type or an interface and add that to the styled component:
type HeaderStyledProps = {
open: boolean;
}
const HeaderStyled = styled.div<HeaderStyledProps>`
background-color: ${theme.primaryBlue};
display: flex;
justify-content: flex-end;
padding: 20px 20px;
align-items: center;
ul {
position: absolute;
background-color: white;
top: 6%;
width: 80%;
height: 25%;
right: 10%;
display: flex;
flex-direction: column;
padding: 0px;
align-items: center;
justify-content: space-around;
transform: ${({open}) => open ? 'translateX(0)': 'translateX(120%)'};
li {
padding: 0px;
a {
color: #0000002e;
}
}
button {
background-color: yellow;
color: black;
}
}
`
Getting this below error in my code. I am unable to find what is the error. Please help.
×
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of `LoginForm`..
LoginForm.js
import React from "react";
import { BoxContainer, FormContainer, MutedLink, SubmitButton, Input } from "./common";
import { Marginer } from "../marginer";
export function LoginForm(props) {
return (
<BoxContainer>
<FormContainer>
<Input type ="email" placeholder="Email" />
<Input type ="password" placeholder="Password" />
<Marginer direction="vertical" margin={5} />
<MutedLink href="#">Forget your password?</MutedLink>
<Marginer direction="vertical" margin="lem" />
<SubmitButton type="submit">Signin</SubmitButton>
</FormContainer>
</BoxContainer>
);
}
index.js
import React from 'react'
import styled from 'styled-components'
import { LoginForm } from './loginForm';
const BoxContainer = styled.div`
width: 280px;
min-height: 550px;
display: flex;
flex-direction: column;
border-radius: 19px;
background-color: #fff;
box-shadow: 0 0 2px rgba(15, 15, 15, 0.28);
position: relative;
overflow: hidden;
`;
const TopContainer =styled.div`
width: 100%;
height: 250px;
display: flex;
flex-direction: column;
justify-content: flex-end;
padding: 0 1.8em;
padding-bottom: 5em;
`;
const BackDrop = styled.div`
position: absolute;
display: flex;
flex-direction: column;
width: 160%;
height: 550px;
border-radius: 50%;
top: -290px;
left: -70px;
transform: rotate(60deg);
background: rgb(241, 196, 15);
background: linear-gradient(
58deg,
rgba(241,196,15,1) 20%,
rgba(243,172,18,1) 100%
)
`;
const HeaderContainer = styled.div`
width:100%;
display: flex;
flex-direction:column;
margin:auto;
`;
const HeaderText = styled.h2`
font-size: 30px;
font-weight: 600;
line-height: 1.24;
color: #fff;
z-index: 10;
margin: 0;
margin-right: 218px;
`;
const SmallText = styled.h5`
color:#ece5e5;
font-weight: 500;
font-size: 11px;
z-index: 10;
margin:0;
margin-right: 147px;
margin-top: 6px;
`;
const InnerContainer = styled.div`
width: 100%;
display: flex;
flex-direction:column;
`;
export function AccountBox(props) {
return (
<BoxContainer>
<TopContainer>
<BackDrop />
<HeaderContainer>
<HeaderText>Welcome</HeaderText>
<HeaderText>Back</HeaderText>
<SmallText>please sign-in to continue!</SmallText>
</HeaderContainer>
</TopContainer>
<InnerContainer>
<LoginForm />
</InnerContainer>
</BoxContainer>
);
}
marginer.js
import React from "react";
import styled from "styled-components";
const HorizontalMargin = styled.span`
display: flex;
width: ${({ margin }) =>
typeof margin === "string" ? margin : `${margin}px`};
`;
const VerticalMargin = styled.span`
display: flex;
height: ${({ margin }) =>
typeof margin === "string" ? margin : `${margin}px`};
`;
function Marginer(props) {
const { direction } = props;
if (direction === "horizontal") return <HorizontalMargin {...props} />;
else {
return <VerticalMargin {...props} />;
}
}
Marginer.defaultProps = {
direction: "horizontal",
};
export { Marginer };