Files
Francesco Sansalvadore c08a241c69 Fix www mobile (#29640)
* fix ent quotes logos

* mobile hp product cards

* mobile customers section

* mobile examples

* update sitemap

* mobile customers slider

* remove autoplay
2024-10-07 09:47:32 +02:00

230 lines
6.7 KiB
TypeScript

import { PropsWithChildren } from 'react'
import dynamic from 'next/dynamic'
import Link from 'next/link'
import Image from 'next/image'
import { useTheme } from 'next-themes'
import { ArrowRight } from 'lucide-react'
import { Button, cn } from 'ui'
import SectionContainer from '~/components/Layouts/SectionContainer'
import SectionHeader from 'components/UI/SectionHeader'
import Panel from '~/components/Panel'
import customerStories from '~/data/CustomerStories'
import type { CustomerStoryType } from '~/data/CustomerStories'
const CustomersSliderMobile = dynamic(() => import('./CustomersSliderMobile'))
const CutomsersSliderDesktop = dynamic(() => import('./CutomsersSliderDesktop'))
const CustomerStories = () => (
<div id="customers" className="overflow-hidden pb-16 md:pb-24">
<SectionContainer className="!pb-8 w-full flex gap-4 justify-between flex-col xl:flex-row xl:items-end">
<SectionHeader
title="Infrastructure"
title_alt=" to innovate and scale with ease."
subtitle="Customer Stories"
paragraph="See how Supabase empowers companies of all sizes to accelerate their growth and streamline their work."
className="xl:w-1/2"
/>
<div className="flex gap-2">
<Button asChild>
<Link href="/customers">View all stories</Link>
</Button>
<Button asChild type="default">
<Link href="/events">View Events</Link>
</Button>
</div>
</SectionContainer>
<CustomersSliderMobile columns={compositionCols} className="md:hidden w-full h-[230px]" />
<CutomsersSliderDesktop columns={compositionCols} className="hidden md:flex" />
</div>
)
/**
* Utils & Components
*/
const getCustomer: (customer: string, linked: boolean) => ExtendedCustomerStoryType = (
customer,
linked
) => ({
...customerStories.find((story: CustomerStoryType) => customer.includes(story.organization!))!,
linked,
})
const compositionCols: CompositionColType[] = [
{
type: 'narrow',
cards: [getCustomer('Quivr', false), getCustomer('Tinloof', false)],
},
{
type: 'narrow',
cards: [
{
logo: '/images/customers/logos/1password.png',
logo_inverse: '/images/customers/logos/light/1password.png',
organization: '1Password',
},
getCustomer('Next Door Lending', true),
],
},
{
type: 'expanded',
cards: [getCustomer('Maergo', true)],
},
{
type: 'narrow',
cards: [
getCustomer('Shotgun', true),
{
logo: '/images/customers/logos/mozilla.png',
logo_inverse: '/images/customers/logos/light/mozilla.png',
organization: 'Mozilla',
linked: false,
},
],
},
{
type: 'expanded',
cards: [getCustomer('Chatbase', true)],
},
{
type: 'narrow',
cards: [getCustomer('Mobbin', true), getCustomer('HappyTeams', true)],
},
{
type: 'expanded',
cards: [getCustomer('Pebblely', true)],
},
]
export const CompositionCol: React.FC<CompositionColProps> = ({ column, className }) => {
return (
<div className={className}>
{column.cards.map((customer) =>
column.type === 'expanded' ? (
<Link
href={customer.url!}
key={customer.organization}
className="col-span-12 md:col-span-4 w-full md:w-[450px] h-full"
>
<CustomerCard size="expanded" customer={customer} />
</Link>
) : customer.linked ? (
<Link
href={customer.url!}
key={customer.organization}
className="col-span-12 md:col-span-4 w-full h-full flex-grow"
>
<CustomerCard size="narrow" customer={customer} />
</Link>
) : (
<CustomerCard
size="narrow"
key={customer.organization}
customer={customer}
className=" pointer-events-none"
/>
)
)}
</div>
)
}
const CustomerCard: React.FC<CustomerCardProps> = ({
customer,
className,
size,
children,
...rest
}) => {
const { resolvedTheme } = useTheme()
const showLogoInverse = customer.logo_inverse && resolvedTheme?.includes('dark')
const showLogo = !showLogoInverse && customer.logo
const LogoComponent = ({ logoImage, className }: { logoImage: string; className?: string }) => (
<div className="relative box-content opacity-50 group-hover:opacity-75 transition-opacity">
<div className="relative h-[33px] w-auto max-w-[145px]">
<Image
src={logoImage}
alt={customer.title!}
fill
priority
sizes="100%"
className={cn('object-contain object-left', className)}
/>
</div>
</div>
)
switch (size) {
case 'narrow':
return (
<Panel
hasActiveOnHover
outerClassName={cn('h-full w-full md:w-[250px] h-full flex-grow', className)}
innerClassName="flex items-center justify-center"
>
<Image
key={customer.organization}
src={customer.logo!}
alt={customer.organization!}
width={300}
height={150}
priority
className="w-full opacity-50 group-hover/panel:opacity-75 transition-opacity max-w-[140px] filter dark:invert"
/>
</Panel>
)
case 'expanded':
return (
<Panel
hasActiveOnHover
outerClassName={cn(
'relative',
'w-full h-full',
'group',
'cursor-pointer',
'overflow-hidden',
'text-left',
'transition',
className
)}
innerClassName="h-full p-4 md:p-8 flex flex-col gap-6 justify-between"
{...rest}
>
<ArrowRight className="not-sr-only absolute top-8 right-8 -rotate-45 stroke-1 -translate-x-1 translate-y-1 opacity-0 transition-all group-hover:opacity-100 group-hover:translate-x-0 group-hover:translate-y-0" />
{showLogoInverse && <LogoComponent logoImage={customer.logo_inverse!} />}
{showLogo && <LogoComponent logoImage={customer.logo!} />}
<p className="text-base text-foreground-lighter">{customer.title}</p>
{children && <span className="text-sm text-foreground-light flex-grow">{children}</span>}
</Panel>
)
}
}
/** Types */
type ColSize = 'narrow' | 'expanded'
type ExtendedCustomerStoryType = Partial<CustomerStoryType> & { linked?: boolean }
export type CompositionColType = {
type: ColSize
cards: ExtendedCustomerStoryType[]
}
interface CompositionColProps {
column: CompositionColType
className?: string
}
interface CustomerCardProps extends PropsWithChildren {
customer: ExtendedCustomerStoryType
className?: string
size?: ColSize
}
export default CustomerStories