mirror of
https://github.com/supabase/supabase.git
synced 2026-10-10 20:05:06 +03:00
Before <img width="588" height="439" alt="Screenshot 2026-07-08 at 7 29 07 PM" src="https://github.com/user-attachments/assets/8a3380d3-571f-49cd-8f32-7b38650dd0e5" /> After <img width="578" height="436" alt="Screenshot 2026-07-08 at 7 29 55 PM" src="https://github.com/user-attachments/assets/09e74c31-e131-41d5-87da-b4518514cfb5" /> ## Summary On the homepage, the Postgres Database product card's elephant artwork renders over the card's description text at every viewport ≥1280px. I traced it to #47226 (merged June 24): standardizing the marketing container to `section-container` (`max-w-7xl` + `xl:px-24`) capped products-grid content at 1088px, shrinking the card to ~538px while its fixed geometry (250px text column + 398px right-anchored square artwork box) needs ~625px. Large monitors regressed hardest: before June 24 they got ~676px cards and no overlap. The app-router homepage move (#47228), the color system PR (#47288), and the artwork PNGs are all unrelated (verified against production DOM and full diffs). Two changes to the artwork span in `DatabaseVisual.tsx`: 1. Cap the box width at `calc(100% - 280px)` from `md` up, where 280 covers the text column's `md:max-w-[250px]` cap (in `ProductCard.tsx`'s `isDatabase` branch) plus card padding and breathing room. The art scales down through its existing `object-contain`. At md/lg the card is full-width (`md:col-span-12`), so the clamp never binds and rendering is unchanged there. 2. Remove the `xl:-right-12` bleed (base `right-0` stands, matching how 2xl already rendered). The bleed used to clip only the art's transparent canvas margin; with the clamped box the art fills its full width, so the 48px offset was cropping the elephant itself at 1280-1535px. The hover line-art SVG scales with the box and stays aligned with the PNG (identical aspect ratios: viewBox 390:430, PNG 585x645). ## Changes - Add `md:max-w-[calc(100%-280px)]` to the artwork span in `DatabaseVisual.tsx` so the Postgres card art can never cross its text column - Drop `xl:-right-12 2xl:right-0` from the same span so the smaller art isn't clipped at the card's right edge ## Testing Round 1 on the Vercel preview (commite1ca671, measured via getBoundingClientRect + computed styles): - [x] Art clear of the text column at 1280/1440/1600/1920 (gap 54px at 1280/1440, 6px at 1600/1920); computed `max-width: calc(100% - 280px)` applies - [x] Hover at 1440 — SVG and PNG rects identical (pixel-exact alignment) - [x] 768/1024 — full-width card unchanged, span still a 398px square (clamp resolves but doesn't bind) - [x] Light theme at 1440 — same geometry, no overlap Round 1 also surfaced that the `xl:-right-12` bleed now cropped the elephant at 1280-1535px widths → second commit removes it. Round 2 (commite28b408): - [x] 1280/1440/1512/1600/1920 — art fully visible (span right edge flush at the card's inner edge, e.g. 713 vs 714 at 1440), still clear of the text column (span left 457 vs text right 451) - [x] 768/1024 — unchanged (span still a right-anchored 398px square) - [x] Hover alignment still exact (PNG and SVG rects identical: 457,452,256,398) ## Linear - fixes GROWTH-971
149 lines
7.4 KiB
TypeScript
149 lines
7.4 KiB
TypeScript
import { detectBrowser, isBrowser } from 'common'
|
|
import Image from 'next/image'
|
|
import React, { useEffect, useRef, useState } from 'react'
|
|
import { cn } from 'ui'
|
|
|
|
interface Props {
|
|
className?: string
|
|
hasGlow?: boolean
|
|
}
|
|
|
|
const DatabaseVisual: React.FC<Props> = ({ className, hasGlow = true }) => {
|
|
const containerRef = useRef(null)
|
|
const ref = useRef(null)
|
|
const [gradientPos, setGradientPos] = useState({ x: 0, y: 0 })
|
|
const isSafari = isBrowser && detectBrowser() === 'Safari'
|
|
|
|
const handleGlow = (event: any) => {
|
|
if (!ref.current || !containerRef.current || !hasGlow) return null
|
|
|
|
const containerRefElement = containerRef.current as HTMLDivElement
|
|
|
|
const {
|
|
x: contX,
|
|
y: contY,
|
|
width: containerWidth,
|
|
height: containerHeight,
|
|
} = containerRefElement.getBoundingClientRect()
|
|
const xCont = event.clientX - contX
|
|
const yCont = event.clientY - contY
|
|
|
|
const isContainerHovered =
|
|
xCont > -3 && xCont < containerWidth + 3 && yCont > -3 && yCont < containerHeight + 3
|
|
|
|
if (!isContainerHovered) return
|
|
|
|
const svgElement = ref.current as SVGElement
|
|
const { x: svgX, y: svgY } = svgElement.getBoundingClientRect()
|
|
const x = event.clientX - svgX
|
|
const y = event.clientY - svgY
|
|
setGradientPos({ x, y })
|
|
}
|
|
|
|
useEffect(() => {
|
|
if (!isBrowser || isSafari) return
|
|
|
|
window.addEventListener('mousemove', handleGlow)
|
|
return () => {
|
|
window.removeEventListener('mousemove', handleGlow)
|
|
}
|
|
}, [])
|
|
|
|
const gradientTransform = isSafari
|
|
? `translate(150 150) rotate(45) scale(166 180)`
|
|
: `translate(${gradientPos?.x} ${gradientPos?.y}) rotate(45) scale(166 180)`
|
|
|
|
return (
|
|
<figure
|
|
className={cn('absolute inset-0 z-0', className)}
|
|
ref={containerRef}
|
|
role="img"
|
|
aria-label="Supabase Postgres database visual composition"
|
|
>
|
|
<span className="absolute group w-full md:w-auto h-full md:aspect-square md:max-w-[calc(100%-280px)] flex items-end md:items-center justify-center md:justify-end right-0 left-0 md:left-auto top-12 md:top-0 md:bottom-0 my-auto">
|
|
<Image
|
|
src="/images/index/products/database-dark.png"
|
|
alt="Supabase Postgres database"
|
|
fill
|
|
priority
|
|
quality={100}
|
|
sizes="100%"
|
|
draggable={false}
|
|
className="hidden dark:block absolute antialiased inset-0 object-contain object-center z-0 w-full md:w-auto h-full transition-opacity group-hover:opacity-80"
|
|
/>
|
|
<Image
|
|
src="/images/index/products/database-light.png"
|
|
alt="Supabase Postgres database"
|
|
fill
|
|
priority
|
|
quality={100}
|
|
draggable={false}
|
|
sizes="100%"
|
|
className="dark:hidden absolute antialiased inset-0 object-contain object-center z-0 w-full md:w-auto h-full transition-opacity group-hover:opacity-80"
|
|
/>
|
|
<svg
|
|
ref={ref}
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
fill="none"
|
|
viewBox="0 0 390 430"
|
|
className="absolute w-full h-full z-10 m-auto will-change-transform opacity-0 transition-opacity group-hover:opacity-100"
|
|
>
|
|
<g stroke="var(--foreground-lighter)" filter="url(#filter5_bd_467_4905)">
|
|
<path d="M192.144 125.816h-53.465c-8.506 0-16.159 5.17-19.334 13.061L99.0045 189.43c-3.0613 7.608-1.3448 16.306 4.3775 22.181l10.232 10.506c4.792 4.919 7.474 11.516 7.474 18.384l-.001 14.473c0 20.197 16.373 36.569 36.569 36.569 6.16 0 11.154-4.993 11.154-11.153l.001-86.241c0-18.629 7.441-36.486 20.668-49.602 2.746-2.723 7.178-2.704 9.9.041 2.722 2.745 2.703 7.178-.042 9.9-10.577 10.488-16.526 24.766-16.526 39.661l-.001 86.241c0 13.892-11.262 25.153-25.154 25.153-27.928 0-50.569-22.64-50.569-50.569l.001-14.474c0-3.218-1.257-6.309-3.503-8.615L93.353 221.38c-9.5904-9.847-12.4673-24.424-7.3366-37.176l20.3406-50.553c5.308-13.192 18.101-21.835 32.322-21.835h55.729v.084h10.339c49.104 0 88.91 39.806 88.91 88.91v50.842c0 3.866-3.134 7-7 7s-7-3.134-7-7V200.81c0-41.372-33.538-74.91-74.91-74.91H193.23c-.37 0-.732-.029-1.086-.084Z" />
|
|
<path d="M210.03 283.94c0-3.866-3.134-7-7-7s-7 3.134-7 7v3.113c0 26.959 21.854 48.814 48.813 48.814 26.351 0 47.825-20.879 48.781-46.996h24.614c3.866 0 7-3.134 7-7s-3.134-7-7-7h-26.841c-30.744 0-60.256-12.083-82.173-33.643-2.756-2.711-7.188-2.675-9.899.081-2.711 2.756-2.675 7.188.081 9.9 21.725 21.371 50.116 34.423 80.228 37.134-.679 18.629-15.995 33.524-34.791 33.524-19.227 0-34.813-15.587-34.813-34.814v-3.113ZM238.03 202.145c0 4.792 3.885 8.677 8.677 8.677s8.676-3.885 8.676-8.677-3.884-8.676-8.676-8.676-8.677 3.884-8.677 8.676Z" />
|
|
</g>
|
|
<path
|
|
stroke="url(#a)"
|
|
d="M192.144 125.816h-53.465c-8.506 0-16.159 5.17-19.334 13.061L99.0045 189.43c-3.0613 7.608-1.3448 16.306 4.3775 22.181l10.232 10.506c4.792 4.919 7.474 11.516 7.474 18.384l-.001 14.473c0 20.197 16.373 36.569 36.569 36.569 6.16 0 11.154-4.993 11.154-11.153l.001-86.241c0-18.629 7.441-36.486 20.668-49.602 2.746-2.723 7.178-2.704 9.9.041 2.722 2.745 2.703 7.178-.042 9.9-10.577 10.488-16.526 24.766-16.526 39.661l-.001 86.241c0 13.892-11.262 25.153-25.154 25.153-27.928 0-50.569-22.64-50.569-50.569l.001-14.474c0-3.218-1.257-6.309-3.503-8.615L93.353 221.38c-9.5904-9.847-12.4673-24.424-7.3366-37.176l20.3406-50.553c5.308-13.192 18.101-21.835 32.322-21.835h55.729v.084h10.339c49.104 0 88.91 39.806 88.91 88.91v50.842c0 3.866-3.134 7-7 7s-7-3.134-7-7V200.81c0-41.372-33.538-74.91-74.91-74.91H193.23c-.37 0-.732-.029-1.086-.084Z"
|
|
/>
|
|
<path
|
|
stroke="url(#b)"
|
|
d="M210.03 283.94c0-3.866-3.134-7-7-7s-7 3.134-7 7v3.113c0 26.959 21.854 48.814 48.813 48.814 26.351 0 47.825-20.879 48.781-46.996h24.614c3.866 0 7-3.134 7-7s-3.134-7-7-7h-26.841c-30.744 0-60.256-12.083-82.173-33.643-2.756-2.711-7.188-2.675-9.899.081-2.711 2.756-2.675 7.188.081 9.9 21.725 21.371 50.116 34.423 80.228 37.134-.679 18.629-15.995 33.524-34.791 33.524-19.227 0-34.813-15.587-34.813-34.814v-3.113Z"
|
|
/>
|
|
<path
|
|
stroke="url(#c)"
|
|
d="M238.03 202.145c0 4.792 3.885 8.677 8.677 8.677s8.676-3.885 8.676-8.677-3.884-8.676-8.676-8.676-8.677 3.884-8.677 8.676Z"
|
|
/>
|
|
<defs>
|
|
<radialGradient
|
|
id="a"
|
|
cx="0"
|
|
cy="0"
|
|
r={isSafari ? '10' : '1'}
|
|
gradientUnits="userSpaceOnUse"
|
|
gradientTransform={gradientTransform}
|
|
>
|
|
<stop stopColor="hsl(var(--brand-default))" />
|
|
<stop offset="1" stopColor="var(--foreground-lighter)" />
|
|
</radialGradient>
|
|
<radialGradient
|
|
id="b"
|
|
cx="0"
|
|
cy="0"
|
|
r={isSafari ? '3' : '1'}
|
|
gradientUnits="userSpaceOnUse"
|
|
gradientTransform={gradientTransform}
|
|
>
|
|
<stop stopColor="hsl(var(--brand-default))" />
|
|
<stop offset="1" stopColor="var(--foreground-lighter)" />
|
|
</radialGradient>
|
|
<radialGradient
|
|
id="c"
|
|
cx="0"
|
|
cy="0"
|
|
r={isSafari ? '3' : '1'}
|
|
gradientUnits="userSpaceOnUse"
|
|
gradientTransform={gradientTransform}
|
|
>
|
|
<stop stopColor="hsl(var(--brand-default))" />
|
|
<stop offset="1" stopColor="var(--foreground-lighter)" />
|
|
</radialGradient>
|
|
</defs>
|
|
</svg>
|
|
</span>
|
|
</figure>
|
|
)
|
|
}
|
|
|
|
export default DatabaseVisual
|