mirror of
https://github.com/supabase/supabase.git
synced 2026-10-10 20:05:06 +03:00
upd
This commit is contained in:
1 parent
1038d88241
commit
4e986a4ef2
4 files changed
+204
-192
No files matched your search
@@ -17,30 +17,29 @@ export function ExamplesSection() {
|
||||
const gridExamples = examples.slice(2, 6)
|
||||
|
||||
return (
|
||||
<div>
|
||||
{/* Header row */}
|
||||
<div className="border-b border-border">
|
||||
<div className="mx-auto max-w-[var(--container-max-w,75rem)] px-6 border-x border-border">
|
||||
<div className="flex items-end justify-between pt-40 pb-8">
|
||||
<h3 className="text-2xl md:text-4xl text-foreground-lighter max-w-xl">
|
||||
What you can build <br />
|
||||
<span className="text-foreground">with Edge Functions</span>
|
||||
</h3>
|
||||
<Link
|
||||
href="/docs/guides/functions#examples"
|
||||
className="text-sm text-foreground-light hover:text-foreground underline"
|
||||
>
|
||||
View all examples
|
||||
</Link>
|
||||
</div>
|
||||
<div className="py-24 flex flex-col gap-16">
|
||||
{/* Header */}
|
||||
<div className="mx-auto max-w-[var(--container-max-w,75rem)] px-6 w-full">
|
||||
<div className="flex items-end justify-between">
|
||||
<h3 className="text-2xl md:text-4xl text-foreground-lighter max-w-xl">
|
||||
What you can build <br />
|
||||
<span className="text-foreground">with Edge Functions</span>
|
||||
</h3>
|
||||
<Link
|
||||
href="/docs/guides/functions#examples"
|
||||
className="text-sm text-foreground-light hover:text-foreground underline"
|
||||
>
|
||||
View all examples
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Featured row - 2 large cells */}
|
||||
<div className="border-b border-border max-w-[var(--container-max-w,75rem)] mx-auto">
|
||||
<div className="border-x border-border">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2">
|
||||
{featuredExamples.map((example) => {
|
||||
{/* Cards */}
|
||||
<div className="mx-auto max-w-[var(--container-max-w,75rem)] w-full">
|
||||
<div className="border border-border rounded-md overflow-clip">
|
||||
{/* Featured row - 2 large cells */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 border-b border-border">
|
||||
{featuredExamples.map((example, i) => {
|
||||
const tag = example.tags?.[0]
|
||||
const icon = tag ? EXAMPLE_ICON[tag] : undefined
|
||||
return (
|
||||
@@ -48,7 +47,45 @@ export function ExamplesSection() {
|
||||
key={example.title}
|
||||
href={example.repo_url ?? '#'}
|
||||
target="_blank"
|
||||
className="group flex flex-col border-b md:border-b-0 md:border-r border-border last:border-r-0 last:border-b-0 px-6 py-8 hover:bg-surface-75/50 transition-colors"
|
||||
className={`group flex flex-col px-6 py-8 hover:bg-surface-75/50 transition-colors ${
|
||||
i < featuredExamples.length - 1
|
||||
? 'border-b md:border-b-0 md:border-r border-border'
|
||||
: ''
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
{icon && (
|
||||
<img
|
||||
src={icon.src}
|
||||
alt=""
|
||||
className={`${icon.className} object-contain${icon.invert ? ' dark:invert' : ''}`}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<h4 className="text-foreground text-sm font-medium">{example.title}</h4>
|
||||
<p className="text-foreground-lighter text-sm mt-1 line-clamp-2">
|
||||
{example.description}
|
||||
</p>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Grid row - 4 smaller cells */}
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4">
|
||||
{gridExamples.map((example, i) => {
|
||||
const tag = example.tags?.[0]
|
||||
const icon = tag ? EXAMPLE_ICON[tag] : undefined
|
||||
return (
|
||||
<Link
|
||||
key={example.title}
|
||||
href={example.repo_url ?? '#'}
|
||||
target="_blank"
|
||||
className={`group flex flex-col px-6 py-8 hover:bg-surface-75/50 transition-colors ${
|
||||
i < gridExamples.length - 1
|
||||
? 'border-b sm:border-b-0 sm:border-r border-border'
|
||||
: ''
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
{icon && (
|
||||
@@ -69,38 +106,6 @@ export function ExamplesSection() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Grid row - 4 smaller cells */}
|
||||
<div className="mx-auto max-w-[var(--container-max-w,75rem)] border-x border-border">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4">
|
||||
{gridExamples.map((example) => {
|
||||
const tag = example.tags?.[0]
|
||||
const icon = tag ? EXAMPLE_ICON[tag] : undefined
|
||||
return (
|
||||
<Link
|
||||
key={example.title}
|
||||
href={example.repo_url ?? '#'}
|
||||
target="_blank"
|
||||
className="group flex flex-col border-b sm:border-b-0 sm:border-r border-border last:border-r-0 last:border-b-0 px-6 py-8 hover:bg-surface-75/50 transition-colors"
|
||||
>
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
{icon && (
|
||||
<img
|
||||
src={icon.src}
|
||||
alt=""
|
||||
className={`${icon.className} object-contain${icon.invert ? ' dark:invert' : ''}`}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<h4 className="text-foreground text-sm font-medium">{example.title}</h4>
|
||||
<p className="text-foreground-lighter text-sm mt-1 line-clamp-2">
|
||||
{example.description}
|
||||
</p>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -72,109 +72,109 @@ export function IntegratesSectionClient({ useCases }: { useCases: UseCase[] }) {
|
||||
}
|
||||
|
||||
return (
|
||||
<div ref={inViewRef}>
|
||||
{/* Header row */}
|
||||
<div className="border-b border-border">
|
||||
<div className="mx-auto max-w-[var(--container-max-w,75rem)] px-6 border-x border-border">
|
||||
<h3 className="text-2xl md:text-4xl text-foreground-lighter max-w-xl pt-40 pb-8">
|
||||
Integrates with the <span className="text-foreground">Supabase ecosystem</span>
|
||||
</h3>
|
||||
</div>
|
||||
<div ref={inViewRef} className="py-24 flex flex-col gap-16 border-b border-border">
|
||||
{/* Header */}
|
||||
<div className="mx-auto max-w-[var(--container-max-w,75rem)] px-6 w-full">
|
||||
<h3 className="text-2xl md:text-4xl text-foreground-lighter max-w-xl">
|
||||
Integrates with the <span className="text-foreground">Supabase ecosystem</span>
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="mx-auto max-w-[var(--container-max-w,75rem)] border-x border-border">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-0">
|
||||
{/* Left: vertical tabs */}
|
||||
<div className="flex flex-col">
|
||||
{useCases.map((useCase, index) => {
|
||||
const isActive = index === activeIdx
|
||||
return (
|
||||
<button
|
||||
key={useCase.label}
|
||||
onClick={() => handleTabClick(index)}
|
||||
className={cn(
|
||||
'relative text-left flex flex-col gap-1 px-6 py-5 transition-colors',
|
||||
isActive
|
||||
? 'bg-surface-75 text-foreground'
|
||||
: 'text-foreground-muted hover:text-foreground-light hover:bg-surface-75/50'
|
||||
)}
|
||||
>
|
||||
<h4 className="text-sm font-medium flex items-center gap-2">
|
||||
{(() => {
|
||||
const Icon = ICONS[useCase.icon]
|
||||
return <Icon size={14} strokeWidth={2} />
|
||||
})()}
|
||||
{useCase.label}
|
||||
</h4>
|
||||
<p
|
||||
<div className="mx-auto max-w-[var(--container-max-w,75rem)] w-full">
|
||||
<div className="border border-border rounded-md overflow-clip">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-0">
|
||||
{/* Left: vertical tabs */}
|
||||
<div className="flex flex-col">
|
||||
{useCases.map((useCase, index) => {
|
||||
const isActive = index === activeIdx
|
||||
return (
|
||||
<button
|
||||
key={useCase.label}
|
||||
onClick={() => handleTabClick(index)}
|
||||
className={cn(
|
||||
'text-sm transition-colors',
|
||||
isActive ? 'text-foreground-lighter' : 'text-foreground-muted'
|
||||
'relative text-left flex flex-col gap-1 px-6 py-5 transition-colors',
|
||||
isActive
|
||||
? 'bg-surface-75 text-foreground'
|
||||
: 'text-foreground-muted hover:text-foreground-light hover:bg-surface-75/50'
|
||||
)}
|
||||
>
|
||||
{useCase.paragraph}
|
||||
</p>
|
||||
{/* Progress bar — hide on last item to avoid doubling with section border-y */}
|
||||
<div className={cn("absolute bottom-0 left-0 right-0 h-[1px] bg-border-strong overflow-hidden", index === useCases.length - 1 && 'hidden')}>
|
||||
{isActive && (
|
||||
<motion.div
|
||||
className={cn(
|
||||
'absolute inset-0 w-full right-full bg-foreground-muted h-full transition-opacity',
|
||||
progress > 99.5 ? 'opacity-0' : 'opacity-100'
|
||||
)}
|
||||
style={{ x: `${progress - 100}%` }}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
<h4 className="text-sm font-medium flex items-center gap-2">
|
||||
{(() => {
|
||||
const Icon = ICONS[useCase.icon]
|
||||
return <Icon size={14} strokeWidth={2} />
|
||||
})()}
|
||||
{useCase.label}
|
||||
</h4>
|
||||
<p
|
||||
className={cn(
|
||||
'text-sm transition-colors',
|
||||
isActive ? 'text-foreground-lighter' : 'text-foreground-muted'
|
||||
)}
|
||||
>
|
||||
{useCase.paragraph}
|
||||
</p>
|
||||
{/* Progress bar — hide on last item to avoid doubling with section border */}
|
||||
<div className={cn("absolute bottom-0 left-0 right-0 h-[1px] bg-border-strong overflow-hidden", index === useCases.length - 1 && 'hidden')}>
|
||||
{isActive && (
|
||||
<motion.div
|
||||
className={cn(
|
||||
'absolute inset-0 w-full right-full bg-foreground-muted h-full transition-opacity',
|
||||
progress > 99.5 ? 'opacity-0' : 'opacity-100'
|
||||
)}
|
||||
style={{ x: `${progress - 100}%` }}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Right: code area */}
|
||||
<div className="relative min-h-[440px] overflow-auto lg:border-l border-border">
|
||||
<AnimatePresence mode="wait">
|
||||
<motion.div
|
||||
key={active.label}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1, transition: { duration: 0.15, delay: 0.05 } }}
|
||||
exit={{ opacity: 0, transition: { duration: 0.05 } }}
|
||||
{/* Right: code area */}
|
||||
<div className="relative min-h-[440px] overflow-auto lg:border-l border-border">
|
||||
<AnimatePresence mode="wait">
|
||||
<motion.div
|
||||
key={active.label}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1, transition: { duration: 0.15, delay: 0.05 } }}
|
||||
exit={{ opacity: 0, transition: { duration: 0.05 } }}
|
||||
>
|
||||
<div
|
||||
dangerouslySetInnerHTML={{ __html: active.darkHtml }}
|
||||
className="hidden dark:block [&_pre]:!bg-transparent [&_pre]:m-0 [&_pre]:p-6"
|
||||
style={{ fontSize: '0.8125rem', fontWeight: 500, lineHeight: 1.7 }}
|
||||
/>
|
||||
<div
|
||||
dangerouslySetInnerHTML={{ __html: active.lightHtml }}
|
||||
className="block dark:hidden [&_pre]:!bg-transparent [&_pre]:m-0 [&_pre]:p-6"
|
||||
style={{ fontSize: '0.8125rem', fontWeight: 500, lineHeight: 1.7 }}
|
||||
/>
|
||||
</motion.div>
|
||||
</AnimatePresence>
|
||||
<Link
|
||||
href="/docs/guides/functions"
|
||||
className="absolute bottom-4 right-4 flex items-center gap-1.5 rounded-full bg-surface-100 border border-border px-3 py-1.5 text-xs text-foreground-light hover:text-foreground hover:bg-surface-200 transition-colors whitespace-nowrap"
|
||||
>
|
||||
<div
|
||||
dangerouslySetInnerHTML={{ __html: active.darkHtml }}
|
||||
className="hidden dark:block [&_pre]:!bg-transparent [&_pre]:m-0 [&_pre]:p-6"
|
||||
style={{ fontSize: '0.8125rem', fontWeight: 500, lineHeight: 1.7 }}
|
||||
/>
|
||||
<div
|
||||
dangerouslySetInnerHTML={{ __html: active.lightHtml }}
|
||||
className="block dark:hidden [&_pre]:!bg-transparent [&_pre]:m-0 [&_pre]:p-6"
|
||||
style={{ fontSize: '0.8125rem', fontWeight: 500, lineHeight: 1.7 }}
|
||||
/>
|
||||
</motion.div>
|
||||
</AnimatePresence>
|
||||
<Link
|
||||
href="/docs/guides/functions"
|
||||
className="absolute bottom-4 right-4 flex items-center gap-1.5 rounded-full bg-surface-100 border border-border px-3 py-1.5 text-xs text-foreground-light hover:text-foreground hover:bg-surface-200 transition-colors whitespace-nowrap"
|
||||
>
|
||||
Documentation
|
||||
<svg
|
||||
width={12}
|
||||
height={12}
|
||||
viewBox="0 0 12 12"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="shrink-0"
|
||||
>
|
||||
<path
|
||||
d="M3.5 2.5H9.5V8.5M9.5 2.5L2.5 9.5"
|
||||
stroke="currentColor"
|
||||
strokeWidth={1.5}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</Link>
|
||||
Documentation
|
||||
<svg
|
||||
width={12}
|
||||
height={12}
|
||||
viewBox="0 0 12 12"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="shrink-0"
|
||||
>
|
||||
<path
|
||||
d="M3.5 2.5H9.5V8.5M9.5 2.5L2.5 9.5"
|
||||
stroke="currentColor"
|
||||
strokeWidth={1.5}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -123,38 +123,38 @@ function LocalDXCard() {
|
||||
|
||||
export function LocalDXSection() {
|
||||
return (
|
||||
<div>
|
||||
{/* Header row */}
|
||||
<div className="border-b border-border">
|
||||
<div className="mx-auto max-w-[var(--container-max-w,75rem)] px-6 border-x border-border">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8 lg:gap-16 items-end pt-40 pb-8">
|
||||
<h3 className="text-2xl md:text-4xl text-foreground-lighter max-w-xl">
|
||||
Delightful DX from <br />
|
||||
<span className="text-foreground">local to production</span>
|
||||
</h3>
|
||||
<p className="text-foreground-lighter text-sm lg:text-base">
|
||||
Edge Functions are developed using{' '}
|
||||
<Link
|
||||
href="https://deno.com/"
|
||||
className="underline hover:text-foreground-light transition-colors"
|
||||
target="_blank"
|
||||
>
|
||||
Deno
|
||||
</Link>
|
||||
, an open source JavaScript runtime that ensures maximum power and flexibility.
|
||||
Migrate in and out at any time with no vendor lock-in.
|
||||
</p>
|
||||
</div>
|
||||
<div className="py-24 flex flex-col gap-16">
|
||||
{/* Header */}
|
||||
<div className="mx-auto max-w-[var(--container-max-w,75rem)] px-6 w-full">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8 lg:gap-16 items-end">
|
||||
<h3 className="text-2xl md:text-4xl text-foreground-lighter max-w-xl">
|
||||
Delightful DX from <br />
|
||||
<span className="text-foreground">local to production</span>
|
||||
</h3>
|
||||
<p className="text-foreground-lighter text-sm lg:text-base">
|
||||
Edge Functions are developed using{' '}
|
||||
<Link
|
||||
href="https://deno.com/"
|
||||
className="underline hover:text-foreground-light transition-colors"
|
||||
target="_blank"
|
||||
>
|
||||
Deno
|
||||
</Link>
|
||||
, an open source JavaScript runtime that ensures maximum power and flexibility. Migrate
|
||||
in and out at any time with no vendor lock-in.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bento grid */}
|
||||
<div className="mx-auto max-w-[var(--container-max-w,75rem)] border-x border-border">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 grid-flow-dense">
|
||||
<LocalDXCard />
|
||||
<ParityCard />
|
||||
<CICard />
|
||||
<EcosystemCard />
|
||||
<div className="mx-auto max-w-[var(--container-max-w,75rem)] w-full">
|
||||
<div className="border border-border rounded-md overflow-clip">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 grid-flow-dense">
|
||||
<LocalDXCard />
|
||||
<ParityCard />
|
||||
<CICard />
|
||||
<EcosystemCard />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -55,26 +55,33 @@ function ObservabilityCard({
|
||||
|
||||
export function ObservabilitySection() {
|
||||
return (
|
||||
<div>
|
||||
{/* Header row */}
|
||||
<div className="border-b border-border">
|
||||
<div className="mx-auto max-w-[var(--container-max-w,75rem)] px-6 border-x border-border">
|
||||
<h3 className="text-2xl md:text-4xl text-foreground-lighter max-w-xl pt-40 pb-8">
|
||||
Built-in <span className="text-foreground">observability</span>
|
||||
<div className="py-24 flex flex-col gap-16">
|
||||
{/* Header */}
|
||||
<div className="mx-auto max-w-[var(--container-max-w,75rem)] px-6 w-full">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8 lg:gap-16 items-end">
|
||||
<h3 className="text-2xl md:text-4xl text-foreground-lighter max-w-xl">
|
||||
Debug and monitor with <br />
|
||||
<span className="text-foreground">built-in observability</span>
|
||||
</h3>
|
||||
<p className="text-foreground-lighter text-sm lg:text-base">
|
||||
Monitor, debug, and optimize your Edge Functions with realtime logs, queryable log
|
||||
explorer, and health dashboards — all built into the Supabase Dashboard.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 3-column grid */}
|
||||
<div className="mx-auto max-w-[var(--container-max-w,75rem)] border-x border-border">
|
||||
<div className="grid grid-cols-1 md:grid-cols-3">
|
||||
{cards.map((card, i) => (
|
||||
<ObservabilityCard
|
||||
key={card.id}
|
||||
card={card}
|
||||
className={cn(i < cards.length - 1 && 'md:border-r')}
|
||||
/>
|
||||
))}
|
||||
<div className="mx-auto max-w-[var(--container-max-w,75rem)] w-full">
|
||||
<div className="border border-border rounded-md overflow-clip">
|
||||
<div className="grid grid-cols-1 md:grid-cols-3">
|
||||
{cards.map((card, i) => (
|
||||
<ObservabilityCard
|
||||
key={card.id}
|
||||
card={card}
|
||||
className={cn(i < cards.length - 1 && 'md:border-r border-border')}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user