CSS Transitions not working (partly) on Safari using styled-component - reactjs

I have applied css transitions all over my app and it's working flawlessly on firefox and chrome but the problem it is not working all the time on Safari for some reason sometimes the animation will choke sometimes it will partly transition sometimes works but I am not sure why
I am using explicit transition declarations not using all always like this transition: color 1s linear for example
I tried -webkit-transition even though Styled-components automatically do this but no luck too
I tried clearing cache and reload nothing changed
I am using NextJS with styled-components
transitions that are triggered on hover all working normally
any suggestions ?
one of the glitching components
import styled from "styled-components";
import { colors } from "../styles/SharedStyles";
const DarkModeToggle = styled.div`
position: fixed;
bottom: 1.25rem;
right: 1.25rem;
width: 45px;
height: 45px;
cursor: pointer;
clip-path: circle();
background-image: ${({ theme }) =>
theme.body !== colors.white
? `url("/images/misc/dark-logo.svg")`
: `url("/images/misc/light-logo.svg")`};
background-color: ${({ theme }) =>
theme.body !== colors.white ? colors.gray[700] : colors.secondary};
background-position: center;
background-repeat: no-repeat;
background-size: ${(props) => (props.theme.body !== colors.white ? `60%` : `70%`)};
transition: background 0.3s ease-in-out;
z-index: 98;
`;
export default DarkModeToggle;

Related

Styled Components Injects wrong classes on wrong elements

I'm witnessing a weird behavior when in styled-components with SSR in remix.run
I have a ProductCard Component that renders a normal product card with styled-components
ProductCard.tsx
import Button from "../Button";
function ProductCard({ product }: props) {
return (
<>
<Wrapper>
....
<ButtonsWrapper>
<Cart
onClick={addToCart}
mode={addedToCart ? "secondary" : "primary"}
disabled={loading}
key="cart-button"
>
{addedToCart ? "Added!" : "Add to cart"}
{loading && <LoadingSpinner src="/images/responses/loader.svg" />}
</Cart>
<ShareButton mode="secondary" aria-label="share">
<Icon id="share" />
</ShareButton>
</ButtonsWrapper>
</Wrapper>
</>
);
}
const Cart = styled(Button)`
flex: 1.1;
display: flex;
justify-content: center;
gap: 10px;
`;
const ShareButton = styled(Button)`
padding: 0.9rem;
`;
const Wrapper = styled.div`
--border-radius: ${clamp(15, 20)};
--columnGap: ${clamp(20, 30)};
display: flex;
flex-direction: column;
gap: var(--columnGap);
justify-content: space-between;
width: 100%;
height: 100%;
margin: auto;
background-color: var(--azure-15);
padding: 1.9rem 1.5rem;
border-radius: var(--border-radius);
box-shadow: var(--box-shadow-lg);
border: var(--border-lg);
`;
const ButtonsWrapper = styled.div`
display: flex;
justify-content: space-between;
gap: 0.625rem;
`;
export default ProductCard;
Button.tsx
const Button = styled.button<{ mode: "primary" | "secondary" | "dark" }>`
display: grid;
/* justify-content: center; */
align-items: center;
text-align: center;
color: var(--mintCream);
padding: ${clamp(9, 10)} ${clamp(20, 30)}; // this clamp function just generates the css clamp func with calculating the values with some equations
box-shadow: var(--box-shadow-md);
border: var(--border-md);
border-radius: 12px;
text-decoration: none;
cursor: pointer;
transition: all 500ms ease;
font-size: ${clamp(13, 16)};
&:disabled {
cursor: not-allowed;
opacity: 0.7;
}
#media (hover: hover) and (pointer: fine) {
&:hover:enabled {
transform: translateY(-2px); }
}
width: fit-content;
`;
The normal render of this Component is as follows
But when navigating to another path and returning to it on / , it renders like this
This problem only happens in production and works fine on local server...
when inspecting elements, I find that the class name of the Cart Component is also injected into the ShareButton Element
I can't find an explanation for this problem and it gets weirder... When I swap the order of the variables Cart and ShareButton or swap them with the Wrapper Element, some other weird behaviors happen like the one below
In this case, the class name of the Cart Component got injected on the parent elemnt of the parent element of the ProductCard Component
I've probably hit on 4 of these rendering issues but all of them share the same problem, the class name of the Cart Components gets injected on a wrong dom element, whether it's a parent or a sibiling
You can view the first weird behaviour here https://store.ieeenu.com
You will find the product component on the root path, navigate to some path like categories/circuits-1-ecen101 and return to the root and you will see the issue
also, you can review the second weird behavior in a previous build here
https://ieee-nu-store-r243eocii-omarkhled.vercel.app/
I just changed the initialization order of the Cart and ShareButton Components as I said earlier
I don't know whether this problem is from styled-components or from remix (this is the first time for me using remix), it's mentioned here https://github.com/remix-run/remix/issues/1032 that the lack of the babel-plugin-styled-components in remix.run introduces some problems in rehydration but I'm not sure that this is the issue I'm facing...
Thanks for reading this till the end and excuse my English, I'm not a native speaker :"

React modal component receiving same class

I have a react Modal component that I have made. I can pass a prop that makes it full screen or define a width. It all works fine, but i'm having an issue reusing it when the first modal is open. The 2nd component takes the same class as the 1st, so it makes the max-width 100%.
For example, I want to have a full screen modal, and show a 2nd modal at 50% size on top when i click a link.
I am using styled components which i think is where the issue may be happening. Im just not sure how to approach it.
Modal component:
<ModalContainer visible={visible} fullScreen={fullScreen}>
<ModalDialog role="dialog" width={width}>
<ModalBody>{children}</ModalBody>
</ModalDialog>
</ModalContainer>
Styles
export const ModalDialog = styled.div`
width: 100%;
max-width: ${({ width }) => width};
`;
export const ModalContainer = styled.div`
visibility: hidden;
opacity: 0;
display: none;
${({ visible }) =>
visible &&
css`
visibility: visible;
opacity: 1;
display: flex;
`}
${({ fullScreen }) =>
fullScreen &&
css`
width: 100vw;
height: 100vh;
overflow: none;
${ModalDialog} {
box-shadow: none;
max-width: 100%;
}
`}
`}
The class of the first modal for dialog is what is also being used for the 2nd even though that does not have the full screen prop.

ReactJs - onClick not firing

Probably a super noobie question, but does anyone know why my onClick is not firing? I have tried changing the z-index in my CSS in case the button was too far back, but this did not change anything.
Here is my button module:
import React from 'react';
import classes from './button.module.css';
const button = (props)=>{
return(
<button onClick={()=>{console.log("hello");props.select()}} className={classes.button}>
<div className={classes.text_center}>
<div className={classes.button_text}>{props.text}</div></div>
</button>
);
}
export default button;
Later on I call the module:
this.state.skills?null:<Button select={()=>{console.log("hi");this.setState({skills:true})}} text={"Skills"}></Button>}.
The button actually displays fine, and the text is passed as a prop, but unfortunately I can't get the onClick to fire. Neither of the two console.log statements fire.
All help is appreciated.
///
As requested in the comments button.module.css:
#font-face {
font-family: 'Raleway';
src: url('../../../Fonts/Raleway/Raleway-Light.ttf') format('truetype') /* IE6-IE8 */
}
.button_choice{
width:10vw;
height:10vh;
top:25%;
border: 2px solid #4ca3dd;
position: relative;
display: inline-block;
margin-left:5vw;
background-color: white;
vertical-align: middle;
border-radius:10px;
padding:5px;
}
.button_choice:hover{
background-color: red;
}
.text_center{
height:100%;
width:100%;
position:relative;
display: table;
}
.text_center:hover{
background-color: blue;
}
.button_text{
font-family:"Raleway";
position:relative;
line-height: 30px;
font-size: 20px;
text-align: center;
display: table-cell;
vertical-align: middle;
}
/////
Slight break through :/, when considering the 3 classes below, .background_init is a div spreading over the whole page. On the press of a button, this div slides to half of the size on the left by changing to the class .background_left. The buttons are contained within background_right. If I change height in .background_left to 200px, the buttons work (including hover), but obviously this completely messes up my styling. Any suggestions?
.background_init{
width:100vw;
height:100vh;
background-color: #4ca3dd;
}
.background_left{
width:50vw;
height:100vh;
background-color: #4ca3dd;
transition: width 2s;
}
.background_right{
overflow: auto;
width:50vw;
height:100vh;
transition: width 2s;
}
I am not sure why this works, but instead of using 100vh and 100vw, I used display:absolute and width:50%/ 100% and height:100%. If anyone can explain why this works I would be extremely grateful.

How to use Media Queries inside a React Styled Components Keyframe?

I can get media queries to work properly inside a regular styled-components component however when I attempted to use it in a keyframe (via import from styled-components) it does not seem to work at all.
Attempting to get a div to animate to a specific position, but have that end position change when the window is < 800px, I've attempted this:
import styled, { keyframes } from 'styled-components';
// ... further down ...
const slideAnim = keyframes`
100% {
top: 20px;
left: 30px;
}
#media (max-width: 800px) {
top: 70px;
left: 50px;
}
`;
I have also tried putting the media query in the 100% block:
const slideAnim = keyframes`
100% {
top: 20px;
left: 30px;
#media (max-width: 800px) {
top: 70px;
left: 50px;
}
}
`;
I made a helpful interactive demonstration of what I am trying to achieve (problem code is at line 24):
https://codesandbox.io/embed/fragrant-star-m71ct
Feel free to change the breakpoint variable from 800 if you need to.
Any help is appreciated!
You could take a different approach, where your keyframes animation is instead defined as a function like this:
const slideAnim = (top, left) => keyframes`
100% {
top: ${ top };
left: ${ left };
}
`;
The function accepts input parameters that dictate the destination coordinates of top and left for that animation's final keyframe.
In your stlyed component (ie Box1), you'd then invoke slideAnim() with specific coordinates to each breakpoint, to achieve different animation behavior per breakpoint:
/*
Declare responsive styling in the Box1 component, where destination
coordinates are specified for the animate on a per-breakpoint-basis
*/
const Box1 = styled.div`
width: 20px;
height: 20px;
background-color: blue;
position: absolute;
left: -100px;
top: 80px;
&.slide {
animation: ${slideAnim('20px', '30px')} 0.4s ease-in-out forwards;
#media (max-width: ${breakpoint}px) {
animation: ${slideAnim('70px', '50px')} 0.4s ease-in-out forwards;
}
}
`;
In summary, the idea is to shift the responsive styling into your styled component (ie Box1), while defining a reusable function that contains the common/shared keyframes for each responsive breakpoint.
Here's a working example - hope that helps!
A more developed approach to use media queries with styled-components
firstly we define the screen size for each device:
const size = {
mobile: "320px",
tablet: "768px",
laptop: "1024px",
desktop: "2560px",
}
then we use css imported from styled-components to address media queries in relevant constants for each device
export const mobile = (inner) => css`
#media (max-width: ${size.mobile}) {
${inner};
}
`;
export const tablet= (inner) => css`
#media (max-width: ${size.tablet}) {
${inner};
}
`;
export const desktop= (inner) => css`
#media (max-width: ${size.desktop}) {
${inner};
}
`;
export const laptop= (inner) => css`
#media (max-width: ${size.laptop}) {
${inner};
}
`;
now lets say you are creating a styled div and you want to use media queries it. and based on the accepted answer to use keyframes
const slideAnim = (top, left) => keyframes`
100% {
top: ${ top };
left: ${ left };
}
`;
const StyledDiv= styled.div`
/* ...css */
animation: ${slideAnim('20px', '30px')} 0.4s ease-in-out forwards;
${mobile(css`
width:300px;
animation: ${slideAnim('10px', '20px')} 0.1s ease-in-out forwards;
/* ...css */
`)};
${tablet(css`
width:500px;
/* ...css */
`)};
/*... and so on */
`;
Use keyframes outside of all blocks. eg:
import { IconButton} from "#material-ui/core";
const CloseButton = styled(IconButton)`
padding: 3px !important;
outline: none;
#media only screen and (min-width: 728px) {
padding: 4px !important;
margin:0
}
`;

How to create Twilio Flex UI themed hml elements

I want to add buttons, form element etc to my component, but they appear without styling. How can I let them render using the theme styling?
Any common componets for buttons/dropdowns/tabs or css classes I can use and how?
I haven't found a good way to actually inherit the styles because they used styled components (Emotion). I've actually been rebuilding flex components (which seems like a waste to be honest).
Here's how I recreated a Flex button:
./src/components/FlexButton/FlexButton.jsx
import React from 'react';
import FlexButtonStyles from './FlexButton.Styles';
const FlexButton = (props) => {
return (
<FlexButtonStyles {...props} />
);
};
export default FlexButton;
./src/component/FlexButton/FlexButton.Styles.js
import { default as styled } from 'react-emotion';
import { withTheme } from '#twilio/flex-ui';
const FlexButtonStyles = styled('button')`
align-self: center;
height: 28px;
font-size: 10px;
font-weight: bold;
letter-spacing: 2px;
white-space: nowrap;
color: rgb(255, 255, 255);
padding: 0px 16px;
border-width: initial;
border-style: none;
border-color: initial;
border-image: initial;
background: linear-gradient(to top, ${props => props.theme.colors.defaultButtonColor}, ${props => props.theme.colors.defaultButtonColor});
outline: none;
border-radius: 100px;
:hover {
background-color: rgba(0, 0, 0, 0.2);
background-blend-mode: color;
}
:disabled{
background: ${props => props.theme.colors.disabledColor};
}
`;
export default withTheme(FlexButtonStyles);
I stole all the CSS by just reviewing the live source code.

Resources