mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 01:15:03 +03:00
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Feature ## What is the current behavior? Region and data residency information is split across docs, `/security`, and legal pages. [MARKET-1866](https://linear.app/supabase/issue/MARKET-1866/package-and-display-available-regions-better-on-website) ## What is the new behavior? Adds `/regions`: a catalog of all 17 regions generated from `regions.ts`, plus what stays in-region, the Europe vs EU caveat, and links to the DPA, GDPR guide, sub-processor list, and security page. Regions is in the footer under Security & Compliance. The security page residency card now links here. ## Test plan - [ ] Open `/regions` in light and dark mode - [ ] Confirm the region count and list match `packages/shared-data/regions.ts` - [ ] Confirm footer Regions link and `/security` residency link go to `/regions` Made with [Cursor](https://cursor.com) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added a Regions page showcasing available AWS regions by geography. - Added an interactive map and region list with selection, hover states, keyboard accessibility, and residency badges. - Included data residency guidance, legal resources, and a call-to-action for next steps. - Added Regions links in the site footer and security documentation. - **Documentation** - Updated agent skill resources with expanded troubleshooting and operational guidance. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Francesco Sansalvadore <f.sansalvadore@gmail.com>
76 lines
2.8 KiB
TypeScript
76 lines
2.8 KiB
TypeScript
'use client'
|
|
|
|
import { Badge, cn } from 'ui'
|
|
|
|
import { GROUPED_REGIONS } from './Regions.constants'
|
|
|
|
interface Props {
|
|
selectedRegionCode: string | null
|
|
hoveredRegionCode?: string
|
|
onRegionHover: (code?: string) => void
|
|
onRegionSelect: (code: string) => void
|
|
}
|
|
|
|
export const RegionsList = ({
|
|
selectedRegionCode,
|
|
hoveredRegionCode,
|
|
onRegionHover,
|
|
onRegionSelect,
|
|
}: Props) => (
|
|
<div className="grid grid-cols-1 gap-8 md:grid-cols-3 lg:gap-12">
|
|
{GROUPED_REGIONS.map(({ group, regions }) => (
|
|
<div key={group} className="flex flex-col gap-3">
|
|
<h3 className="font-mono text-xs uppercase tracking-widest text-foreground-muted">
|
|
{group}
|
|
</h3>
|
|
<ul className="flex flex-col divide-y divide-border-muted border-t border-border-muted">
|
|
{regions.map((region) => {
|
|
const isSelected = region.code === selectedRegionCode
|
|
|
|
return (
|
|
<li key={region.code}>
|
|
<button
|
|
type="button"
|
|
tabIndex={0}
|
|
aria-pressed={isSelected}
|
|
onClick={() => onRegionSelect(region.code)}
|
|
onMouseEnter={() => onRegionHover(region.code)}
|
|
onMouseLeave={() => onRegionHover(undefined)}
|
|
onFocus={() => onRegionHover(region.code)}
|
|
onBlur={() => onRegionHover(undefined)}
|
|
className={cn(
|
|
// Bleeds the hover background 8px each side so row content stays aligned with the heading
|
|
'-mx-2 flex w-[calc(100%+1rem)] items-center gap-3 rounded-sm px-2 py-2.5 text-left transition-colors',
|
|
'hover:bg-surface-100 focus-visible:ring-2 focus-visible:ring-foreground-lighter focus-visible:outline-none',
|
|
isSelected && 'bg-surface-100',
|
|
!isSelected && region.code === hoveredRegionCode && 'bg-surface-100'
|
|
)}
|
|
>
|
|
{/* Flags are SVGs, which next/image can't serve while dangerouslyAllowSVG is off */}
|
|
<img
|
|
alt=""
|
|
className="w-4 shrink-0 rounded-xs"
|
|
src={`/images/regions/${region.code}.svg`}
|
|
/>
|
|
<span
|
|
className={cn(
|
|
'text-xs',
|
|
isSelected ? 'text-foreground' : 'text-foreground-light'
|
|
)}
|
|
>
|
|
{region.displayName}
|
|
</span>
|
|
{region.jurisdiction && <Badge>{region.jurisdiction}</Badge>}
|
|
<code className="ml-auto shrink-0 font-mono text-xs text-foreground-lighter">
|
|
{region.code}
|
|
</code>
|
|
</button>
|
|
</li>
|
|
)
|
|
})}
|
|
</ul>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)
|