mirror of
https://github.com/supabase/supabase.git
synced 2026-10-08 19:05:06 +03:00
Merge pull request #16308 from supabase/chore/update-lw-page
Chore/update lw page
This commit is contained in:
6 files changed
+168
-134
No files matched your search
@@ -3,64 +3,93 @@ import { SmallCard } from './components'
|
||||
import Link from 'next/link'
|
||||
import Image from 'next/image'
|
||||
import days from './lw8_data'
|
||||
import { ExpandableVideo } from 'ui'
|
||||
|
||||
const LWAnnouncement = ({ title }: { title?: string }) => {
|
||||
const LWAnnouncement = ({
|
||||
title,
|
||||
isLaunchWeekPage,
|
||||
}: {
|
||||
title?: string
|
||||
isLaunchWeekPage?: boolean
|
||||
}) => {
|
||||
if (typeof document === 'undefined') return null
|
||||
const [_pre, d1, _d2, _d3, _d4, _d5] = days
|
||||
const today = document.getElementById('today')
|
||||
|
||||
const announcement = (
|
||||
<>
|
||||
<div className="relative flex-shrink flex items-center p-2 w-2/3 md:w-auto">
|
||||
<div className="flex flex-col gap-1 sm:pl-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className={['hidden sm:flex min-w-[20px] opacity-50', 'opacity-pulse'].join(' ')}>
|
||||
<svg
|
||||
width="21"
|
||||
height="21"
|
||||
viewBox="0 0 21 21"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M5.55025 3.97258C5.94078 4.36311 5.94078 4.99627 5.55025 5.38679C2.81658 8.12046 2.81658 12.5526 5.55025 15.2863C5.94078 15.6768 5.94078 16.31 5.55025 16.7005C5.15973 17.091 4.52656 17.091 4.13604 16.7005C0.62132 13.1858 0.62132 7.4873 4.13604 3.97258C4.52656 3.58206 5.15973 3.58206 5.55025 3.97258ZM15.4498 3.97281C15.8403 3.58229 16.4735 3.58229 16.864 3.97281C20.3787 7.48753 20.3787 13.186 16.864 16.7007C16.4735 17.0913 15.8403 17.0913 15.4498 16.7007C15.0592 16.3102 15.0592 15.677 15.4498 15.2865C18.1834 12.5529 18.1834 8.1207 15.4498 5.38703C15.0592 4.9965 15.0592 4.36334 15.4498 3.97281ZM8.37869 6.80101C8.76921 7.19153 8.76921 7.8247 8.37869 8.21522C7.20711 9.38679 7.20711 11.2863 8.37869 12.4579C8.76921 12.8484 8.76921 13.4816 8.37868 13.8721C7.98816 14.2626 7.355 14.2626 6.96447 13.8721C5.01185 11.9195 5.01185 8.75363 6.96447 6.80101C7.355 6.41048 7.98816 6.41048 8.37869 6.80101ZM12.6213 6.80124C13.0119 6.41072 13.645 6.41072 14.0355 6.80124C15.9882 8.75386 15.9882 11.9197 14.0355 13.8723C13.645 14.2628 13.0119 14.2628 12.6213 13.8723C12.2308 13.4818 12.2308 12.8486 12.6213 12.4581C13.7929 11.2865 13.7929 9.38703 12.6213 8.21545C12.2308 7.82493 12.2308 7.19176 12.6213 6.80124ZM10.5 9.33677C11.0523 9.33677 11.5 9.78449 11.5 10.3368V10.3468C11.5 10.8991 11.0523 11.3468 10.5 11.3468C9.94772 11.3468 9.5 10.8991 9.5 10.3468V10.3368C9.5 9.78449 9.94772 9.33677 10.5 9.33677Z"
|
||||
fill="#F2F2F2"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<span className="text-foreground">{title ?? 'Launch Week 8: Day 1'}</span>
|
||||
</div>
|
||||
<span className="text-foreground-light">{d1.steps[0].title}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative flex items-center justify-center !aspect-video h-[80px] md:h-[80px] gap-2 z-10 rounded overflow-hidden">
|
||||
<div className="absolute z-10 w-4 h-4 text-white opacity-70">
|
||||
<svg viewBox="0 0 81 91" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M76.5621 37.998C82.3369 41.3321 82.3369 49.6673 76.5621 53.0014L13.2198 89.5721C7.44504 92.9062 0.226562 88.7386 0.226562 82.0704L0.226566 8.92901C0.226566 2.26085 7.44506 -1.90673 13.2199 1.42735L76.5621 37.998Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<Image
|
||||
src="/images/launchweek/8/lw8-yt-thumb.jpg"
|
||||
alt="Youtube video thumbnail"
|
||||
layout="fill"
|
||||
objectFit="cover"
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
|
||||
const handleClick = (e: any) => {
|
||||
if (!today) return
|
||||
today.scrollIntoView({ behavior: 'smooth' })
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full max-w-xl opacity-0 !animate-[fadeIn_0.5s_cubic-bezier(0.25,0.25,0,1)_0.5s_both]">
|
||||
<SmallCard
|
||||
className="border hover:border-scale-800 transition-colors"
|
||||
innerClassName="bg-opacity-70"
|
||||
innerClassName="bg-opacity-70 items-stretch"
|
||||
>
|
||||
<Link href="/launch-week#today">
|
||||
<a className="flex flex-row justify-between items-center w-full h-full gap-2 text-left">
|
||||
<div className="relative flex-shrink flex items-center p-2 w-2/3 md:w-auto">
|
||||
<div className="flex flex-col gap-1 sm:pl-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<div
|
||||
className={['hidden sm:flex min-w-[20px] opacity-50', 'opacity-pulse'].join(
|
||||
' '
|
||||
)}
|
||||
>
|
||||
<svg
|
||||
width="21"
|
||||
height="21"
|
||||
viewBox="0 0 21 21"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M5.55025 3.97258C5.94078 4.36311 5.94078 4.99627 5.55025 5.38679C2.81658 8.12046 2.81658 12.5526 5.55025 15.2863C5.94078 15.6768 5.94078 16.31 5.55025 16.7005C5.15973 17.091 4.52656 17.091 4.13604 16.7005C0.62132 13.1858 0.62132 7.4873 4.13604 3.97258C4.52656 3.58206 5.15973 3.58206 5.55025 3.97258ZM15.4498 3.97281C15.8403 3.58229 16.4735 3.58229 16.864 3.97281C20.3787 7.48753 20.3787 13.186 16.864 16.7007C16.4735 17.0913 15.8403 17.0913 15.4498 16.7007C15.0592 16.3102 15.0592 15.677 15.4498 15.2865C18.1834 12.5529 18.1834 8.1207 15.4498 5.38703C15.0592 4.9965 15.0592 4.36334 15.4498 3.97281ZM8.37869 6.80101C8.76921 7.19153 8.76921 7.8247 8.37869 8.21522C7.20711 9.38679 7.20711 11.2863 8.37869 12.4579C8.76921 12.8484 8.76921 13.4816 8.37868 13.8721C7.98816 14.2626 7.355 14.2626 6.96447 13.8721C5.01185 11.9195 5.01185 8.75363 6.96447 6.80101C7.355 6.41048 7.98816 6.41048 8.37869 6.80101ZM12.6213 6.80124C13.0119 6.41072 13.645 6.41072 14.0355 6.80124C15.9882 8.75386 15.9882 11.9197 14.0355 13.8723C13.645 14.2628 13.0119 14.2628 12.6213 13.8723C12.2308 13.4818 12.2308 12.8486 12.6213 12.4581C13.7929 11.2865 13.7929 9.38703 12.6213 8.21545C12.2308 7.82493 12.2308 7.19176 12.6213 6.80124ZM10.5 9.33677C11.0523 9.33677 11.5 9.78449 11.5 10.3368V10.3468C11.5 10.8991 11.0523 11.3468 10.5 11.3468C9.94772 11.3468 9.5 10.8991 9.5 10.3468V10.3368C9.5 9.78449 9.94772 9.33677 10.5 9.33677Z"
|
||||
fill="#F2F2F2"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<span className="text-foreground">{title ?? 'Launch Week 8: Day 1'}</span>
|
||||
</div>
|
||||
<span className="text-foreground-light">{d1.steps[0].title}</span>
|
||||
{isLaunchWeekPage ? (
|
||||
<ExpandableVideo
|
||||
videoId="RJccSbJ9Go4"
|
||||
onOpenCallback={handleClick}
|
||||
triggerContainerClassName="w-full"
|
||||
trigger={
|
||||
<div className="flex flex-row justify-between items-stretch w-full h-full gap-2 text-left">
|
||||
{announcement}
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative flex items-center justify-center !aspect-video h-[80px] md:h-[80px] gap-2 z-10 rounded overflow-hidden">
|
||||
<div className="absolute z-10 w-4 h-4 text-white opacity-70">
|
||||
<svg viewBox="0 0 81 91" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M76.5621 37.998C82.3369 41.3321 82.3369 49.6673 76.5621 53.0014L13.2198 89.5721C7.44504 92.9062 0.226562 88.7386 0.226562 82.0704L0.226566 8.92901C0.226566 2.26085 7.44506 -1.90673 13.2199 1.42735L76.5621 37.998Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<Image
|
||||
src="/images/launchweek/8/lw8-yt-thumb.jpg"
|
||||
alt="Youtube video thumbnail"
|
||||
layout="fill"
|
||||
objectFit="cover"
|
||||
/>
|
||||
</div>
|
||||
</a>
|
||||
</Link>
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<Link href="/launch-week#today">
|
||||
<a className="flex flex-row justify-between items-center w-full h-full gap-2 text-left">
|
||||
{announcement}
|
||||
</a>
|
||||
</Link>
|
||||
)}
|
||||
</SmallCard>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -167,7 +167,9 @@ export const AccordionHeader = ({
|
||||
videoThumbnail?: string
|
||||
}) => (
|
||||
<div
|
||||
className={['flex flex-1 justify-between items-stretch scroll-mt-20 text-scale-900'].join(' ')}
|
||||
className={[
|
||||
'h-[79px] hover:cursor-default flex flex-1 items-center scroll-mt-20 text-scale-900',
|
||||
].join(' ')}
|
||||
>
|
||||
<div
|
||||
className={[
|
||||
@@ -184,16 +186,16 @@ export const AccordionHeader = ({
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
{shippable && shipped && (
|
||||
<Badge
|
||||
className={`relative hidden sm:inline-flex inset-0 !bg-[#05090B] border !border-[#061517] !py-1 !px-4 h-fit`}
|
||||
>
|
||||
<span className="text-[#F4FFFA40] text-sm font-normal bg-clip-text bg-gradient-to-r from-[#F4FFFA] to-[#675FA7]">
|
||||
Shipped
|
||||
</span>
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
{shippable && shipped && (
|
||||
<Badge
|
||||
className={`relative hidden sm:inline-flex inset-0 !bg-[#05090B] border !border-[#061517] !py-1 !px-4 h-fit`}
|
||||
>
|
||||
<span className="text-[#F4FFFA40] text-sm font-normal bg-clip-text bg-gradient-to-r from-[#F4FFFA] to-[#675FA7]">
|
||||
Shipped
|
||||
</span>
|
||||
</Badge>
|
||||
)}
|
||||
{shippable && !shipped && (
|
||||
<span className="text-sm font-normal text-[#A0A0A0] mt-1 sm:mt-0 flex items-center gap-1 md:gap-4">
|
||||
<svg
|
||||
@@ -218,7 +220,7 @@ export const AccordionHeader = ({
|
||||
)}
|
||||
</div>
|
||||
{shippable && shipped && youtube_id && (
|
||||
<div className="self-end hover:cursor-pointer">
|
||||
<div className="hover:cursor-pointer animate-pulse hover:!opacity-100">
|
||||
<ExpandableVideo
|
||||
videoId={youtube_id}
|
||||
trigger={
|
||||
@@ -236,8 +238,8 @@ export const AccordionHeader = ({
|
||||
export const VideoPreviewTrigger = ({ title, thumbnail }: { title: string; thumbnail: string }) => (
|
||||
<div className="flex items-center h-full gap-3 text-xs group/vid text-scale-1100 hover:text-scale-1200 transition-colors">
|
||||
<span>{title}</span>
|
||||
<div className="relative h-8 !aspect-video flex items-center justify-center rounded overflow-hidden border border-scale-1000 opacity-80 group-hover/vid:opacity-100 transition-colors">
|
||||
<div className="absolute z-10 w-2.5 h-2.5 text-scale-1000 opacity-80 group-hover/vid:opacity-100">
|
||||
<div className="relative h-10 !aspect-video flex items-center justify-center rounded overflow-hidden border border-scale-1000 opacity-80 group-hover/vid:opacity-100 transition-colors">
|
||||
<div className="absolute z-10 w-2.5 h-2.5 text-white opacity-100">
|
||||
<svg viewBox="0 0 81 91" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M76.5621 37.998C82.3369 41.3321 82.3369 49.6673 76.5621 53.0014L13.2198 89.5721C7.44504 92.9062 0.226562 88.7386 0.226562 82.0704L0.226566 8.92901C0.226566 2.26085 7.44506 -1.90673 13.2199 1.42735L76.5621 37.998Z"
|
||||
@@ -250,7 +252,7 @@ export const VideoPreviewTrigger = ({ title, thumbnail }: { title: string; thumb
|
||||
alt="Video thumbnail"
|
||||
layout="fill"
|
||||
objectFit="cover"
|
||||
className="blur-sm"
|
||||
// className="blur-sm"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -287,80 +287,71 @@ export default function LW8Releases() {
|
||||
</Accordion.Item>
|
||||
</div>
|
||||
<div className="border-b border-[#111718] scroll-mt-16" id="today">
|
||||
<Accordion.Item
|
||||
header={
|
||||
<AccordionHeader
|
||||
date={day1.date}
|
||||
day={day1.d}
|
||||
weekDay={day1.dd}
|
||||
title={day1.title}
|
||||
shipped={day1Shipped}
|
||||
publishedAt={day1.publishedAt}
|
||||
youtube_id={day1.youtube_id}
|
||||
videoThumbnail={day1.videoThumbnail}
|
||||
/>
|
||||
}
|
||||
disabled={true}
|
||||
className="h-[79px] hover:cursor-default"
|
||||
id={day1.d.toString()}
|
||||
>
|
||||
{day1.steps.length > 0 && (
|
||||
<div className="flex flex-col gap-5 lg:flex-row pb-4">
|
||||
<motion.div
|
||||
className={`
|
||||
<AccordionHeader
|
||||
date={day1.date}
|
||||
day={day1.d}
|
||||
weekDay={day1.dd}
|
||||
title={day1.title}
|
||||
shipped={day1Shipped}
|
||||
publishedAt={day1.publishedAt}
|
||||
youtube_id={day1.youtube_id}
|
||||
videoThumbnail={day1.videoThumbnail}
|
||||
/>
|
||||
|
||||
{day1.steps.length > 0 && (
|
||||
<div className="flex flex-col gap-5 lg:flex-row pb-4">
|
||||
<motion.div
|
||||
className={`
|
||||
min-h-[400px] relative overflow-hidden group/d1 flex-1 flex flex-col items-center lg:items-start justify-between
|
||||
basis-1/2 lg:basis-1/3 border border-[#111718] rounded-xl lg:h-full bg-no-repeat py-10 lg:py-12 px-8 lg:px-10 text-2xl bg-contain shadow-lg
|
||||
`}
|
||||
initial="default"
|
||||
animate="default"
|
||||
whileHover="hover"
|
||||
>
|
||||
<div
|
||||
className="inset-0 absolute group-hover/d1:scale-105 opacity-60 group-hover/d1:opacity-100 w-full h-full -z-10 transition-all duration-500 pointer-events-none"
|
||||
style={{
|
||||
background: `radial-gradient(100% 100% at 80% 80%, #6F13A450, #030A0C)`,
|
||||
}}
|
||||
/>
|
||||
<div className="flex flex-col items-center lg:items-start gap-2 min-w-[300px] w-full text-center lg:text-left">
|
||||
<CartTitle>{day1.steps[0].title}</CartTitle>
|
||||
<p className="text-sm text-slate-900">{day1.steps[0]?.description}</p>
|
||||
</div>
|
||||
<SectionButtons
|
||||
blog={day1.steps[0].blog}
|
||||
video={day1.steps[0].video}
|
||||
// hackernews={day1.steps[0].hackernews}
|
||||
// twitter_spaces={day1.steps[0].twitter_spaces}
|
||||
// mobileGrid
|
||||
/>
|
||||
{day1.steps[0]?.bg_layers &&
|
||||
day1.steps[0]?.bg_layers?.map(
|
||||
(layer, i) =>
|
||||
!!layer.img && (
|
||||
<motion.div
|
||||
className="absolute opacity-90 inset-0 w-full h-full -z-10"
|
||||
variants={i === 1 ? scaleOpacityVariant : undefined}
|
||||
>
|
||||
<Image
|
||||
src={
|
||||
!!layer.mobileImg && isTablet
|
||||
? (layer.mobileImg as any)
|
||||
: layer.img
|
||||
}
|
||||
className={`
|
||||
initial="default"
|
||||
animate="default"
|
||||
whileHover="hover"
|
||||
>
|
||||
<div
|
||||
className="inset-0 absolute group-hover/d1:scale-105 opacity-60 group-hover/d1:opacity-100 w-full h-full -z-10 transition-all duration-500 pointer-events-none"
|
||||
style={{
|
||||
background: `radial-gradient(100% 100% at 80% 80%, #6F13A450, #030A0C)`,
|
||||
}}
|
||||
/>
|
||||
<div className="flex flex-col items-center lg:items-start gap-2 min-w-[300px] w-full text-center lg:text-left">
|
||||
<CartTitle>{day1.steps[0].title}</CartTitle>
|
||||
<p className="text-sm text-slate-900">{day1.steps[0]?.description}</p>
|
||||
</div>
|
||||
<SectionButtons
|
||||
blog={day1.steps[0].blog}
|
||||
// video={day1.steps[0].video}
|
||||
hackernews={day1.steps[0].hackernews}
|
||||
// twitter_spaces={day1.steps[0].twitter_spaces}
|
||||
// mobileGrid
|
||||
/>
|
||||
{day1.steps[0]?.bg_layers &&
|
||||
day1.steps[0]?.bg_layers?.map(
|
||||
(layer, i) =>
|
||||
!!layer.img && (
|
||||
<motion.div
|
||||
className="absolute opacity-90 inset-0 w-full h-full -z-10"
|
||||
variants={i === 1 ? scaleOpacityVariant : undefined}
|
||||
>
|
||||
<Image
|
||||
src={
|
||||
!!layer.mobileImg && isTablet ? (layer.mobileImg as any) : layer.img
|
||||
}
|
||||
className={`
|
||||
absolute opacity-90
|
||||
w-full h-full -z-10 transition-all duration-300
|
||||
`}
|
||||
layout="fill"
|
||||
objectPosition={isTablet ? '50%' : '90% 50%'}
|
||||
objectFit="contain"
|
||||
/>
|
||||
</motion.div>
|
||||
)
|
||||
)}
|
||||
</motion.div>
|
||||
</div>
|
||||
)}
|
||||
</Accordion.Item>
|
||||
layout="fill"
|
||||
objectPosition={isTablet ? '50%' : '90% 50%'}
|
||||
objectFit="contain"
|
||||
/>
|
||||
</motion.div>
|
||||
)
|
||||
)}
|
||||
</motion.div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="border-b border-[#111718]">
|
||||
<Accordion.Item
|
||||
|
||||
@@ -103,7 +103,7 @@ const days: WeekDayProps[] = [
|
||||
{
|
||||
title: 'Hugging Face now supported in Supabase',
|
||||
blog: '/blog/hugging-face-supabase',
|
||||
hackernews: '/',
|
||||
hackernews: 'https://news.ycombinator.com/item?id=37035960',
|
||||
video: 'https://www.youtube.com/watch?v=RJccSbJ9Go4',
|
||||
twitter_spaces: 'https://twitter.com/i/spaces/1DXGyvjkeEeJM',
|
||||
bg_layers: [{ img: images['01-hugging'] }],
|
||||
|
||||
@@ -145,7 +145,7 @@ export default function TicketHome({ users, meetups }: Props) {
|
||||
</div>
|
||||
<div className="absolute inset-0 z-0 flex items-center justify-center">
|
||||
<div className="absolute z-40 w-full flex justify-center -translate-y-8 px-6">
|
||||
<LWAnnouncement />
|
||||
<LWAnnouncement isLaunchWeekPage />
|
||||
</div>
|
||||
<AnimatedParticles />
|
||||
<Image
|
||||
|
||||
@@ -7,16 +7,20 @@ interface ExpandableVideoProps {
|
||||
videoId: string
|
||||
imgUrl?: string
|
||||
imgOverlayText?: string
|
||||
triggerContainerClassName?: string
|
||||
imgAltText?: string
|
||||
trigger?: ReactNode
|
||||
onOpenCallback?: any
|
||||
}
|
||||
|
||||
export function ExpandableVideo({
|
||||
imgUrl,
|
||||
videoId,
|
||||
imgOverlayText,
|
||||
triggerContainerClassName = '',
|
||||
imgAltText,
|
||||
trigger,
|
||||
onOpenCallback,
|
||||
}: ExpandableVideoProps) {
|
||||
const [expandVideo, setExpandVideo] = React.useState(false)
|
||||
const isMobile = useBreakpoint(768)
|
||||
@@ -99,7 +103,15 @@ export function ExpandableVideo({
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
<div onClick={() => setExpandVideo(true)}>{trigger ?? <CliccablePreview />}</div>
|
||||
<button
|
||||
onClick={() => {
|
||||
setExpandVideo(true)
|
||||
if (onOpenCallback) onOpenCallback()
|
||||
}}
|
||||
className={[triggerContainerClassName].join(' ')}
|
||||
>
|
||||
{trigger ?? <CliccablePreview />}
|
||||
</button>
|
||||
</>
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user