From 78a49a63033a92ce8b1f66f637f45380c58bd833 Mon Sep 17 00:00:00 2001 From: Hugo ChunHo Lin Date: Sat, 7 Dec 2024 01:28:39 +0800 Subject: [PATCH 1/4] chore(package): bump version to 0.5.1 and add @radix-ui/react-icons dependency (#582) --- apps/web/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/web/package.json b/apps/web/package.json index ebc50cb4..73016f52 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,6 +1,6 @@ { "name": "1chooo-com", - "version": "0.5.0", + "version": "0.5.1", "private": true, "license": "CC-BY-4.0", "author": { @@ -29,6 +29,7 @@ "@next/mdx": "^15.0.3", "@next/third-parties": "^15.0.1", "@primer/octicons-react": "^19.12.0", + "@radix-ui/react-icons": "^1.3.2", "@repo/math": "*", "@repo/ui": "*", "@testing-library/user-event": "^14.5.2", @@ -38,7 +39,6 @@ "@types/react": "^18.2.48", "@types/react-dom": "^18.2.18", "bootstrap": "^5.3.3", - "caniuse-lite": "^1.0.30001653", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cobe": "^0.6.3", From 5e805e5705ddcc610fced7b8f58c00aa362b151a Mon Sep 17 00:00:00 2001 From: Hugo ChunHo Lin Date: Sat, 7 Dec 2024 01:31:04 +0800 Subject: [PATCH 2/4] feat(about): replace SeeMoreButton with AnimatedShinyText for enhanced UI and add animation styles (#587) --- .../src/components/about/latest-articles.tsx | 18 ++++++- .../components/magicui/animated-button.tsx | 47 ------------------- .../magicui/animated-shiny-text.tsx | 43 +++++++++++++++++ apps/web/tailwind.config.js | 29 ++++++++++++ 4 files changed, 88 insertions(+), 49 deletions(-) delete mode 100644 apps/web/src/components/magicui/animated-button.tsx create mode 100644 apps/web/src/components/magicui/animated-shiny-text.tsx diff --git a/apps/web/src/components/about/latest-articles.tsx b/apps/web/src/components/about/latest-articles.tsx index 56ffabfe..9544d890 100644 --- a/apps/web/src/components/about/latest-articles.tsx +++ b/apps/web/src/components/about/latest-articles.tsx @@ -5,9 +5,10 @@ import Link from "next/link"; import Image from "next/image"; import MarkdownRenderer from "@/components/markdown/markdown-renderer"; import { sendGTMEvent } from "@/components/google"; -import SeeMoreButton from "@/components/about/see-more-button"; import { LuEye } from "react-icons/lu"; import { ArrowRightIcon } from "@primer/octicons-react"; +import { cn } from "@/lib/utils"; +import AnimatedShinyText from "@/components/magicui/animated-shiny-text"; import "@/styles/about/latest-posts.css"; @@ -78,7 +79,20 @@ const LatestArticles = ({ posts }: { posts: Post[] }) => { ))} - +
+
+ + + ✨ See More Posts + + + +
+
); }; diff --git a/apps/web/src/components/magicui/animated-button.tsx b/apps/web/src/components/magicui/animated-button.tsx deleted file mode 100644 index 2273a994..00000000 --- a/apps/web/src/components/magicui/animated-button.tsx +++ /dev/null @@ -1,47 +0,0 @@ -'use client' - -import { motion } from 'framer-motion' -import Link from 'next/link' -import type { IconType as ReactIconType } from "react-icons" -import type { Icon as OcticonsType } from "@primer/octicons-react" -import { sendGTMEvent } from "@/components/google" - -type AnimatedButtonProps = { - path: string - bannerText: string - icon: ReactIconType | OcticonsType - onClick?: () => void -} - -const AnimatedButton: React.FC = ({ path, bannerText, icon: Icon, onClick }) => { - const handleClick = (e: React.MouseEvent) => { - if (onClick) { - e.preventDefault() - onClick() - } - sendGTMEvent({ - event: 'animatedButtonClick', - value: 'GTM-PDJ3NF4Q' - }) - } - - return ( - - - - {bannerText} - - - - - - - ) -} - -export default AnimatedButton diff --git a/apps/web/src/components/magicui/animated-shiny-text.tsx b/apps/web/src/components/magicui/animated-shiny-text.tsx new file mode 100644 index 00000000..fb0cdc8b --- /dev/null +++ b/apps/web/src/components/magicui/animated-shiny-text.tsx @@ -0,0 +1,43 @@ +import { CSSProperties, FC, ReactNode } from "react"; + +import { cn } from "@/lib/utils"; + +interface AnimatedShinyTextProps { + children: ReactNode; + className?: string; + shimmerWidth?: number; +} + +/** + * @link https://magicui.design/docs/components/animated-shiny-text + */ +const AnimatedShinyText: FC = ({ + children, + className, + shimmerWidth = 100, +}) => { + return ( +

+ {children} +

+ ); +}; + +export default AnimatedShinyText; diff --git a/apps/web/tailwind.config.js b/apps/web/tailwind.config.js index ecdd1454..478e587c 100644 --- a/apps/web/tailwind.config.js +++ b/apps/web/tailwind.config.js @@ -33,6 +33,35 @@ module.exports = { md: `calc(var(--radius) - 2px)`, sm: "calc(var(--radius) - 4px)", }, + animation: { + "shiny-text": "shiny-text 8s infinite", + gradient: "gradient 8s linear infinite", + marquee: "marquee var(--duration) linear infinite", + "marquee-vertical": "marquee-vertical var(--duration) linear infinite", + }, + keyframes: { + "shiny-text": { + "0%, 90%, 100%": { + "background-position": "calc(-100% - var(--shiny-width)) 0", + }, + "30%, 60%": { + "background-position": "calc(100% + var(--shiny-width)) 0", + }, + }, + gradient: { + to: { + backgroundPosition: "var(--bg-size) 0", + }, + }, + marquee: { + from: { transform: "translateX(0)" }, + to: { transform: "translateX(calc(-100% - var(--gap)))" }, + }, + "marquee-vertical": { + from: { transform: "translateY(0)" }, + to: { transform: "translateY(calc(-100% - var(--gap)))" }, + }, + }, }, }, plugins: [require("tailwindcss-animate")], From 797df0b146612fba061e857edfac29a9fac0806a Mon Sep 17 00:00:00 2001 From: Hugo ChunHo Lin Date: Sat, 7 Dec 2024 01:32:18 +0800 Subject: [PATCH 3/4] feat(gallery): add Gallery page with animated gradient text and blur fade demo components (#588) --- apps/web/src/app/gallery/page.tsx | 23 +++++ .../magicui/animated-gradient-text-demo.tsx | 30 +++++++ .../magicui/animated-gradient-text.tsx | 26 ++++++ .../src/components/magicui/blur-fade-demo.tsx | 26 ++++++ apps/web/src/components/magicui/blur-fade.tsx | 83 +++++++++++++++++++ apps/web/src/config/index.ts | 1 + 6 files changed, 189 insertions(+) create mode 100644 apps/web/src/app/gallery/page.tsx create mode 100644 apps/web/src/components/magicui/animated-gradient-text-demo.tsx create mode 100644 apps/web/src/components/magicui/animated-gradient-text.tsx create mode 100644 apps/web/src/components/magicui/blur-fade-demo.tsx create mode 100644 apps/web/src/components/magicui/blur-fade.tsx diff --git a/apps/web/src/app/gallery/page.tsx b/apps/web/src/app/gallery/page.tsx new file mode 100644 index 00000000..930e8569 --- /dev/null +++ b/apps/web/src/app/gallery/page.tsx @@ -0,0 +1,23 @@ +import type { Metadata } from "next"; +import PageHeader from '@/components/page-header'; +import config from '@/config'; +import { BlurFadeDemo } from "@/components/magicui/blur-fade-demo"; +import { AnimatedGradientTextDemo } from "@/components/magicui/animated-gradient-text-demo"; + +const { title } = config; + +export const metadata: Metadata = { + title: `Gallery | ${title}`, +}; + +const Gallery = async () => { + return ( +
+ + + +
+ ); +}; + +export default Gallery; diff --git a/apps/web/src/components/magicui/animated-gradient-text-demo.tsx b/apps/web/src/components/magicui/animated-gradient-text-demo.tsx new file mode 100644 index 00000000..0130f0a1 --- /dev/null +++ b/apps/web/src/components/magicui/animated-gradient-text-demo.tsx @@ -0,0 +1,30 @@ +import { ChevronRight } from "lucide-react"; +import Link from "next/link"; + +import { cn } from "@/lib/utils"; +import AnimatedGradientText from "@/components/magicui/animated-gradient-text"; + +export async function AnimatedGradientTextDemo() { + return ( +
+ + + 🎉
{" "} + + Thanks for Magic UI! + + + +
+ +
+ ); +} diff --git a/apps/web/src/components/magicui/animated-gradient-text.tsx b/apps/web/src/components/magicui/animated-gradient-text.tsx new file mode 100644 index 00000000..19b0e628 --- /dev/null +++ b/apps/web/src/components/magicui/animated-gradient-text.tsx @@ -0,0 +1,26 @@ +import { ReactNode } from "react"; + +import { cn } from "@/lib/utils"; + +export default function AnimatedGradientText({ + children, + className, +}: { + children: ReactNode; + className?: string; +}) { + return ( +
+
+ + {children} +
+ ); +} diff --git a/apps/web/src/components/magicui/blur-fade-demo.tsx b/apps/web/src/components/magicui/blur-fade-demo.tsx new file mode 100644 index 00000000..e8542845 --- /dev/null +++ b/apps/web/src/components/magicui/blur-fade-demo.tsx @@ -0,0 +1,26 @@ +import BlurFade from "@/components/magicui/blur-fade"; + +const images = Array.from({ length: 9 }, (_, i) => { + const isLandscape = i % 2 === 0; + const width = isLandscape ? 800 : 600; + const height = isLandscape ? 600 : 800; + return `https://picsum.photos/seed/${i + 1}/${width}/${height}`; +}); + +export function BlurFadeDemo() { + return ( +
+
+ {images.map((imageUrl, idx) => ( + + {`Random + + ))} +
+
+ ); +} diff --git a/apps/web/src/components/magicui/blur-fade.tsx b/apps/web/src/components/magicui/blur-fade.tsx new file mode 100644 index 00000000..2b750921 --- /dev/null +++ b/apps/web/src/components/magicui/blur-fade.tsx @@ -0,0 +1,83 @@ +"use client"; + +import { useRef } from "react"; +import { + AnimatePresence, + motion, + useInView, + UseInViewOptions, + Variants, +} from "framer-motion"; + +type MarginType = UseInViewOptions["margin"]; + +interface BlurFadeProps { + children: React.ReactNode; + className?: string; + variant?: { + hidden: { y: number }; + visible: { y: number }; + }; + duration?: number; + delay?: number; + yOffset?: number; + inView?: boolean; + inViewMargin?: MarginType; + blur?: string; +} + +/** + * @example + * + */ + +export default function BlurFade({ + children, + className, + variant, + duration = 0.4, + delay = 0, + yOffset = 6, + inView = false, + inViewMargin = "-50px", + blur = "6px", +}: BlurFadeProps) { + const ref = useRef(null); + 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)` }, + }; + const combinedVariants = variant || defaultVariants; + return ( + + + {children} + + + ); +} diff --git a/apps/web/src/config/index.ts b/apps/web/src/config/index.ts index 8aa071a9..257918de 100644 --- a/apps/web/src/config/index.ts +++ b/apps/web/src/config/index.ts @@ -50,6 +50,7 @@ const config: Config = { { path: '/resume', label: 'Resume' }, { path: '/portfolio', label: 'Portfolio' }, { path: '/post', label: 'Post' }, + { path: '/gallery', label: 'Gallery' }, ], socialLinks: [ { url: `https://github.com/1chooo`, icon: LuGithub, name: 'GitHub' }, From eab921a3c960653b5a53add58f07e966c6af675e Mon Sep 17 00:00:00 2001 From: Hugo ChunHo Lin Date: Sat, 7 Dec 2024 01:33:09 +0800 Subject: [PATCH 4/4] feat(sitemap): update routes to include Gallery page in sitemap (#589) --- apps/web/src/app/sitemap.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/src/app/sitemap.ts b/apps/web/src/app/sitemap.ts index 86e385b3..98443f33 100644 --- a/apps/web/src/app/sitemap.ts +++ b/apps/web/src/app/sitemap.ts @@ -26,7 +26,7 @@ export default async function sitemap() { '/resume', '/portfolio', '/post', - // '/contact' + '/gallery' ].map((route) => ({ url: `https://1chooo.com${route}`, lastModified: new Date().toISOString().split('T')[0],