mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 17:35:10 +03:00
## What kind of change does this PR introduce? Refactor. Follow-up to #49871. ## What is the current behavior? Branded (green) text still uses the `text-brand` classname while the colour comes from `--primary`. ## What is the new behavior? **Rename-only:** `text-brand` → `text-primary` across callsites and docs. Leftover `bg-brand` / `border-brand` alias to `brand-default`. No intentional colour changes in this PR. This better matches how we treat our green in other components and props, like `variant="primary"` for green buttons. ## To test On light mode: smoke-test that branded text still looks like #49871 (readable green, not the bright fill). - [Homepage](https://zone-www-dot-com-git-dnywh-depr-316-text-brand-de2380-supabase.vercel.app/): “Scale to millions” uses `text-primary` - [Docs homepage](https://docs-git-dnywh-depr-316-text-brand-to-primary-supabase.vercel.app/docs): branded links like “More on self-hosting” are still readable - [Typography docs](https://design-system-git-dnywh-depr-316-text-brand-to-primary-supabase.vercel.app/design-system/docs/typography): documents `text-primary` - [Colour usage](https://design-system-git-dnywh-depr-316-text-brand-to-primary-supabase.vercel.app/design-system/docs/color-usage): `text-primary` is visibly darker than `bg-brand-default` _on light mode_ - [Studio auth providers](https://studio-staging-git-dnywh-depr-316-text-brand-to-60fa6c-supabase.vercel.app/dashboard/project/_/auth/providers): enabled provider badge text readable; status dot stays bright green <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Style** * Updated branded text, link hover states, icons, badges, indicators, and highlighted content across the Design System, Docs, Studio, Learn, UI Library, and marketing experiences to use the primary theme color. * Updated syntax highlighting and table-of-contents styling for consistent primary-color presentation. * Refined brand color fallback behavior for bright fills and borders. * **Documentation** * Updated color-usage and typography guidance to recommend the primary text utility. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
206 lines
6.1 KiB
TypeScript
206 lines
6.1 KiB
TypeScript
'use client'
|
|
|
|
import { AnimatedCounter } from '../AnimatedCounter'
|
|
import { AnimatedGridBackground } from '../AnimatedGridBackground'
|
|
|
|
type HeroStat = {
|
|
headline: string
|
|
number: number
|
|
increment: number
|
|
intervalMs: number
|
|
}
|
|
|
|
const heroStats: HeroStat[] = [
|
|
{
|
|
headline: 'More databases created in 2025 than in all previous years combined',
|
|
number: 15_106_212,
|
|
increment: 1,
|
|
intervalMs: 1000,
|
|
},
|
|
{
|
|
headline: 'Projects created',
|
|
number: 11_808_815,
|
|
increment: 1,
|
|
intervalMs: 500,
|
|
},
|
|
{
|
|
headline: 'Realtime messages delivered',
|
|
number: 280_355_288_012,
|
|
increment: 1931,
|
|
intervalMs: 200,
|
|
},
|
|
]
|
|
|
|
type GridStat = {
|
|
headline: string
|
|
number: number
|
|
increment: number
|
|
suffix?: string
|
|
prefix?: string
|
|
}
|
|
|
|
const gridStats: GridStat[] = [
|
|
{
|
|
headline: 'Peak concurrent Realtime connections',
|
|
number: 193_942,
|
|
increment: 0,
|
|
},
|
|
{
|
|
headline: 'Edge Functions invoked',
|
|
number: 49_632_206_530,
|
|
increment: 1_709,
|
|
},
|
|
{
|
|
headline: 'Images transformed via Storage',
|
|
number: 64_454_990,
|
|
increment: 2,
|
|
},
|
|
{
|
|
headline: 'Petabytes stored',
|
|
number: 64.5,
|
|
increment: 0,
|
|
suffix: 'PB',
|
|
},
|
|
{
|
|
headline: 'Petabytes served',
|
|
number: 19.3,
|
|
increment: 0,
|
|
suffix: 'PB',
|
|
},
|
|
{
|
|
headline: 'One of the top 100 repos on Github',
|
|
number: 94_500,
|
|
increment: 0,
|
|
suffix: 'stars',
|
|
},
|
|
{
|
|
headline: 'paid to fund open source',
|
|
number: 662_357.71,
|
|
increment: 0,
|
|
prefix: '$',
|
|
suffix: 'USD',
|
|
},
|
|
{
|
|
headline: 'Commits to our repos by community members',
|
|
number: 1_421,
|
|
increment: 0,
|
|
},
|
|
]
|
|
|
|
export const Devs = () => {
|
|
return (
|
|
<>
|
|
<section className="relative max-w-240 h-[240px] md:h-[360px] mx-auto border-x border-b w-[95%] md:w-full">
|
|
{/* Grid background */}
|
|
<AnimatedGridBackground
|
|
cols={5}
|
|
rows={{ mobile: 2, desktop: 3 }}
|
|
tiles={[
|
|
{ cell: 0, type: 'dots' },
|
|
{ cell: 2, type: 'stripes' },
|
|
{ cell: 3, type: 'stripes' },
|
|
{ cell: 4, type: 'stripes' },
|
|
{ cell: 5, type: 'stripes' },
|
|
{ cell: 7, type: 'dots' },
|
|
]}
|
|
initialDelay={0.35}
|
|
/>
|
|
|
|
{/* Content */}
|
|
<div className="flex flex-col justify-end h-full px-4 py-0 relative">
|
|
<div className="flex justify-between items-center">
|
|
<h2 className="font-medium tracking-tighter text-6xl md:text-7xl lg:text-[5.6rem] translate-y-2 lg:translate-y-[10px]">
|
|
Devs <span className="text-primary">love</span> Supabase
|
|
</h2>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<div className="relative max-w-240 mx-auto border-x border-b px-4 lg:px-8 py-12 w-[95%] md:w-full">
|
|
<p className="text-lg text-foreground-light max-w-2xl">
|
|
In 2025, developers around the world shipped faster, scaled further, and built things we
|
|
never imagined. Here is what you accomplished on Supabase.
|
|
</p>
|
|
</div>
|
|
|
|
{/* Hero stats */}
|
|
{heroStats.map((stat) => (
|
|
<div
|
|
key={stat.headline}
|
|
className="relative max-w-240 mx-auto border-x border-b p-8 bg-surface-75 w-[95%] md:w-full"
|
|
>
|
|
<div className="flex flex-col gap-2">
|
|
<p className="text-4xl md:text-5xl font-mono font-medium text-primary tracking-tighter">
|
|
<AnimatedCounter
|
|
value={stat.number}
|
|
increment={stat.increment}
|
|
intervalMs={stat.intervalMs}
|
|
/>
|
|
</p>
|
|
<p className="text-base text-foreground-light">{stat.headline}</p>
|
|
</div>
|
|
</div>
|
|
))}
|
|
|
|
{/* Stats grid */}
|
|
<div className="relative max-w-240 mx-auto border-x w-[95%] md:w-full">
|
|
<div className="grid grid-cols-2 lg:grid-cols-4">
|
|
{(() => {
|
|
const cols = 4
|
|
const remainder = gridStats.length % cols
|
|
const emptyCells = remainder === 0 ? 0 : cols - remainder
|
|
|
|
return (
|
|
<>
|
|
{gridStats.map((stat) => (
|
|
<div
|
|
key={stat.headline}
|
|
className="p-8 border-r border-b border-muted nth-[2n]:border-r-0 lg:nth-[2n]:border-r nth-[4n]:border-r-0"
|
|
>
|
|
<div className="flex flex-col gap-2">
|
|
<div className="flex flex-col">
|
|
<p
|
|
className={`text-2xl md:text-3xl font-mono font-medium tracking-tighter ${stat.increment > 0 ? 'text-primary' : 'text-foreground'}`}
|
|
>
|
|
{stat.suffix ? (
|
|
<>
|
|
{stat.prefix}
|
|
{new Intl.NumberFormat('en-US', {
|
|
notation: 'compact',
|
|
maximumFractionDigits: stat.number % 1 !== 0 ? 2 : 0,
|
|
minimumFractionDigits: stat.number % 1 !== 0 ? 1 : 0,
|
|
})
|
|
.format(stat.number)
|
|
.toLowerCase()}
|
|
<span className="text-lg ml-1.5 font-medium tracking-tight">
|
|
{stat.suffix}
|
|
</span>
|
|
</>
|
|
) : (
|
|
<AnimatedCounter
|
|
value={stat.number}
|
|
increment={stat.increment}
|
|
compact
|
|
/>
|
|
)}
|
|
</p>
|
|
</div>
|
|
<p className="text-sm text-foreground-lighter">{stat.headline}</p>
|
|
</div>
|
|
</div>
|
|
))}
|
|
{Array.from({ length: emptyCells }).map((_, i) => (
|
|
<div
|
|
key={`empty-${i}`}
|
|
className="px-6 py-8 border-r border-b border-muted last:border-r-0"
|
|
/>
|
|
))}
|
|
</>
|
|
)
|
|
})()}
|
|
</div>
|
|
</div>
|
|
</>
|
|
)
|
|
}
|