diff options
Diffstat (limited to 'src/app/(main)/(home)/_components')
| -rw-r--r-- | src/app/(main)/(home)/_components/call-to-action.tsx | 23 | ||||
| -rw-r--r-- | src/app/(main)/(home)/_components/hero.tsx | 98 | ||||
| -rw-r--r-- | src/app/(main)/(home)/_components/posts.tsx | 41 |
3 files changed, 162 insertions, 0 deletions
diff --git a/src/app/(main)/(home)/_components/call-to-action.tsx b/src/app/(main)/(home)/_components/call-to-action.tsx new file mode 100644 index 0000000..b75298e --- /dev/null +++ b/src/app/(main)/(home)/_components/call-to-action.tsx @@ -0,0 +1,23 @@ +import { NewsletterForm } from '@/components/newsletter-form'; +import { Section } from '@/components/section'; +import type React from 'react'; + +export function CTA(): React.ReactElement { + return ( + <Section className='relative grid gap-8 px-4 py-10 sm:grid-cols-2 md:py-14 lg:px-6 lg:py-16'> + <div className='max-w-xl space-y-2'> + <h2 className='font-semibold text-2xl md:text-3xl lg:text-4xl'> + Subscribe to the Newsletter + </h2> + <p className='text-muted-foreground text-sm md:text-base'> + Get the latest articles and updates delivered straight to your inbox. + No spam, unsubscribe anytime. + </p> + </div> + + <div className='flex w-full items-center'> + <NewsletterForm /> + </div> + </Section> + ); +} diff --git a/src/app/(main)/(home)/_components/hero.tsx b/src/app/(main)/(home)/_components/hero.tsx new file mode 100644 index 0000000..04371ca --- /dev/null +++ b/src/app/(main)/(home)/_components/hero.tsx @@ -0,0 +1,98 @@ +import { baseOptions, linkItems } from '@/app/(main)/layout.config'; +import { Icons } from '@/components/icons/icons'; +import { Section } from '@/components/section'; +import { buttonVariants } from '@/components/ui/button'; +import { cn } from '@/lib/utils'; +import { getLinks } from 'fumadocs-ui/layouts/shared'; +import * as motion from 'motion/react-client'; +import Image from 'next/image'; +import Link from 'next/link'; +import Balancer from 'react-wrap-balancer'; +import heroImage from '../../../../../public/images/gradient-noise-purple-azure-light.png'; + +const Hero = () => { + const links = getLinks(linkItems, baseOptions.githubUrl); + const navItems = links.filter((item) => + ['nav', 'all'].includes(item.on ?? 'all'), + ); + + return ( + <Section className='relative flex flex-col items-center justify-center gap-6 overflow-hidden bg-dashed px-4 py-16 sm:px-16 sm:py-24 md:py-32'> + <motion.div + initial={{ opacity: 0 }} + animate={{ opacity: 1 }} + transition={{ + duration: 0.4, + scale: { type: 'spring', visualDuration: 0.4, bounce: 0.5 }, + }} + whileInView={{ opacity: 1 }} + viewport={{ once: true }} + className='-z-10 absolute inset-0 h-full w-full' + > + <Image + src={heroImage} + alt='Hero Background' + height={600} + width={704} + className='pointer-events-none absolute right-0 bottom-0 h-[900px] w-[1004px] max-w-[1004px] translate-x-1/2 translate-y-1/2 select-none opacity-80 dark:opacity-100' + priority + /> + </motion.div> + <div className='flex items-center justify-center space-x-2'> + <Icons.code className='h-6 w-6 text-primary transition-transform hover:scale-125' /> + <span className='font-medium text-muted-foreground text-sm'> + Full-Stack Developer & Tech Writer + </span> + </div> + <h1 className='max-w-3xl text-center font-bold text-4xl leading-tight tracking-tighter sm:text-5xl md:max-w-4xl md:text-6xl lg:leading-[1.1]'> + <Balancer>I'm John Doe , a Full-Stack Developer.</Balancer> + </h1> + <p className='max-w-xl text-center text-muted-foreground md:max-w-2xl md:text-lg'> + <Balancer> + I write about web development, software engineering, and the latest + technologies. I also create fun projects and tutorials to help you + learn and grow as a developer. + </Balancer> + </p> + + <div className='flex flex-wrap items-center justify-center gap-4'> + <Link + className={cn( + buttonVariants({ + variant: 'default', + size: 'lg', + }), + 'group rounded-full bg-primary hover:bg-primary/90', + )} + href='/posts' + > + Browse Posts + <Icons.arrowUpRight className='group-hover:-rotate-12 ml-2 size-5 transition-transform' /> + </Link> + + <div className='flex items-center space-x-4'> + {navItems + .filter((item) => item.type === 'icon') + .map((item, i) => ( + <Link + key={i.toString()} + href={item.url} + className={cn( + buttonVariants({ + variant: 'ghost', + size: 'icon', + }), + 'rounded-full', + )} + > + {item.icon} + <span className='sr-only'>{item.text}</span> + </Link> + ))} + </div> + </div> + </Section> + ); +}; + +export default Hero; diff --git a/src/app/(main)/(home)/_components/posts.tsx b/src/app/(main)/(home)/_components/posts.tsx new file mode 100644 index 0000000..0eacce1 --- /dev/null +++ b/src/app/(main)/(home)/_components/posts.tsx @@ -0,0 +1,41 @@ +import { Icons } from '@/components/icons/icons'; +import { PostCard } from '@/components/posts/post-card'; +import { Section } from '@/components/section'; +import { buttonVariants } from '@/components/ui/button'; +import type { BlogPost } from '@/lib/payload-posts'; +import Link from 'next/link'; + +interface PostsProps { + posts: BlogPost[]; +} + +export default function Posts({ posts }: PostsProps) { + return ( + <Section> + <div className='grid divide-y divide-dashed divide-border/70 text-left dark:divide-border'> + {posts.map((post) => ( + <PostCard + title={post.title} + description={post.description} + image={post.image} + url={post.url} + date={post.date.toDateString()} + key={post.id} + author={post.author} + tags={post.tags} + /> + ))} + <Link + href='/posts' + className={buttonVariants({ + variant: 'default', + className: 'group rounded-none py-4 sm:py-8', + })} + > + View More + <Icons.arrowUpRight className='group-hover:-rotate-12 ml-2 size-5 transition-transform' /> + </Link> + </div> + </Section> + ); +} |
