Skip to content

Commit

Permalink
Added custom UI components to animate text and HTML elements
Browse files Browse the repository at this point in the history
  • Loading branch information
FlorianLeChat committed Dec 14, 2024
1 parent da9e99c commit 0bf6e42
Show file tree
Hide file tree
Showing 3 changed files with 194 additions and 0 deletions.
57 changes: 57 additions & 0 deletions app/[locale]/components/ui/thirdparty/blur-in.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//
// Composant d'animation pour le texte.
// Source : https://magicui.design/docs/components/blur-in
//

"use client";

import { motion } from "framer-motion";
import type { ReactNode } from "react";

interface BlurInProps {
as: string;
children: ReactNode;
className?: string;
variant?: {
hidden: { filter: string; opacity: number };
visible: { filter: string; opacity: number };
};
delay?: number;
duration?: number;
}

function BlurIn( {
as,
children,
className,
variant,
delay = 0,
duration = 1
}: Readonly<BlurInProps> )
{
const MotionComponent = motion.create( as, {
forwardMotionProps: true
} ) as typeof motion.div;
const defaultVariants = {
hidden: { filter: "blur(10px)", opacity: 0 },
visible: {
filter: "blur(0px)",
opacity: 1,
transition: { delay, duration }
}
};
const combinedVariants = variant || defaultVariants;

return (
<MotionComponent
initial="hidden"
animate="visible"
variants={combinedVariants}
className={className}
>
{children}
</MotionComponent>
);
}

export default BlurIn;
75 changes: 75 additions & 0 deletions app/[locale]/components/ui/thirdparty/fade-text.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//
// Composant d'animation pour le texte.
// Source : https://magicui.design/docs/components/fade-text
//

"use client";

import { useMemo, type ReactNode } from "react";
import { motion, type Variants } from "framer-motion";

type FadeTextProps = {
as: string;
delay?: number;
className?: string;
direction?: "up" | "down" | "left" | "right";
framerProps?: Variants;
children: ReactNode;
};

export default function FadeText( {
as,
delay = 0,
direction = "up",
className,
framerProps = {
hidden: { opacity: 0 },
show: { opacity: 1, transition: { type: "spring", delay } }
},
children
}: Readonly<FadeTextProps> )
{
const MotionComponent = motion.create( as, {
forwardMotionProps: true
} ) as typeof motion.div;
const directionOffset = useMemo( () =>
{
const map = { up: 10, down: -10, left: -10, right: 10 };
return map[ direction ];
}, [ direction ] );

const axis = direction === "up" || direction === "down" ? "y" : "x";

const FADE_ANIMATION_VARIANTS = useMemo( () =>
{
const { hidden, show, ...rest } = framerProps as {
[name: string]: { [name: string]: number; opacity: number };
};

return {
...rest,
hidden: {
...( hidden ?? {} ),
opacity: hidden?.opacity ?? 0,
[ axis ]: hidden?.[ axis ] ?? directionOffset
},
show: {
...( show ?? {} ),
opacity: show?.opacity ?? 1,
[ axis ]: show?.[ axis ] ?? 0
}
};
}, [ directionOffset, axis, framerProps ] );

return (
<MotionComponent
className={className}
initial="hidden"
animate="show"
viewport={{ once: true }}
variants={FADE_ANIMATION_VARIANTS}
>
{children}
</MotionComponent>
);
}
62 changes: 62 additions & 0 deletions app/[locale]/components/ui/thirdparty/word-pull-up.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//
// Composant d'animation pour le texte.
// Source : https://magicui.design/docs/components/word-pull-up
//

"use client";

import { merge } from "@/utilities/tailwind";
import { motion, type Variants } from "framer-motion";

interface WordPullUpProps {
as: string;
words: string;
delayMultiple?: number;
wrapperFramerProps?: Variants;
framerProps?: Variants;
className?: string;
}

export default function WordPullUp( {
as,
words,
wrapperFramerProps = {
hidden: { opacity: 0 },
show: {
opacity: 1,
transition: {
staggerChildren: 0.2
}
}
},
framerProps = {
hidden: { y: 20, opacity: 0 },
show: { y: 0, opacity: 1 }
},
className
}: Readonly<WordPullUpProps> )
{
const MotionComponent = motion.create( as ) as typeof motion.div;

return (
<MotionComponent
variants={wrapperFramerProps}
initial="hidden"
animate="show"
className={merge(
"font-display text-center text-4xl font-bold leading-[5rem] tracking-[-0.02em] drop-shadow-sm",
className
)}
>
{words.split( " " ).map( ( word ) => (
<motion.span
key={word}
variants={framerProps}
style={{ display: "inline-block", paddingRight: "8px" }}
>
{word === "" ? <span>&nbsp;</span> : word}
</motion.span>
) )}
</MotionComponent>
);
}

0 comments on commit 0bf6e42

Please sign in to comment.