AnimatePresence and Exit Not Working for Components - framer-motion - framer-motion

I've got this code in index page.
const screen = "landing";
<AnimatePresence exitBeforeEnter>
<Header key="header" />
{screen === "landing" && <LandingComponent key="landing" /> // in here this work for me.
</AnimatePresence>
and here is Header component
return ...map(
(item) =>
item === ... && (
<motion.img
src="https://assets.glitch.ge/abba/setlist/logo.png"
className={style.image}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.5, delay: 0.3 }}
exit={{ opacity: 0 }}
/>
)
);
in here not work exit animations

Related

React-beautiful-dnd: lazy loaded component keeps falling back to suspense when dragged

I have a react component that dynamically loads a widget component using react lazy, with the component path passed as a prop.
It renders fine, but when I drag it, the component flickers between its Suspense fallback and the fully rendered component. How can I prevent the Suspense fallback from being shown while dragging?
The draggable list looks like this:
<DragDropContext
onDragEnd={result => {
console.log(result);
reorder({ result, previousData: dashboard.data });
}}
>
<Title title={`Dashboard`} />
<Droppable droppableId={"dashboard"}>
{(
provided
// snapshot
) => {
return (
<div
{...provided.droppableProps}
ref={provided.innerRef}
style={{
display: "flex",
flexDirection: "column"
}}
>
{Array.isArray(dashboardItems.data) && dashboardItems.data.length > 0 ? (
dashboardItems.data.map((item: any, index: number) => {
return (
<Draggable key={item.id} draggableId={item.id} index={index}>
{(provided, snapshot) => {
return (
<div ref={provided.innerRef} {...provided.draggableProps}>
<WidgetCard item={item} dragHandleProps={provided.dragHandleProps} />
{!snapshot.isDragging && <AddWidgetControl />}
</div>
);
}}
</Draggable>
);
})
) : (
<Button
onClick={() =>
addDashboardItem.mutate({
index: 0,
dashboardItem: widgets.overview
})
}
>
<Typography variant="body2">Add</Typography>
</Button>
)}
{provided.placeholder}
</div>
);
}}
</Droppable>
</DragDropContext>
and the WidgetCard component that conditionally renders the widgets using lazy looks like this:
const WidgetCard = ({
item,
dragHandleProps
}: {
item: DashboardItemEntity,
dragHandleProps?: any
}) => {
{...}
const renderLoader = () => <p>Loading</p>;
const WidgetComponent = lazy(() => import(`../${item.component}`));
{...}
return (
{...}
<CardContent sx={{ marginTop: 0, paddingTop: 0 }}>
{/* {description} */}
<Box sx={{ marginLeft: 2 }}>
<Suspense fallback={renderLoader()}>
<WidgetComponent item={item} />
</Suspense>
</Box>
</CardContent>
{...}
);
};

Remix-Run Page Transition Animation With Framer Motion

I would like to add some page transitions to my web app.
The problem is that the exit animation doesn't work.
I have a Motion Component
// app/components/Motion.tsx
import React from "react";
import { motion } from "framer-motion";
export default function Motion(props: {
children: React.ReactChild | React.ReactFragment | React.ReactPortal;
}) {
return (
<motion.div
className="w-full h-screen bg-blue-400 flex pt-24 mx-auto"
initial={{ opacity: 0, x: -100 }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: -100 }}
transition={{ duration: 2 }}
>
{props.children}
</motion.div>
);
}
In which I want to wrap every page like this:
// app/routes/contact.tsx
import Motion from "~/components/Motion";
export default function contact() {
return (
<Motion>
<div>Contact</div>
</Motion>
);
}
I know that I should use the <AnimatePresence> from framer-motion but I don't know where.
Funny enough, I was just trying to figure out how to do this a few hours ago. I'm super new to Remix, but here's a really simple example of what I did to get route animations working.
root.jsx
import {
Links,
LiveReload,
Meta,
Outlet,
Scripts,
ScrollRestoration,
} from 'remix'
import { AnimatePresence } from 'framer-motion'
import styles from './styles/app.css'
export function meta() {
return {
charset: 'utf-8',
title: 'New Remix App',
viewport: 'width=device-width,initial-scale=1',
}
}
export function links() {
return [{ rel: 'stylesheet', href: styles }]
}
export default function App() {
return (
<html lang="en">
<head>
<Meta />
<Links />
</head>
<body>
<AnimatePresence exitBeforeEnter>
<Outlet />
</AnimatePresence>
<ScrollRestoration />
<Scripts />
<LiveReload />
</body>
</html>
)
}
Example of first route index.jsx
import { motion } from 'framer-motion'
export default function Index() {
return (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.5 }}
className="w-full h-full md:col-span-3 sm:overflow-auto relative z-0"
>
{/* page content */}
</motion.div>
Same <motion.div></motion.div> parent elements as above to be applied to the next route (e.g. about.jsx) - including the same initial, animate, exit, and transition attributes.

How can i center the content of my footer?

I am new to react material ui.
I am using this table here
https://material-ui.com/components/tables/
under Custom pagination actions section.
Inside, there is a contenet in the footer with Rows per page text buttons for next previous etc...
I can't find a way to center that content in the middle.Right not is it is 'aligned' to the right by default
I tried adding
align="center"
justify="center"
but without success
My footer code looks like this
<TablePagination
className=""
align="center"
justify="center"
text-align="center"
rowsPerPageOptions={[5, 10, {label: 'All', value: -1}]}
// colSpan={12}
count={props.rowsCount}
rowsPerPage={props.rowsPerPage}
page={props.page}
SelectProps={{
inputProps: {'aria-label': 'rows per page'},
native: true,
}}
onChangePage={props.onChangePage}
onChangeRowsPerPage={props.onChangeRowsPerPage}
ActionsComponent={TablePaginationActions}
/>
Table pagination actions
import KeyboardArrowLeft from '#material-ui/icons/KeyboardArrowLeft';
import KeyboardArrowRight from '#material-ui/icons/KeyboardArrowRight';
import FirstPageIcon from '#material-ui/icons/FirstPage';
import LastPageIcon from '#material-ui/icons/LastPage';
import {makeStyles, useTheme} from '#material-ui/core/styles';
import {IconButton} from '#material-ui/core';
const useStyles = makeStyles((theme) => ({
root: {
flexShrink: 0,
marginLeft: theme.spacing(2.5),
},
}));
function TablePaginationActions(props) {
const classes = useStyles();
const theme = useTheme();
const {count, page, rowsPerPage, onChangePage} = props;
const c = console;
// c.table(props);
const handleFirstPageButtonClick = (event) => {
onChangePage(event, 0);
};
const handleBackButtonClick = (event) => {
onChangePage(event, page - 1);
};
const handleNextButtonClick = (event) => {
onChangePage(event, page + 1);
};
const handleLastPageButtonClick = (event) => {
onChangePage(event, Math.max(0, Math.ceil(count / rowsPerPage) - 1));
};
return (
<div className={classes.root}>
<IconButton
onClick={handleFirstPageButtonClick}
disabled={page === 0}
aria-label="first page"
>
{theme.direction === 'rtl' ? <LastPageIcon /> : <FirstPageIcon />}
</IconButton>
<IconButton
onClick={handleBackButtonClick}
disabled={page === 0}
aria-label="previous page"
>
{theme.direction === 'rtl' ? <KeyboardArrowRight /> : <KeyboardArrowLeft />}
</IconButton>
<IconButton
onClick={handleNextButtonClick}
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
aria-label="next page"
>
{theme.direction === 'rtl' ? <KeyboardArrowLeft /> : <KeyboardArrowRight />}
</IconButton>
<IconButton
onClick={handleLastPageButtonClick}
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
aria-label="last page"
>
{theme.direction === 'rtl' ? <FirstPageIcon /> : <LastPageIcon />}
</IconButton>
</div>
);
}
export default TablePaginationActions;
I found a way.The problem was that react used out of the box class - MuiTablePagination-spacer
which had this css
MuiTablePagination-spacer {
flex: 1 1 100%;
}
that maked the other sibling div go to the right
with this css applied i justified my content in the center
.MuiToolbar-root {
justify-content: center !important;
border:2px solid red;
}
.MuiTablePagination-spacer {
flex: 0 !important;
}
MuiToolbar-root already has display:flex so i applied only justify-content. We must disable the spaces on MuiTablePagination-spacer, otherwise it won't work.

Multistage transitions in react spring

I have a react-spring Transition starts when the component mounts. I want it to wait for 'x' seconds when enter is complete, then flip the show state so it can start leave.
<Transition
items={show}
from={{ ...styles, position: "absolute", opacity: 0 }}
enter={{ opacity: 1 }}
leave={{ opacity: 0 }}
>
{show => show && (props => <div style={props}>{content}</div>)}
</Transition>
You must put the timeout to the componentDidMount lifecycle method. So it shows your content and the after 1 second it fades out and unmouts it. Do you need something like it?:
class App extends React.Component {
state = {
show: true
};
componentDidMount() {
setTimeout(() => this.setState({ show: false }), 1000);
}
render() {
const { show } = this.state;
const content = <div>eeeeeeeee</div>;
return (
<div className="App">
<Transition
items={[show]}
from={{ position: "absolute", opacity: 0 }}
enter={{ opacity: 1 }}
leave={{ opacity: 0 }}
>
{show =>
show &&
(props => <animated.div style={props}>{content}</animated.div>)
}
</Transition>
</div>
);
}
}
https://codesandbox.io/s/keen-almeida-5wlk7

React Motion CSS transform from center

I am using react-motion for CSS transfrom in react. this bellow code scales my desired output from top left corner.
<Motion defaultStyle={{ x: 0 }} style={{ x: spring(360) }}>
{(value) => {
return (
<div
style={{
width: value.x,
height: value.x,
animation: `scale 5s infinite`,
transform: `scale(1,1)`,
}}
>
{" "}
<this.ComponentName post={post} view={view} />
</div>
);
}}
</Motion>
How can i make it scale from center?
I have come to a solution. It can be done with a few changes but a tricky one.
<Motion defaultStyle={{ x: 0 }} style={{ x: spring(1) }} >
{value => {return <div style={{
animation: `scale 5s infinite`,
transform: `scale(${value.x})`,
}}
> <this.ComponentName post={post} view={view}/></div>}}

Resources