logo

Step Form

Um provider de formulário com animação passo-a-passo

Código:


//src/components/stepFormProvider/stepFormProvider.tsx
'use client';

import { ReactNode, useEffect, useState } from 'react';

interface FormProviderProps {
	forms: ReactNode[];
	actualForm: number;
}

export default function StepFormProvider({ forms, actualForm }: FormProviderProps) {
	const [prevForm, setPrevForm] = useState(actualForm);
	const [direction, setDirection] = useState(0);
	const [transitioning, setTransitioning] = useState(false);

	useEffect(() => {
		if (actualForm === prevForm) return;

		setDirection(actualForm > prevForm ? 1 : -1);
		setTransitioning(true);

		const timer = setTimeout(() => {
			setPrevForm(actualForm);
			setTransitioning(false);
		}, 300); // deve bater com a duração das animações

		return () => clearTimeout(timer);
	}, [actualForm, prevForm]);

	return (
		<div className='relative h-full w-full overflow-hidden'>
			{/* Form que está saindo */}
			{transitioning && (
				<div
					className='absolute left-0 top-0 h-full w-full'
					style={{
					animation: `${direction === 1 ? 'slideOutLeft' : 'slideOutRight'} 300ms ease-in-out forwards`,					}}
				>
					{forms[prevForm]}
				</div>
			)}

			{/* Form que está entrando */}
			<div
				className='absolute left-0 top-0 h-full w-full'
				style={{
					animation: transitioning? `${direction === 1 ? 'slideInRight' : 'slideInLeft'} 300ms ease-in-out forwards`: undefined,
				}}
			>
				{forms[transitioning ? actualForm : prevForm]}
			</div>
			<style jsx global>{`@keyframes slideOutLeft {from {
						transform: translateX(0%);
						opacity: 1;
					}
					to {
						transform: translateX(-100%);
						opacity: 0;
					}
				}
				@keyframes slideOutRight {
					from {
						transform: translateX(0%);
						opacity: 1;
					}
					to {
						transform: translateX(100%);
						opacity: 0;
					}
				}
				@keyframes slideInRight {
					from {
						transform: translateX(100%);
						opacity: 0;
					}
					to {
						transform: translateX(0%);
						opacity: 1;
					}
				}
				@keyframes slideInLeft {
					from {
						transform: translateX(-100%);
						opacity: 0;
					}
					to {
						transform: translateX(0%);
						opacity: 1;
					}
				}`}</style></div>
	);
}
yarn add motion

Prévia:

Formulário passo-a-passo