From 6d3921b7011f7e67a7c2a603d0e12d086c9374ab Mon Sep 17 00:00:00 2001 From: Arghya Das Date: Thu, 19 Dec 2024 18:34:26 +0530 Subject: [PATCH] feat: adding 4 direction in blur fade --- content/docs/components/blur-fade.mdx | 23 ++++++++++--------- public/r/styles/default/blur-fade.json | 2 +- public/r/styles/default/dock.json | 2 +- registry/default/example/blur-fade-demo.tsx | 1 + .../default/example/blur-fade-text-demo.tsx | 2 +- registry/default/magicui/blur-fade.tsx | 19 +++++++++++---- registry/default/magicui/dock.tsx | 10 ++++---- 7 files changed, 36 insertions(+), 23 deletions(-) diff --git a/content/docs/components/blur-fade.mdx b/content/docs/components/blur-fade.mdx index 6eb471352..1c822fd48 100644 --- a/content/docs/components/blur-fade.mdx +++ b/content/docs/components/blur-fade.mdx @@ -46,14 +46,15 @@ npx shadcn@latest add "https://magicui.design/r/blur-fade" ## Props -| Prop | Type | Description | Default | -| ------------ | --------------- | ------------------------------------------------------ | ------- | -| children | React.ReactNode | The content to be animated | | -| className | string | The class name to be applied to the component | | -| variant | object | Custom animation variants for motion component | | -| duration | number | Duration (seconds) for the animation | 0.4 | -| delay | number | Delay (seconds) before the animation starts | 0 | -| yOffset | number | Vertical offset for the animation | 6 | -| inView | boolean | Whether to trigger animation when component is in view | false | -| inViewMargin | MarginType | Margin for triggering the in-view animation | "-50px" | -| blur | string | Amount of blur to apply during the animation | "6px" | +| Prop | Type | Description | Default | +| ------------ | --------------- | ----------------------------------------------------------- | ------- | +| children | React.ReactNode | The content to be animated | | +| className | string | The class name to be applied to the component | | +| variant | object | Custom animation variants for motion component | | +| duration | number | Duration (seconds) for the animation | 0.4 | +| delay | number | Delay (seconds) before the animation starts | 0 | +| offset | number | Offset for the animation | 6 | +| direction | string | Direction for the animation (`up`, `down`, `left`, `right`) | "down" | +| inView | boolean | Whether to trigger animation when component is in view | false | +| inViewMargin | MarginType | Margin for triggering the in-view animation | "-50px" | +| blur | string | Amount of blur to apply during the animation | "6px" | diff --git a/public/r/styles/default/blur-fade.json b/public/r/styles/default/blur-fade.json index 702d72e68..a6e87dd0f 100644 --- a/public/r/styles/default/blur-fade.json +++ b/public/r/styles/default/blur-fade.json @@ -7,7 +7,7 @@ "files": [ { "path": "magicui/blur-fade.tsx", - "content": "\"use client\";\n\nimport { useRef } from \"react\";\nimport {\n AnimatePresence,\n motion,\n useInView,\n UseInViewOptions,\n Variants,\n} from \"framer-motion\";\n\ntype MarginType = UseInViewOptions[\"margin\"];\n\ninterface BlurFadeProps {\n children: React.ReactNode;\n className?: string;\n variant?: {\n hidden: { y: number };\n visible: { y: number };\n };\n duration?: number;\n delay?: number;\n yOffset?: number;\n inView?: boolean;\n inViewMargin?: MarginType;\n blur?: string;\n}\n\nexport default function BlurFade({\n children,\n className,\n variant,\n duration = 0.4,\n delay = 0,\n yOffset = 6,\n inView = false,\n inViewMargin = \"-50px\",\n blur = \"6px\",\n}: BlurFadeProps) {\n const ref = useRef(null);\n const inViewResult = useInView(ref, { once: true, margin: inViewMargin });\n const isInView = !inView || inViewResult;\n const defaultVariants: Variants = {\n hidden: { y: yOffset, opacity: 0, filter: `blur(${blur})` },\n visible: { y: -yOffset, opacity: 1, filter: `blur(0px)` },\n };\n const combinedVariants = variant || defaultVariants;\n return (\n \n \n {children}\n \n \n );\n}\n", + "content": "\"use client\";\n\nimport { useRef } from \"react\";\nimport {\n AnimatePresence,\n motion,\n useInView,\n UseInViewOptions,\n Variants,\n} from \"framer-motion\";\n\ntype MarginType = UseInViewOptions[\"margin\"];\n\ninterface BlurFadeProps {\n children: React.ReactNode;\n className?: string;\n variant?: {\n hidden: { y: number };\n visible: { y: number };\n };\n duration?: number;\n delay?: number;\n offset?: number;\n direction?: \"up\" | \"down\" | \"left\" | \"right\";\n inView?: boolean;\n inViewMargin?: MarginType;\n blur?: string;\n}\n\nexport default function BlurFade({\n children,\n className,\n variant,\n duration = 0.4,\n delay = 0,\n offset = 6,\n direction = \"down\",\n inView = false,\n inViewMargin = \"-50px\",\n blur = \"6px\",\n}: BlurFadeProps) {\n const ref = useRef(null);\n const inViewResult = useInView(ref, { once: true, margin: inViewMargin });\n const isInView = !inView || inViewResult;\n const defaultVariants: Variants = {\n hidden: {\n [direction === \"left\" || direction === \"right\" ? \"x\" : \"y\"]:\n direction === \"right\" || direction === \"down\" ? -offset : offset,\n opacity: 0,\n filter: `blur(${blur})`,\n },\n visible: {\n [direction === \"left\" || direction === \"right\" ? \"x\" : \"y\"]: 0,\n opacity: 1,\n filter: `blur(0px)`,\n },\n };\n const combinedVariants = variant || defaultVariants;\n return (\n \n \n {children}\n \n \n );\n}\n", "type": "registry:ui", "target": "" } diff --git a/public/r/styles/default/dock.json b/public/r/styles/default/dock.json index 08908f201..0c6a94bd3 100644 --- a/public/r/styles/default/dock.json +++ b/public/r/styles/default/dock.json @@ -7,7 +7,7 @@ "files": [ { "path": "magicui/dock.tsx", - "content": "\"use client\";\n\nimport React, { PropsWithChildren, useRef } from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport {\n motion,\n MotionValue,\n useMotionValue,\n useSpring,\n useTransform,\n} from \"framer-motion\";\n\nimport { cn } from \"@/lib/utils\";\n\nexport interface DockProps extends VariantProps {\n className?: string;\n iconSize?: number;\n iconMagnification?: number;\n iconDistance?: number;\n direction?: \"top\" | \"middle\" | \"bottom\";\n children: React.ReactNode;\n}\n\nconst DEFAULT_SIZE = 40;\nconst DEFAULT_MAGNIFICATION = 60;\nconst DEFAULT_DISTANCE = 140;\n\nconst dockVariants = cva(\n \"supports-backdrop-blur:bg-white/10 supports-backdrop-blur:dark:bg-black/10 mx-auto mt-8 flex h-[58px] w-max items-center justify-center gap-2 rounded-2xl border p-2 backdrop-blur-md\",\n);\n\nconst Dock = React.forwardRef(\n (\n {\n className,\n children,\n iconSize = DEFAULT_SIZE,\n iconMagnification = DEFAULT_MAGNIFICATION,\n iconDistance = DEFAULT_DISTANCE,\n direction = \"middle\",\n ...props\n },\n ref,\n ) => {\n const mouseX = useMotionValue(Infinity);\n\n const renderChildren = () => {\n return React.Children.map(children, (child) => {\n if (React.isValidElement(child) && child.type === DockIcon) {\n return React.cloneElement(child, {\n ...child.props,\n mouseX: mouseX,\n size: iconSize,\n magnification: iconMagnification,\n distance: iconDistance,\n });\n }\n return child;\n });\n };\n\n return (\n mouseX.set(e.pageX)}\n onMouseLeave={() => mouseX.set(Infinity)}\n {...props}\n className={cn(dockVariants({ className }), {\n \"items-start\": direction === \"top\",\n \"items-center\": direction === \"middle\",\n \"items-end\": direction === \"bottom\",\n })}\n >\n {renderChildren()}\n \n );\n },\n);\n\nDock.displayName = \"Dock\";\n\nexport interface DockIconProps {\n size?: number;\n magnification?: number;\n distance?: number;\n mouseX?: MotionValue;\n className?: string;\n children?: React.ReactNode;\n props?: PropsWithChildren;\n}\n\nconst DockIcon = ({\n size = DEFAULT_SIZE,\n magnification = DEFAULT_MAGNIFICATION,\n distance = DEFAULT_DISTANCE,\n mouseX,\n className,\n children,\n ...props\n}: DockIconProps) => {\n const ref = useRef(null);\n const padding = Math.max(6, size * 0.2);\n const defaultMouseX = useMotionValue(Infinity);\n\n const distanceCalc = useTransform(mouseX ?? defaultMouseX, (val: number) => {\n const bounds = ref.current?.getBoundingClientRect() ?? { x: 0, width: 0 };\n return val - bounds.x - bounds.width / 2;\n });\n\n const sizeTransform = useTransform(\n distanceCalc,\n [-distance, 0, distance],\n [size, magnification, size],\n );\n\n const scaleSize = useSpring(sizeTransform, {\n mass: 0.1,\n stiffness: 150,\n damping: 12,\n });\n\n return (\n \n {children}\n \n );\n};\n\nDockIcon.displayName = \"DockIcon\";\n\nexport { Dock, DockIcon, dockVariants };\n", + "content": "\"use client\";\n\nimport React, { PropsWithChildren, useRef } from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport {\n motion,\n MotionValue,\n useMotionValue,\n useSpring,\n useTransform,\n MotionProps,\n} from \"framer-motion\";\n\nimport { cn } from \"@/lib/utils\";\n\nexport interface DockProps extends VariantProps {\n className?: string;\n iconSize?: number;\n iconMagnification?: number;\n iconDistance?: number;\n direction?: \"top\" | \"middle\" | \"bottom\";\n children: React.ReactNode;\n}\n\nconst DEFAULT_SIZE = 40;\nconst DEFAULT_MAGNIFICATION = 60;\nconst DEFAULT_DISTANCE = 140;\n\nconst dockVariants = cva(\n \"supports-backdrop-blur:bg-white/10 supports-backdrop-blur:dark:bg-black/10 mx-auto mt-8 flex h-[58px] w-max items-center justify-center gap-2 rounded-2xl border p-2 backdrop-blur-md\",\n);\n\nconst Dock = React.forwardRef(\n (\n {\n className,\n children,\n iconSize = DEFAULT_SIZE,\n iconMagnification = DEFAULT_MAGNIFICATION,\n iconDistance = DEFAULT_DISTANCE,\n direction = \"middle\",\n ...props\n },\n ref,\n ) => {\n const mouseX = useMotionValue(Infinity);\n\n const renderChildren = () => {\n return React.Children.map(children, (child) => {\n if (React.isValidElement(child) && child.type === DockIcon) {\n return React.cloneElement(child, {\n ...child.props,\n mouseX: mouseX,\n size: iconSize,\n magnification: iconMagnification,\n distance: iconDistance,\n });\n }\n return child;\n });\n };\n\n return (\n mouseX.set(e.pageX)}\n onMouseLeave={() => mouseX.set(Infinity)}\n {...props}\n className={cn(dockVariants({ className }), {\n \"items-start\": direction === \"top\",\n \"items-center\": direction === \"middle\",\n \"items-end\": direction === \"bottom\",\n })}\n >\n {renderChildren()}\n \n );\n },\n);\n\nDock.displayName = \"Dock\";\n\nexport interface DockIconProps\n extends Omit, \"children\"> {\n size?: number;\n magnification?: number;\n distance?: number;\n mouseX?: MotionValue;\n className?: string;\n children?: React.ReactNode;\n props?: PropsWithChildren;\n}\n\nconst DockIcon = ({\n size = DEFAULT_SIZE,\n magnification = DEFAULT_MAGNIFICATION,\n distance = DEFAULT_DISTANCE,\n mouseX,\n className,\n children,\n ...props\n}: DockIconProps) => {\n const ref = useRef(null);\n const padding = Math.max(6, size * 0.2);\n const defaultMouseX = useMotionValue(Infinity);\n\n const distanceCalc = useTransform(mouseX ?? defaultMouseX, (val: number) => {\n const bounds = ref.current?.getBoundingClientRect() ?? { x: 0, width: 0 };\n return val - bounds.x - bounds.width / 2;\n });\n\n const sizeTransform = useTransform(\n distanceCalc,\n [-distance, 0, distance],\n [size, magnification, size],\n );\n\n const scaleSize = useSpring(sizeTransform, {\n mass: 0.1,\n stiffness: 150,\n damping: 12,\n });\n\n return (\n \n {children}\n \n );\n};\n\nDockIcon.displayName = \"DockIcon\";\n\nexport { Dock, DockIcon, dockVariants };\n", "type": "registry:ui", "target": "" } diff --git a/registry/default/example/blur-fade-demo.tsx b/registry/default/example/blur-fade-demo.tsx index 30328c8af..e8fefd0e3 100644 --- a/registry/default/example/blur-fade-demo.tsx +++ b/registry/default/example/blur-fade-demo.tsx @@ -1,3 +1,4 @@ +/* eslint-disable @next/next/no-img-element */ import BlurFade from "@/registry/default/magicui/blur-fade"; const images = Array.from({ length: 9 }, (_, i) => { diff --git a/registry/default/example/blur-fade-text-demo.tsx b/registry/default/example/blur-fade-text-demo.tsx index 986a3b2a2..8e6e2f067 100644 --- a/registry/default/example/blur-fade-text-demo.tsx +++ b/registry/default/example/blur-fade-text-demo.tsx @@ -9,7 +9,7 @@ export default function BlurFadeTextDemo() { - + Nice to meet you diff --git a/registry/default/magicui/blur-fade.tsx b/registry/default/magicui/blur-fade.tsx index 44e897ee4..e7216e10d 100644 --- a/registry/default/magicui/blur-fade.tsx +++ b/registry/default/magicui/blur-fade.tsx @@ -20,7 +20,8 @@ interface BlurFadeProps { }; duration?: number; delay?: number; - yOffset?: number; + offset?: number; + direction?: "up" | "down" | "left" | "right"; inView?: boolean; inViewMargin?: MarginType; blur?: string; @@ -32,7 +33,8 @@ export default function BlurFade({ variant, duration = 0.4, delay = 0, - yOffset = 6, + offset = 6, + direction = "down", inView = false, inViewMargin = "-50px", blur = "6px", @@ -41,8 +43,17 @@ export default function BlurFade({ const inViewResult = useInView(ref, { once: true, margin: inViewMargin }); const isInView = !inView || inViewResult; const defaultVariants: Variants = { - hidden: { y: yOffset, opacity: 0, filter: `blur(${blur})` }, - visible: { y: -yOffset, opacity: 1, filter: `blur(0px)` }, + hidden: { + [direction === "left" || direction === "right" ? "x" : "y"]: + direction === "right" || direction === "down" ? -offset : offset, + opacity: 0, + filter: `blur(${blur})`, + }, + visible: { + [direction === "left" || direction === "right" ? "x" : "y"]: 0, + opacity: 1, + filter: `blur(0px)`, + }, }; const combinedVariants = variant || defaultVariants; return ( diff --git a/registry/default/magicui/dock.tsx b/registry/default/magicui/dock.tsx index d59b27e40..13cd7a07a 100644 --- a/registry/default/magicui/dock.tsx +++ b/registry/default/magicui/dock.tsx @@ -27,7 +27,7 @@ const DEFAULT_MAGNIFICATION = 60; const DEFAULT_DISTANCE = 140; const dockVariants = cva( - "supports-backdrop-blur:bg-white/10 supports-backdrop-blur:dark:bg-black/10 mx-auto mt-8 flex h-[58px] w-max items-center justify-center gap-2 rounded-2xl border p-2 backdrop-blur-md" + "supports-backdrop-blur:bg-white/10 supports-backdrop-blur:dark:bg-black/10 mx-auto mt-8 flex h-[58px] w-max items-center justify-center gap-2 rounded-2xl border p-2 backdrop-blur-md", ); const Dock = React.forwardRef( @@ -41,7 +41,7 @@ const Dock = React.forwardRef( direction = "middle", ...props }, - ref + ref, ) => { const mouseX = useMotionValue(Infinity); @@ -75,7 +75,7 @@ const Dock = React.forwardRef( {renderChildren()} ); - } + }, ); Dock.displayName = "Dock"; @@ -112,7 +112,7 @@ const DockIcon = ({ const sizeTransform = useTransform( distanceCalc, [-distance, 0, distance], - [size, magnification, size] + [size, magnification, size], ); const scaleSize = useSpring(sizeTransform, { @@ -127,7 +127,7 @@ const DockIcon = ({ style={{ width: scaleSize, height: scaleSize, padding }} className={cn( "flex aspect-square cursor-pointer items-center justify-center rounded-full", - className + className, )} {...props} >