Fix www mobile (#29640)

* fix ent quotes logos

* mobile hp product cards

* mobile customers section

* mobile examples

* update sitemap

* mobile customers slider

* remove autoplay
This commit is contained in:
Francesco Sansalvadore authored and GitHub committed 2024-10-07 09:47:32 +02:00
1 parent 9686f90628
commit c08a241c69
24 files changed
+492 -262

No files matched your search

-49
View File
@@ -1,49 +0,0 @@
import { Button, IconGitHubSolid } from 'ui'
import Link from 'next/link'
import SectionContainer from '~/components/Layouts/SectionContainer'
import ExampleCard from './ExampleCard'
import Examples from 'data/Examples'
const BuiltWithSupabase = () => {
return (
<SectionContainer id="examples" className="xl:pt-32">
<div className="text-center">
<h3 className="h2">Start building in seconds</h3>
<p className="p">
Kickstart your next project with templates built by us and our community.
</p>
<div className="flex justify-center gap-2 py-4">
<Button asChild type="default" size="small" className="h-full">
<Link href="/docs/guides/examples">View all examples</Link>
</Button>
<Button
asChild
type="default"
icon={<IconGitHubSolid size="tiny" className="!w-full !h-full" />}
size="small"
>
<Link href="https://github.com/supabase/supabase/tree/master/examples">
Official GitHub library
</Link>
</Button>
</div>
</div>
<div className="mt-16 grid grid-cols-12 gap-5">
{Examples.slice(0, 6).map((example, i) => {
return (
<div
className={`col-span-12 lg:col-span-6 xl:col-span-4 ${i > 2 && `sm:hidden lg:block`}`}
key={i}
>
<ExampleCard {...example} showProducts />
</div>
)
})}
</div>
</SectionContainer>
)
}
export default BuiltWithSupabase
@@ -0,0 +1,53 @@
import 'swiper/css'
import React, { FC } from 'react'
import { useRouter } from 'next/router'
import { Swiper, SwiperSlide } from 'swiper/react'
import ExampleCard from '../ExampleCard'
import content from '~/data/home/content'
import type { Example } from 'data/Examples'
interface Props {
examples: Example[]
className?: string
}
const ExamplesMobile: FC<Props> = ({ examples, className }: any) => {
const { basePath } = useRouter()
return (
<div className={className}>
<Swiper
style={{ zIndex: 0, marginRight: '1px' }}
initialSlide={0}
spaceBetween={12}
slidesPerView={1.1}
speed={300}
watchOverflow
threshold={2}
updateOnWindowResize
className="!px-6 w-full overflow-visible"
breakpoints={{
320: {
slidesPerView: 1.1,
},
540: {
slidesPerView: 1.6,
},
720: {
slidesPerView: 2.5,
},
}}
>
{examples.map((example: Example, i: number) => (
<SwiperSlide key={`${content}-${i}`}>
<ExampleCard {...example} showProducts />
</SwiperSlide>
))}
</Swiper>
</div>
)
}
export default ExamplesMobile
@@ -0,0 +1,58 @@
import { Button, cn, IconGitHubSolid } from 'ui'
import Link from 'next/link'
import SectionContainer from '~/components/Layouts/SectionContainer'
import ExampleCard from '../ExampleCard'
import Examples from 'data/Examples'
import ExamplesMobile from './ExamplesMobile'
const BuiltWithSupabase = () => {
return (
<>
<SectionContainer id="examples" className="xl:pt-32 !pb-0">
<div className="text-center flex flex-col items-center">
<h3 className="h2">Start building in seconds</h3>
<p className="p max-w-[300px] md:max-w-none">
Kickstart your next project with templates built by us and our community.
</p>
<div className="flex justify-center gap-2 py-4">
<Button asChild type="default" size="small" className="h-full">
<Link href="/docs/guides/examples">View all examples</Link>
</Button>
<Button
asChild
type="default"
icon={<IconGitHubSolid size="tiny" className="!w-full !h-full" />}
size="small"
>
<Link href="https://github.com/supabase/supabase/tree/master/examples">
Official GitHub library
</Link>
</Button>
</div>
</div>
</SectionContainer>
<SectionContainer className="relative w-full !px-0 lg:!px-16 xl:!px-20 !pb-0 mb-16 md:mb-12 lg:mb-12 !pt-6 max-w-[1400px]">
<ExamplesMobile examples={Examples.slice(0, 6)} className="lg:hidden" />
<div className="hidden lg:grid grid-cols-12 gap-5 mt-4">
{Examples.slice(0, 6).map((example, i) => {
return (
<div
className={cn(
'col-span-12 h-full lg:col-span-6 xl:col-span-4',
'flex items-stretch'
)}
key={i}
>
<ExampleCard {...example} showProducts />
</div>
)
})}
</div>
</SectionContainer>
</>
)
}
export default BuiltWithSupabase
@@ -0,0 +1,48 @@
import 'swiper/css'
import React from 'react'
import { Swiper, SwiperSlide } from 'swiper/react'
import { cn } from 'ui'
import { CompositionCol } from '.'
import type { CompositionColType } from '.'
interface Props {
className?: string
columns: CompositionColType[]
}
const CustomersSliderMobile: React.FC<Props> = ({ columns, className }) => (
<div className={className}>
<Swiper
initialSlide={0}
spaceBetween={12}
slidesPerView="auto"
speed={400}
watchOverflow
threshold={2}
updateOnWindowResize
allowTouchMove
className="!px-6 w-full h-full overflow-visible"
>
{columns.map((column: CompositionColType, i: number) => (
<SwiperSlide
className={cn(
'flex w-full !h-full',
column.type === 'expanded' ? 'w-full max-w-[450px]' : '!w-[250px]'
)}
key={`${column.cards[0].organization}-mobile-customer-${i}`}
>
<CompositionCol
className={cn(
'flex flex-col w-full !h-full gap-3',
column.type === 'expanded' ? 'w-full' : 'w-[250px]'
)}
column={column}
/>
</SwiperSlide>
))}
</Swiper>
</div>
)
export default CustomersSliderMobile
@@ -0,0 +1,52 @@
import React from 'react'
import { range } from 'lodash'
import { cn } from 'ui'
import { CompositionCol } from '.'
import type { CompositionColType } from '.'
interface Props {
className?: string
columns: CompositionColType[]
}
const compositionGap = 'gap-4'
const CutomsersSliderDesktop: React.FC<Props> = ({ columns, className }) => (
<div
className={cn(
'group/tw-marquee w-full items-stretch h-[300px] min-w-[300px] nowrap mb-16 md:mb-24 lg:mb-24',
compositionGap,
className
)}
>
{range(0, 2).map((_, idx1: number) => (
<div
key={`row-${idx1}`}
className={cn(
'relative',
'left-0 z-10',
'w-auto h-full',
'flex gap-4 items-end',
'motion-safe:run motion-safe:animate-[marquee_50000ms_linear_both_infinite] group-hover/tw-marquee:pause',
'will-change-transform transition-transform',
compositionGap
)}
>
{columns.map((column, idx2) => (
<CompositionCol
key={`customers-col-${idx1}-${idx2}`}
className={cn(
'flex flex-col !h-full',
compositionGap,
column.type === 'expanded' ? 'w-[450px]' : 'w-[250px]'
)}
column={column}
/>
))}
</div>
))}
</div>
)
export default CutomsersSliderDesktop
+138 -143
View File
@@ -1,11 +1,11 @@
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 { range } from 'lodash'
import { ArrowRight } from 'lucide-react'
import { Button, cn } from 'ui'
import { Button, cn } from 'ui'
import SectionContainer from '~/components/Layouts/SectionContainer'
import SectionHeader from 'components/UI/SectionHeader'
import Panel from '~/components/Panel'
@@ -13,150 +13,124 @@ import Panel from '~/components/Panel'
import customerStories from '~/data/CustomerStories'
import type { CustomerStoryType } from '~/data/CustomerStories'
const getCustomer = (customer: string, linked: boolean) => ({
...customerStories.find((story: any) => customer.includes(story.organization)),
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 CustomerStories = () => {
const composition = [
{
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)],
},
]
const compositionGap = 'gap-4'
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 id="customers" className="overflow-hidden">
<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>
<div
className={cn(
'group/tw-marquee w-full flex items-stretch h-[300px] min-w-[300px] nowrap mb-16 md:mb-24 lg:mb-24',
compositionGap
)}
>
{range(0, 2).map((_, idx1: number) => (
<div
key={`row-${idx1}`}
className={cn(
'relative',
'left-0 z-10',
'w-auto h-full',
'flex gap-4 items-end',
'motion-safe:run motion-safe:animate-[marquee_50000ms_linear_both_infinite] group-hover/tw-marquee:pause',
'will-change-transform transition-transform',
compositionGap
)}
<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"
>
{composition.map((group, idx2) => (
<div
key={`customers-col-${idx1}-${idx2}`}
className={cn(
'flex flex-col !h-full',
compositionGap,
group.type === 'expanded' ? 'w-[450px]' : 'w-[250px]'
)}
>
{group.cards.map((customer: any, idx3) =>
group.type === 'expanded' ? (
<Link
href={`${customer.url}`}
key={customer.organization}
className="col-span-12 md:col-span-4 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 h-full flex-grow"
>
<CustomerCard size="narrow" customer={customer} />
</Link>
) : (
<CustomerCard
size="narrow"
key={customer.organization}
customer={customer}
className="pointer-events-none"
/>
)
)}
</div>
))}
</div>
))}
</div>
<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>
)
}
interface CustomerCardProps extends PropsWithChildren {
customer: CustomerStoryType
className?: string
size?: 'narrow' | 'expanded'
}
const CustomerCard: React.FC<CustomerCardProps> = ({
customer,
className,
@@ -173,7 +147,7 @@ const CustomerCard: React.FC<CustomerCardProps> = ({
<div className="relative h-[33px] w-auto max-w-[145px]">
<Image
src={logoImage}
alt={customer.title}
alt={customer.title!}
fill
priority
sizes="100%"
@@ -188,13 +162,13 @@ const CustomerCard: React.FC<CustomerCardProps> = ({
return (
<Panel
hasActiveOnHover
outerClassName={cn('h-full w-[250px] h-full flex-grow', className)}
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}
src={customer.logo!}
alt={customer.organization!}
width={300}
height={150}
priority
@@ -208,7 +182,7 @@ const CustomerCard: React.FC<CustomerCardProps> = ({
hasActiveOnHover
outerClassName={cn(
'relative',
'h-full',
'w-full h-full',
'group',
'cursor-pointer',
'overflow-hidden',
@@ -216,13 +190,13 @@ const CustomerCard: React.FC<CustomerCardProps> = ({
'transition',
className
)}
innerClassName="h-full p-8 flex flex-col gap-6 justify-between"
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} />}
{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>}
@@ -231,4 +205,25 @@ const CustomerCard: React.FC<CustomerCardProps> = ({
}
}
/** 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
@@ -10,7 +10,9 @@ interface Props {
const DashboardFeatures: React.FC<Props> = ({ title, tabs }) => (
<SectionContainer className="text-center" id="dashboard">
<h3 className="mb-8 text-2xl lg:text-4xl text-foreground-lighter">{title}</h3>
<h3 className="mb-8 text-2xl md:text-4xl max-w-[300px] sm:max-w-none mx-auto text-foreground-lighter">
{title}
</h3>
<TabsWithHighlights tabs={tabs} />
</SectionContainer>
)
+3 -2
View File
@@ -1,7 +1,8 @@
import { useEffect, useState } from 'react'
import { useBreakpoint } from 'common'
import Link from 'next/link'
import { ArrowUpRight } from 'lucide-react'
import { useBreakpoint } from 'common'
import { Button } from 'ui'
import Panel from './Panel'
@@ -17,7 +18,7 @@ function ExampleCard(props: any) {
return (
<Link href={props.repo_url} className="w-full h-full" target="_blank">
<Panel innerClassName="bg-surface-75 group/panel" hasActiveOnHover>
<Panel outerClassName="h-full" innerClassName="bg-surface-75 group/panel" hasActiveOnHover>
<div className="flex flex-col justify-between">
{props.tags && (
<div className="relative w-full aspect-[3/1] bg flex items-center justify-center gap-4 overflow-hidden">
+7 -2
View File
@@ -1,10 +1,15 @@
import Image from 'next/image'
import React from 'react'
import { cn } from 'ui'
const AuthVisual = () => {
interface Props {
className?: string
}
const AuthVisual: React.FC<Props> = ({ className }) => {
return (
<figure
className="group absolute inset-0 z-0 -top-16 xl:top-0 xl:bottom-0"
className={cn('group absolute inset-0 z-0 -top-16 xl:top-0 xl:bottom-0', className)}
role="img"
aria-label="Supabase Authentication provides Row Level Security which enables you to define custom Policies to restrict access to your database"
>
@@ -1,9 +1,14 @@
import React from 'react'
import Image from 'next/image'
import { range } from 'lodash'
import { cn } from 'ui'
const DataAPIsVisual = () => (
<figure className="absolute inset-0 overflow-hidden">
interface Props {
className?: string
}
const DataAPIsVisual: React.FC<Props> = ({ className }) => (
<figure className={cn('absolute inset-0 overflow-hidden', className)}>
<div className="absolute z-0 inset-0 flex flex-nowrap">
{range(0, 3).map((_, idx1: number) => (
<div
@@ -1,8 +1,13 @@
import React, { useEffect, useRef, useState } from 'react'
import Image from 'next/image'
import { detectBrowser, isBrowser } from 'common'
import { cn } from 'ui'
const DatabaseVisual = () => {
interface Props {
className?: string
}
const DatabaseVisual: React.FC<Props> = ({ className }) => {
const containerRef = useRef(null)
const ref = useRef(null)
const [gradientPos, setGradientPos] = useState({ x: 0, y: 0 })
@@ -49,7 +54,7 @@ const DatabaseVisual = () => {
return (
<figure
className="absolute inset-0 z-0"
className={cn('absolute inset-0 z-0', className)}
ref={containerRef}
role="img"
aria-label="Supabase Postgres database visual composition"
@@ -3,8 +3,13 @@ import Image from 'next/image'
import Typed from 'typed.js'
import type { TypedOptions } from 'typed.js'
import { useBreakpoint } from 'common'
import { cn } from 'ui'
const FunctionsVisual = () => {
interface Props {
className?: string
}
const FunctionsVisual: React.FC<Props> = ({ className }) => {
const typerRef = useRef<HTMLSpanElement>(null)
const isMobile = useBreakpoint('md')
const [typed, setTyped] = useState<Typed | null>(null)
@@ -64,7 +69,7 @@ const FunctionsVisual = () => {
return (
<figure
className="absolute inset-0 z-20"
className={cn('absolute inset-0 z-20', className)}
role="img"
aria-label="Supabase Edge Functions visual composition"
onMouseOver={handleMouseEnter}
+11 -6
View File
@@ -30,7 +30,7 @@ const ProductCard = ({
<Link
href={url}
className={cn(
'group relative w-full h-[400px] flex flex-col gap-5 lg:flex-row focus:outline-none focus:border-none focus:ring-brand-600 focus:ring-2 focus:rounded-xl',
'group relative w-full sm:h-[400px] flex flex-col gap-5 lg:flex-row focus:outline-none focus:border-none focus:ring-brand-600 focus:ring-2 focus:rounded-xl',
className
)}
onClick={onClick}
@@ -41,17 +41,22 @@ const ProductCard = ({
hasMotion={title.includes('Edge Functions')}
outerClassName="relative w-full h-full"
innerClassName={cn(
'relative overflow-hidden flex-1 flex flex-col items-center gap-5 lg:items-start justify-between',
'bg-surface-75 w-full h-full text-foreground-lighter [&_strong]:!font-normal [&_strong]:!text-foreground'
'relative overflow-hidden flex-1 flex flex-row sm:flex-col gap-4 items-start sm:items-center lg:items-start justify-between',
'bg-surface-75 w-full h-full text-foreground-lighter [&_strong]:!font-normal [&_strong]:!text-foreground',
'p-4 sm:py-6'
)}
>
<div
className={cn(
'relative z-10 flex flex-col lg:h-full gap-4 mx-auto items-center text-center h-full px-4 py-6',
alignLeft && !isDatabase && 'lg:mx-0 lg:pl-6 lg:items-start lg:text-left',
'relative z-10',
'h-full w-full',
'mx-auto gap-2 sm:gap-4',
'flex flex-col items-start sm:items-center',
'text-left sm:text-center',
alignLeft && !isDatabase && 'lg:mx-0 lg:pl-2 lg:items-start lg:text-left',
alignLeft &&
isDatabase &&
'md:ml-4 md:mt-2 md:justify-start md:max-w-[260px] md:text-left md:items-start'
'md:ml-2 md:mt-2 lg:pl-0 md:justify-start md:max-w-[250px] md:text-left md:items-start'
)}
>
<div className="flex items-center gap-2 text-foreground">
@@ -1,8 +1,12 @@
import React, { useRef, useState } from 'react'
import Image from 'next/image'
import { isBrowser, useReducedMotion } from 'common'
import { cn } from 'ui'
interface Props {
className?: string
}
const RealtimeVisual = () => {
const RealtimeVisual: React.FC<Props> = ({ className }) => {
const cardRef = useRef<HTMLDivElement | null>(null)
const [svgTransformSelf, setSvgTransformSelf] = useState<string>('translate(0px, 0px)')
const [svgTransform, setSvgTransform] = useState<string>('translate(0px, 0px)')
@@ -39,7 +43,10 @@ const RealtimeVisual = () => {
return (
<figure
ref={cardRef}
className="absolute inset-0 xl:-bottom-2 2xl:bottom-0 z-0 w-full overflow-hidden pointer-events-auto"
className={cn(
'absolute inset-0 xl:-bottom-2 2xl:bottom-0 z-0 w-full overflow-hidden pointer-events-auto',
className
)}
role="img"
aria-label="Supabase Realtime multiplayer app demo"
onMouseMove={reduceMotion ? undefined : handleMouseMove}
@@ -1,7 +1,12 @@
import { range } from 'lodash'
import { File, Image, Video } from 'lucide-react'
import { cn } from 'ui'
const StorageVisual = () => {
interface Props {
className?: string
}
const StorageVisual: React.FC<Props> = ({ className }) => {
const cols = [
<Image className="w-6 h-6 md:w-6 md:h-6" />,
<File className="w-6 h-6 md:w-6 md:h-6" />,
@@ -10,7 +15,7 @@ const StorageVisual = () => {
return (
<figure
className="absolute inset-0 overflow-hidden flex nowrap"
className={cn('absolute inset-0 overflow-hidden flex nowrap', className)}
role="img"
aria-label="Supabase Storage supports images, documents and videos"
>
+16 -10
View File
@@ -1,8 +1,13 @@
import { detectBrowser, isBrowser } from 'common'
import Image from 'next/image'
import React, { useEffect, useRef, useState } from 'react'
import { cn } from 'ui'
const VectorVisual = () => {
interface Props {
className?: string
}
const VectorVisual: React.FC<Props> = ({ className }) => {
const containerRef = useRef(null)
const ref = useRef(null)
const [gradientPos, setGradientPos] = useState({ x: 0, y: 0 })
@@ -49,15 +54,16 @@ const VectorVisual = () => {
return (
<figure
className="
absolute inset-0
z-0 flex items-end
top-auto
aspect-[390/430]
w-full md:w-[calc(100%+4rem)] 2xl:w-full
md:-mx-8 2xl:mx-0
-bottom-0 sm:-bottom-28 md:bottom-0 lg:-bottom-28 xl:bottom-0
"
className={cn(
'absolute inset-0',
'z-0 flex items-end',
'top-auto',
'aspect-[390/430]',
'w-full md:w-[calc(100%+4rem)] 2xl:w-full',
'md:-mx-8 2xl:mx-0',
'-bottom-0 sm:-bottom-28 md:bottom-0 lg:-bottom-28 xl:bottom-0',
className
)}
ref={containerRef}
role="img"
aria-label="Supabase Vector uses pgvector to store, index, and access embeddings"
+14 -16
View File
@@ -22,7 +22,7 @@ interface Props {
products: SolutionsType
}
const Products = (props: Props) => {
const Products: React.FC<Props> = (props) => {
const router = useRouter()
const telemetryProps = useTelemetryProps()
@@ -97,7 +97,7 @@ const Products = (props: Props) => {
</ul>
}
onClick={() => sendTelemetryEvent(PRODUCT_SHORTNAMES.DATABASE)}
image={<DatabaseVisual />}
image={<DatabaseVisual className="hidden sm:block" />}
/>
<ProductCard
className="col-span-6 xl:col-span-3"
@@ -108,11 +108,10 @@ const Products = (props: Props) => {
subtitle={
<>
<strong>Add user sign ups and logins</strong>,
<br className="inline-block sm:hidden lg:inline-block" />
securing your data with Row Level Security.
<br className="hidden lg:inline-block" /> securing your data with Row Level Security.
</>
}
image={<AuthVisual />}
image={<AuthVisual className="hidden sm:block" />}
onClick={() => sendTelemetryEvent(PRODUCT_SHORTNAMES.AUTHENTICATION)}
/>
<ProductCard
@@ -124,12 +123,12 @@ const Products = (props: Props) => {
subtitle={
<>
Easily write custom code
<br className="inline-block sm:hidden lg:inline-block" />{' '}
<br className="hidden sm:inline-block" />{' '}
<strong>without deploying or scaling servers.</strong>
</>
}
onClick={() => sendTelemetryEvent(PRODUCT_SHORTNAMES.FUNCTIONS)}
image={<FunctionsVisual />}
image={<FunctionsVisual className="hidden sm:block" />}
/>
<ProductCard
className="col-span-6 xl:col-span-3"
@@ -140,11 +139,11 @@ const Products = (props: Props) => {
subtitle={
<>
<strong>Store, organize, and serve</strong>
<br className="inline-block xl:hidden 2xl:inline-block" /> large files, from videos to
images.
<br className="hidden sm:inline-block xl:hidden 2xl:inline-block" /> large files, from
videos to images.
</>
}
image={<StorageVisual />}
image={<StorageVisual className="hidden sm:block" />}
onClick={() => sendTelemetryEvent(PRODUCT_SHORTNAMES.STORAGE)}
/>
<ProductCard
@@ -155,12 +154,11 @@ const Products = (props: Props) => {
subtitle={
<>
<strong>Build multiplayer experiences</strong>
<br className="inline-block md:hidden 2xl:inline-block" /> with real-time data
synchronization.
<br className="hidden sm:inline-block" /> with real-time data synchronization.
</>
}
onClick={() => sendTelemetryEvent(PRODUCT_SHORTNAMES.REALTIME)}
image={<RealtimeVisual />}
image={<RealtimeVisual className="hidden sm:block" />}
className="
col-span-6 pointer-events-none xl:col-span-3
hover:!cursor-[url('/images/index/products/realtime-cursor-light.svg'),_auto]
@@ -175,7 +173,7 @@ const Products = (props: Props) => {
title={props.products['vector'].name}
subtitle={
<>
Integrate your favorite ML-models to <br className="inline-block md:hidden" />
Integrate your favorite ML-models to <br className="hidden sm:inline-block md:hidden" />
<strong>store, index and search vector embeddings</strong>.
</>
}
@@ -243,7 +241,7 @@ const Products = (props: Props) => {
</ul>
}
onClick={() => sendTelemetryEvent(PRODUCT_SHORTNAMES.VECTOR)}
image={<VectorVisual />}
image={<VectorVisual className="hidden sm:block" />}
/>
<ProductCard
alignLeft
@@ -253,7 +251,7 @@ const Products = (props: Props) => {
title={props.products['data-api'].name}
subtitle={props.products['data-api'].description}
onClick={() => sendTelemetryEvent('data-api')}
image={<DataAPIsVisual />}
image={<DataAPIsVisual className="hidden sm:block" />}
/>
<p className="text-xl sm:text-2xl text-foreground-lighter col-span-full tracking-[-.01rem]">
<span className="text-foreground">Use one or all.</span> Best of breed products. Integrated
+6 -4
View File
@@ -12,10 +12,12 @@ const TwitterSocialSection = () => {
return (
<>
<SectionContainer className="w-full text-center !pb-0">
<SectionContainer className="w-full text-center flex flex-col items-center !pb-0">
<h3 className="h2">Join the community</h3>
<p className="p">Discover what our community has to say about their Supabase experience.</p>
<div className="my-8 flex justify-center gap-2">
<p className="p max-w-[300px] md:max-w-none">
Discover what our community has to say about their Supabase experience.
</p>
<div className="my-4 flex justify-center gap-2">
<Button asChild size="small" iconRight={<MessageCircle size={14} />} type="default">
<Link
href={'https://github.com/supabase/supabase/discussions'}
@@ -33,7 +35,7 @@ const TwitterSocialSection = () => {
</div>
</SectionContainer>
<SectionContainer className="relative w-full !px-0 lg:!px-16 xl:!px-0 !pb-0 mb-16 md:mb-12 lg:mb-12 !pt-6 max-w-[1400px]">
<TwitterSocialProofMobile className="lg:hidden -mb-24" tweets={tweets} />
<TwitterSocialProofMobile className="lg:hidden -mb-32" tweets={tweets} />
<TwitterSocialProof className="hidden lg:flex" />
</SectionContainer>
</>
+18 -1
View File
@@ -1,6 +1,21 @@
import { PRODUCT_NAMES } from 'shared-data/products'
export default [
export type Example = {
type: string
tags: string[]
products: PRODUCT_NAMES[]
title: string
description: string
author?: string
author_url?: string
author_img?: string
repo_name?: string
repo_url?: string
vercel_deploy_url?: string
demo_url?: string
}
const Examples: Example[] = [
{
type: 'example',
tags: ['Next.js', 'Stripe', 'Vercel'],
@@ -287,3 +302,5 @@ export default [
'https://github.com/supabase/supabase/tree/master/examples/edge-functions/supabase/functions/file-upload-storage',
},
]
export default Examples
+1 -2
View File
@@ -51,8 +51,7 @@ export default {
title: (
<>
<span className="text-foreground">Stay productive and manage your app</span>
<br className="hidden md:block" />
without leaving the dashboard
<br className="hidden sm:block" /> without leaving the dashboard
</>
),
tabs: [
+1 -1
View File
@@ -137,7 +137,7 @@ export const CustomerQuote = ({
)
export const CustomerLogo = ({ title, logo }: { title: string; logo: string }) => (
<div className="relative h-8 max-h-6 w-28">
<div className="relative h-8 max-h-5 xl:max-h-6 w-20 max-w-20 md:w-28 xl:max-w-28">
<Image
fill
src={logo}
+4 -4
View File
@@ -79,16 +79,16 @@ function CustomerStoriesPage(props: any) {
/>
<DefaultLayout>
<div className="relative z-0 bg-background overflow-hidden">
<div className="container mx-auto mt-44 px-8 sm:px-4 xl:px-20">
<div className="container mx-auto mt-28 sm:mt-44 px-4 xl:px-20">
<div className="mx-auto relative z-10">
<motion.div
className="mx-auto max-w-2xl text-center"
className="mx-auto sm:max-w-2xl text-center"
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0, transition: { duration: 0.5, easing: 'easeOut' } }}
>
<WebinarAnnouncement />
<h1 className="text-foreground mb-3 text-3xl">Customer stories</h1>
<h2 className="text-foreground-light text-xl">
<h2 className="text-foreground-light text-base sm:text-xl">
Discover case studies on how Supabase is being used around the world to quickly
create outstanding products and set new industry standards.
</h2>
@@ -125,7 +125,7 @@ function CustomerStoriesPage(props: any) {
</div>
<div
className={[
'absolute inset-0 h-[300px] bg-background z-0 after:!bg-background',
'absolute inset-0 h-[150px] sm:h-[300px] bg-background z-0 after:!bg-background',
styles['bg-visual'],
].join(' ')}
/>
+8 -9
View File
@@ -115,12 +115,12 @@ function CaseStudyPage(props: any) {
<DefaultLayout>
<div
className="
container mx-auto px-8 py-16 sm:px-16
container mx-auto p-8 sm:py-16 sm:px-16
xl:px-20
"
>
<div className="grid grid-cols-12 gap-4">
<div className="col-span-12 mb-2 xl:col-span-2">
<div className="hidden xl:block col-span-12 mb-2 xl:col-span-2">
{/* Back button */}
<Link
href="/customers"
@@ -131,15 +131,14 @@ function CaseStudyPage(props: any) {
</Link>
</div>
<div
className="col-span-12 lg:col-span-8
"
>
<div className="col-span-12 lg:col-span-8">
<div>
<article className="flex flex-col gap-8">
<div className="flex flex-col gap-8 max-w-xxl">
<Link href="/customers" className="text-brand hover:text-brand-600 mb-2 mt-0">
<div className="flex flex-col gap-4 sm:gap-8 max-w-xxl">
<Link
href="/customers"
className="text-brand hover:text-brand-600 sm:mb-2 mt-0"
>
Customer Stories
</Link>
<h1 className="text-foreground text-4xl font-semibold xl:text-5xl">{title}</h1>
+14 -2
View File
@@ -66,6 +66,12 @@
<priority>0.5</priority>
</url>
<url>
<loc>https://supabase.com/enterprise</loc>
<changefreq>weekly</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://supabase.com/ga-week</loc>
<changefreq>weekly</changefreq>
@@ -229,13 +235,13 @@
</url>
<url>
<loc>https://supabase.com/partners/experts</loc>
<loc>https://supabase.com/partners/integrations</loc>
<changefreq>weekly</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://supabase.com/partners/integrations</loc>
<loc>https://supabase.com/partners/experts</loc>
<changefreq>weekly</changefreq>
<priority>0.5</priority>
</url>
@@ -2024,6 +2030,12 @@
<priority>0.5</priority>
</url>
<url>
<loc>https://supabase.com/blog/lw12-hackathon-winners</loc>
<changefreq>weekly</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://supabase.com/customers/berriai</loc>
<changefreq>weekly</changefreq>