Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: "How it works" section on landing page is broken #49 #50

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions components.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
"hooks": "@/hooks",
"form": "@/components/form"
}
}
}
268 changes: 74 additions & 194 deletions components/features-vertical.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import React, {

import { cn } from '@/lib/utils'
import Safari from './safari'
import { Card, CardContent } from './ui/card'

type AccordionItemProps = {
children: React.ReactNode
Expand Down Expand Up @@ -88,19 +89,15 @@ export type FeaturesDataProps = {

export type FeaturesProps = {
collapseDelay?: number
ltr?: boolean
linePosition?: 'left' | 'right' | 'top' | 'bottom'
data: FeaturesDataProps[]
}

export default function Features({
collapseDelay = 5000,
ltr = false,
linePosition = 'left',
data = [],
}: FeaturesProps) {
const [currentIndex, setCurrentIndex] = useState<number>(-1)
const carouselRef = useRef<HTMLUListElement>(null)
const carouselRef = useRef<HTMLDivElement>(null)
const ref = useRef(null)
const isInView = useInView(ref, {
once: true,
Expand All @@ -115,7 +112,6 @@ export default function Features({
setCurrentIndex(-1)
}
}, 100)

return () => clearTimeout(timer)
}, [isInView])

Expand All @@ -138,213 +134,97 @@ export default function Features({
}
}

// interval for changing images
useEffect(() => {
const timer = setInterval(() => {
setCurrentIndex((prevIndex) =>
prevIndex !== undefined ? (prevIndex + 1) % data.length : 0,
)
}, collapseDelay)

return () => clearInterval(timer)
}, [collapseDelay, data.length])

useEffect(() => {
if (data.length <= currentIndex) { // Only the case when you change data.length at runtime and you data.length goes <= currentIndex then we should reset our carousel.
setCurrentIndex(0);
return;
}
const handleAutoScroll = () => {
const nextIndex =
(currentIndex !== undefined ? currentIndex + 1 : 0) % data.length
setCurrentIndex(nextIndex)
scrollToIndex(nextIndex)
}

const autoScrollTimer = setInterval(handleAutoScroll, collapseDelay)

return () => clearInterval(autoScrollTimer)
}, [currentIndex, collapseDelay, data.length])

useEffect(() => {
const carousel = carouselRef.current
if (carousel) {
const handleScroll = () => {
const scrollLeft = carousel.scrollLeft
const cardWidth = carousel.querySelector('.card')?.clientWidth || 0
const newIndex = Math.min(
Math.floor(scrollLeft / cardWidth),
data.length - 1,
)
setCurrentIndex(newIndex)
}

carousel.addEventListener('scroll', handleScroll)
return () => carousel.removeEventListener('scroll', handleScroll)
}
}, [data.length])

return (
<section ref={ref} id="features">
<section ref={ref} id="features" className="flex justify-center">
<div className="container">
<div className="max-w-6xl mx-auto">
<div className="mx-auto my-12 h-full grid lg:grid-cols-2 gap-10 items-center">
<div
className={` hidden lg:flex order-1 lg:order-[0] ${
ltr ? 'lg:order-2 lg:justify-end' : 'justify-start'
}`}
>
<Accordion.Root
className=""
type="single"
defaultValue={`item-${currentIndex}`}
value={`item-${currentIndex}`}
onValueChange={(value) =>
setCurrentIndex(Number(value.split('-')[1]))
}
>
{data.map((item, index) => (
<AccordionItem
key={item.id}
className="relative mb-8 last:mb-0"
value={`item-${index}`}
<div className="mx-auto my-12 h-full grid grid-rows-auto lg:grid-rows-1 grid-cols-1 lg:grid-cols-2 lg:gap-10 items-center grid-flow-dense">
<div ref={carouselRef} className="overflow-x-auto flex lg:flex-col gap-8 lg:gap-0 snap-x order-2 lg:order-1 [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden snap-mandatory">
{data.map((item, index) => (
<Card key={item.id} className="card bg-background border-none shadow-none min-w-64" onClick={() => setCurrentIndex(index)}>
<CardContent className="relative p-0 pt-6 lg:pt-0 lg:mb-6 overflow-visible">
<div
className={`absolute left-0 top-0 right-0 lg:bottom-0 w-full lg:w-0.5 h-0.5 lg:h-full rounded-lg bg-neutral-300/50 dark:bg-neutral-300/30`}
>
{linePosition === 'left' || linePosition === 'right' ? (
<div
className={`absolute bottom-0 top-0 h-full w-0.5 overflow-hidden rounded-lg bg-neutral-300/50 dark:bg-neutral-300/30 ${
linePosition === 'right'
? 'left-auto right-0'
: 'left-0 right-auto'
}`}
>
<div
className={`absolute left-0 top-0 w-full ${
currentIndex === index ? 'h-full' : 'h-0'
} origin-top bg-primary transition-all ease-linear dark:bg-white`}
style={{
transitionDuration:
currentIndex === index
? `${collapseDelay}ms`
: '0s',
}}
></div>
</div>
) : null}

{linePosition === 'top' || linePosition === 'bottom' ? (
<div
className={`absolute left-0 right-0 w-full h-0.5 overflow-hidden rounded-lg bg-neutral-300/50 dark:bg-neutral-300/30 ${
linePosition === 'bottom' ? 'bottom-0' : 'top-0'
}`}
>
<div
className={`absolute left-0 ${
linePosition === 'bottom' ? 'bottom-0' : 'top-0'
} h-full ${
currentIndex === index ? 'w-full' : 'w-0'
} origin-left bg-primary transition-all ease-linear dark:bg-white`}
style={{
transitionDuration:
currentIndex === index
? `${collapseDelay}ms`
: '0s',
}}
></div>
</div>
) : null}

<div className="flex items-center relative">
<div className="item-box w-12 h-12 bg-primary/10 rounded-full sm:mx-6 mx-2 shrink-0 flex items-center justify-center">
{item.icon}
</div>

<div>
<AccordionTrigger className="text-xl font-bold">
{item.title}
</AccordionTrigger>

<AccordionTrigger className="justify-start text-left leading-4 font-sans text-[16px]">
{item.content}
</AccordionTrigger>
</div>
</div>
</AccordionItem>
))}
</Accordion.Root>
</div>
<div
className={`h-[350px] min-h-[150px] w-auto flex justify-center ${
ltr && 'lg:order-1'
}`}
>
{data[currentIndex]?.image ? (
// <motion.img
// key={currentIndex}
// src={data[currentIndex].image}
// alt="feature"
// className="aspect-auto h-full w-full rounded-xl border border-neutral-300/50 object-cover object-left-top p-1 shadow-lg"
// initial={{ opacity: 0, scale: 0.98 }}
// animate={{ opacity: 1, scale: 1 }}
// exit={{ opacity: 0, scale: 0.98 }}
// transition={{ duration: 0.25, ease: "easeOut" }}
// />
<motion.div
initial={{ opacity: 0, scale: 0.98 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.98 }}
transition={{ duration: 0.25, ease: 'easeOut' }}
className='w-auto h-fit'
>
<Safari
key={currentIndex}
src={data[currentIndex].image}
url="https://acme.ai"
className="aspect-auto h-full w-full rounded-xl border border-neutral-300/50 object-cover object-left-top p-1 shadow-lg"
/>
</motion.div>
) : data[currentIndex]?.video ? (
<video
preload="auto"
src={data[currentIndex].video}
className="aspect-auto h-full w-full rounded-lg object-cover shadow-lg"
autoPlay
loop
muted
/>
) : (
<div className="aspect-auto h-full w-full rounded-xl border border-neutral-300/50 bg-gray-200 p-1"></div>
)}
</div>

<ul
ref={carouselRef}
className=" flex h-full snap-x flex-nowrap overflow-x-auto py-10 [-ms-overflow-style:none] [-webkit-mask-image:linear-gradient(90deg,transparent,black_20%,white_80%,transparent)] [mask-image:linear-gradient(90deg,transparent,black_20%,white_80%,transparent)] [scrollbar-width:none] lg:hidden [&::-webkit-scrollbar]:hidden snap-mandatory"
style={{
padding: '50px calc(50%)',
}}
>
{data.map((item, index) => (
<div
key={item.id}
className="card relative mr-8 grid h-full max-w-60 shrink-0 items-start justify-center py-4 last:mr-0"
onClick={() => setCurrentIndex(index)}
style={{
scrollSnapAlign: 'center',
}}
>
<div className="absolute bottom-0 left-0 right-auto top-0 h-0.5 w-full overflow-hidden rounded-lg bg-neutral-300/50 dark:bg-neutral-300/30">
<div
className={`absolute left-0 top-0 h-full ${
currentIndex === index ? 'w-full' : 'w-0'
} origin-top bg-primary transition-all ease-linear`}
className={`absolute left-0 right-0 lg:bottom-0 lg:top-0 ${currentIndex === index ? 'w-full h-full' : 'w-0 h-0'
} origin-left bg-primary transition-all ease-linear dark:bg-white`}
style={{
transitionDuration:
currentIndex === index ? `${collapseDelay}ms` : '0s',
currentIndex === index
? `${collapseDelay}ms`
: '0s',
}}
></div>
</div>
<h2 className="text-xl font-bold">{item.title}</h2>
<p className="mx-0 max-w-sm text-balance text-sm">
{item.content}
</p>
</div>
))}
</ul>
<div className='flex lg:items-center'>
<div className="hidden lg:flex item-box w-12 h-12 bg-primary/10 rounded-full sm:mx-6 mx-2 shrink-0 items-center justify-center">
{item.icon}
</div>
<div className='px-5'>
<h3 className="text-xl font-semibold">{item.title}</h3>
<p className="text-base font-sans leading-6 text-muted-foreground">{item.content}</p>
</div>
</div>
</CardContent>
</Card>
))}
</div>

<div
className={`lg:h-[350px] lg:min-h-[150px] w-auto flex justify-center order-1 lg:order-2`}
>
{data[currentIndex]?.image ? (
// <motion.img
// key={currentIndex}
// src={data[currentIndex].image}
// alt="feature"
// className="aspect-auto h-full w-full rounded-xl border border-neutral-300/50 object-cover object-left-top p-1 shadow-lg"
// initial={{ opacity: 0, scale: 0.98 }}
// animate={{ opacity: 1, scale: 1 }}
// exit={{ opacity: 0, scale: 0.98 }}
// transition={{ duration: 0.25, ease: "easeOut" }}
// />
<motion.div
initial={{ opacity: 0, scale: 0.98 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.98 }}
transition={{ duration: 0.25, ease: 'easeOut' }}
className='w-auto h-fit'
>
<Safari
key={currentIndex}
src={data[currentIndex].image}
url="https://acme.ai"
className="aspect-auto h-full w-full rounded-xl border border-neutral-300/50 object-cover object-left-top p-1 shadow-lg"
/>
</motion.div>
) : data[currentIndex]?.video ? (
<video
preload="auto"
src={data[currentIndex].video}
className="aspect-auto h-full w-full rounded-lg object-cover shadow-lg"
autoPlay
loop
muted
/>
) : (
<div className="aspect-auto h-full w-full rounded-xl border border-neutral-300/50 bg-gray-200 p-1"></div>
)}
</div>
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions components/footer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ export function Footer() {
<footer className="max-w-5xl mx-auto flex flex-col gap-y-3 pt-10 pb-5 px-5 lg:px-0">
<div className="flex items-center justify-between">
<div className="flex items-center gap-x-2">
<Link href="/" className="cursor-pointer">
<Logo />
<Link href="/" className="cursor-pointer dark:bg-white dark:rounded-lg p-1">
<Logo className="w-9 h-9" />
</Link>
<h2 className="font-semibold text-neutral-900 dark:text-white">
Shadcn Form Builder
Expand Down
2 changes: 1 addition & 1 deletion components/section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default function Section({
</h2>
)}
{subtitle && (
<h3 className="mx-auto mt-4 max-w-xs text-3xl font-semibold sm:max-w-none sm:text-4xl md:text-5xl">
<h3 className="mx-auto mt-4 font-semibold sm:max-w-none text-2xl sm:text-3xl md:text-5xl">
{subtitle}
</h3>
)}
Expand Down
12 changes: 6 additions & 6 deletions components/sections/hero/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,14 @@ function HeroPill() {
initial={{ opacity: 0, y: -20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, ease }}
className="flex items-center"
className="flex items-center justify-center w-full"
>
<div className="space-y-3">
<div className="w-full space-y-3">
<p className="text-center text-xs text-muted-foreground">
Last Update {stats.lastUpdate}
</p>
<div className="flex flex-col md:flex-row gap-3 md:gap-5">
<div className="flex flex-row items-center justify-center w-full">
<div className="flex flex-wrap justify-center gap-5 w-full">
<div className="flex flex-row items-center justify-center">
<AnimatedTooltip items={sponsors} />
</div>
<div className={cn('z-10 flex -space-x-12 rtl:space-x-reverse')}>
Expand All @@ -123,7 +123,7 @@ function HeroPill() {
className="h-10 cursor-pointer flex w-auto items-center space-x-1 rounded-full bg-muted px-3 group border-2 border-white whitespace-pre shadow hover:shadow-lg"
>
<p className="font-medium text-primary text-sm">
Star Project on GitHub
<span className='hidden sm:inline'>Star Project on{" "}</span>GitHub
</p>
<div className="flex items-center rounded-full px-2 py-1 text-center font-medium text-sm ">
<StarIcon />
Expand Down Expand Up @@ -265,7 +265,7 @@ export default function HeroSection() {
<HeroTitles />
<HeroCTA />
<HeroImage />
<div className="pointer-events-none absolute inset-x-0 -bottom-12 h-1/3 bg-gradient-to-t from-background via-background to-transparent lg:h-1/4"></div>
<div className=" pointer-events-none absolute inset-x-0 -bottom-12 h-1/5 sm:h-1/4 bg-gradient-to-t from-background via-background to-transparent"></div>
</div>
</section>
)
Expand Down
1 change: 1 addition & 0 deletions components/sections/testimonials.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export default function Testimonials() {
delay: Math.random() * 0.8,
duration: 1.2,
}}
className='flex justify-center'
>
{/* <TestimonialCard {...card} /> */}
<ClientTweetCard id={tweet} />
Expand Down
Loading