add main stage card links and interactions

This commit is contained in:
Francesco Sansalvadore committed 2025-07-11 15:46:23 +02:00
1 parent 896fc68092
commit d1763db786
3 files changed
+104 -13

No files matched your search

@@ -10,6 +10,7 @@ import SectionContainer from 'components/Layouts/SectionContainer'
import { mainDays, WeekDayProps } from './data'
import { useWindowSize } from 'react-use'
import { useBreakpoint } from 'common'
import { DayLink } from './lw15.components'
const LW15MainStage = ({ className }: { className?: string }) => {
const { resolvedTheme } = useTheme()
@@ -50,7 +51,9 @@ const DayCard = ({ day }: { day: WeekDayProps }) =>
<div></div>
<div className="flex flex-col gap-2 p-4">
<span className="text-xs text-foreground-lighter">{day.date}</span>
<h4 className="text-lg leading-snug text-foreground-light">&#91; Access locked &#93;</h4>
<h4 className="text-lg leading-snug text-foreground-lighter">
&#91; Access locked &#93;
</h4>
</div>
</div>
</div>
@@ -68,19 +71,27 @@ const DayCardShipped = ({ day }: { day: WeekDayProps }) => {
const { height } = hiddenRef.current.getBoundingClientRect()
setHiddenHeight(height + padding)
}
console.log(hiddenHeight)
}, [hiddenRef, width])
return (
<div
className={cn(
'group/main block w-full h-full xl:flex-1 xl:h-auto xl:aspect-[217/275] relative overflow-hidden rounded border hover:border-black dark:hover:border-stronger text-white'
'group/main block w-full h-full xl:flex-1 xl:h-auto xl:aspect-[217/275] relative overflow-hidden rounded border border-strong text-white',
day.isToday && 'ring-1 ring-foreground-lighter ring-offset-2 ring-offset-background'
)}
>
<CardBG day={day} />
<div className="w-full h-full relative z-10 flex flex-col justify-between gap-4 overflow-hidden">
<div></div>
<ul className="flex flex-col gap-1 p-4">
{day.links?.map((link) => (
<li key={link.href}>
<DayLink
{...link}
className="transition-all duration-300 !ease-[.25,.25,0,1] lg:-translate-y-full lg:opacity-0 group-hover/main:translate-y-0 group-hover/main:opacity-100"
/>
</li>
))}
</ul>
<div
className="flex flex-col p-4 gap-2 relative group-hover/main:!bottom-0 !ease-[.25,.25,0,1] duration-300"
style={{
@@ -90,7 +101,7 @@ const DayCardShipped = ({ day }: { day: WeekDayProps }) => {
<span className="text-xs opacity-60">{day.date}</span>
<h4 className="text-lg leading-snug">{day.title}</h4>
<div
className="block lg:opacity-0 blur-lg duration-300 group-hover/main:lg:blur-none transition-all group-hover/main:lg:opacity-100"
className="block lg:opacity-0 lg:blur-lg duration-300 group-hover/main:lg:blur-none transition-all group-hover/main:lg:opacity-100"
ref={hiddenRef}
>
<Button type="outline" size="small" className="text-current rounded-sm border-dashed">
@@ -114,7 +125,7 @@ const CardBG = ({ day }: { day: WeekDayProps }) => (
className={cn(
'absolute inset-0 w-full h-full -z-10',
'transition-all duration-300 !ease-[.24,0,.22,.99]',
'dark:opacity-40 scale-100',
'dark:opacity-50 scale-100',
'group-hover/main:dark:opacity-100'
)}
>
@@ -134,7 +145,7 @@ const CardBG = ({ day }: { day: WeekDayProps }) => (
)}
</>
))}
<div className="absolute inset-0 z-0 w-full h-full bg-gradient-to-b from-black/30 to-black/90" />
<div className="absolute inset-0 z-0 w-full h-full bg-gradient-to-b from-black/80 via-black/30 to-black/90" />
</div>
)
@@ -62,7 +62,7 @@ const days: (isDark?: boolean) => WeekDayProps[] = (isDark = true) => [
d: 1,
dd: 'Mon',
shipped: true,
isToday: false,
isToday: true,
hasCountdown: false,
blog: '/blog/',
date: 'Monday, 14th',
@@ -96,7 +96,7 @@ const days: (isDark?: boolean) => WeekDayProps[] = (isDark = true) => [
id: 'day-2',
d: 2,
dd: 'Tue',
shipped: true,
shipped: false,
isToday: false,
hasCountdown: false,
blog: '/blog/',
@@ -131,8 +131,8 @@ const days: (isDark?: boolean) => WeekDayProps[] = (isDark = true) => [
id: 'day-3',
d: 3,
dd: 'Wed',
shipped: true,
isToday: true,
shipped: false,
isToday: false,
hasCountdown: false,
blog: '/blog/',
date: 'Wednesday, 16th',
@@ -1,5 +1,11 @@
import { useEffect, useState } from 'react'
import { IconDocumentation, IconMicSolid, IconProductHunt, IconYoutubeSolid, cn } from 'ui'
import { Music } from 'lucide-react'
import Link from 'next/link'
import { StepLink } from './data/lw15_data'
import { ExpandableVideo } from 'ui-patterns/ExpandableVideo'
import { useTheme } from 'next-themes'
import { cn } from 'ui'
export const LWSVG = (props: React.SVGProps<SVGSVGElement>) => {
return (
@@ -68,3 +74,77 @@ export const LW15ThemeSwitcher = ({
</div>
)
}
interface DayLink extends StepLink {
className?: string
}
export const DayLink = ({ type, icon, text, href = '', className }: DayLink) => {
const [isMounted, setIsMounted] = useState(false)
useEffect(() => {
setIsMounted(true)
}, [])
if (!isMounted) return null
const linkTypes = {
blog: {
icon: IconDocumentation,
text: 'Blog Post',
},
docs: {
icon: IconDocumentation,
text: 'Docs',
},
productHunt: {
icon: IconProductHunt,
text: 'Product Hunt',
},
video: {
icon: IconYoutubeSolid,
text: 'Watch video',
},
podcast: {
icon: Music,
text: 'Podcast',
},
xSpace: {
icon: IconMicSolid,
text: 'X Space',
},
}
const isTargetBlank = () => {
switch (type) {
case 'productHunt':
case 'xSpace':
case 'docs':
return true
}
}
const Text = () => <>{text ?? linkTypes[type]?.text}</>
const Component = type === 'video' ? 'div' : Link
const Trigger = ({ component: Comp, ...props }: any) => (
<Comp
className={cn(
'py-1 flex gap-2 items-center text-foreground-light hover:text-foreground transition-colors text-sm !leading-none',
className
)}
{...props}
>
<span className="w-1.5 h-1.5 bg-current flex items-center justify-center" />
<Text />
</Comp>
)
if (type === 'video')
return <ExpandableVideo videoId={href} trigger={<Trigger component={Component} />} />
return <Trigger href={href} target={isTargetBlank() ? '_blank' : '_self'} component={Component} />
}
export default {
DayLink,
}