mirror of
https://github.com/supabase/supabase.git
synced 2026-05-08 09:50:33 -04:00
56de26fe22
This PR migrates the whole monorepo to use Tailwind v4: - Removed `@tailwindcss/container-queries` plugin since it's included by default in v4, - Bump all instances of Tailwind to v4. Made minimal changes to the shared config to remove non-supported features (`alpha` mentions), - Migrate all apps to be compatible with v4 configs, - Fix the `typography.css` import in 3 apps, - Add missing rules which were included by default in v3, - Run `pnpm dlx @tailwindcss/upgrade` on all apps, which renames a lot of classes - Rename all misnamed classes according to https://tailwindcss.com/docs/upgrade-guide#renamed-utilities in all apps. --------- Co-authored-by: Jordi Enric <jordi.err@gmail.com>
294 lines
12 KiB
TypeScript
294 lines
12 KiB
TypeScript
import { useParams } from 'common'
|
|
import { ChevronRight, FileCode, X } from 'lucide-react'
|
|
import Link from 'next/link'
|
|
import { PropsWithChildren, ReactNode } from 'react'
|
|
import {
|
|
Badge,
|
|
Button,
|
|
cn,
|
|
Collapsible_Shadcn_,
|
|
CollapsibleContent_Shadcn_,
|
|
CollapsibleTrigger_Shadcn_,
|
|
WarningIcon,
|
|
} from 'ui'
|
|
import { Admonition } from 'ui-patterns/admonition'
|
|
import { CodeBlock, type CodeBlockLang } from 'ui-patterns/CodeBlock'
|
|
|
|
import { ConnectionParameters } from './ConnectionParameters'
|
|
import { useSupavisorConfigurationQuery } from '@/data/database/supavisor-configuration-query'
|
|
import { IS_PLATFORM } from '@/lib/constants'
|
|
import { useDatabaseSelectorStateSnapshot } from '@/state/database-selector'
|
|
|
|
interface ConnectionPanelProps {
|
|
type?: 'direct' | 'transaction' | 'session'
|
|
badge?: string
|
|
title: string
|
|
description: string
|
|
contentFooter?: ReactNode
|
|
connectionString: string
|
|
ipv4Status: {
|
|
type: 'error' | 'success'
|
|
title: string
|
|
description?: string | ReactNode
|
|
links?: { text: string; url: string }[]
|
|
}
|
|
notice?: string[]
|
|
parameters?: Array<{
|
|
key: string
|
|
value: string
|
|
description?: string
|
|
}>
|
|
contentType?: 'input' | 'code'
|
|
lang?: CodeBlockLang
|
|
fileTitle?: string
|
|
onCopyCallback: () => void
|
|
}
|
|
|
|
const IPv4StatusIcon = ({ className, active }: { className?: string; active: boolean }) => {
|
|
return (
|
|
<div className={cn('relative inline-flex', className)}>
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
fill="none"
|
|
viewBox="0 0 24 24"
|
|
strokeWidth="1"
|
|
stroke="currentColor"
|
|
className="size-6 stroke-foreground-lighter"
|
|
>
|
|
<path
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
d="M12 21a9.004 9.004 0 0 0 8.716-6.747M12 21a9.004 9.004 0 0 1-8.716-6.747M12 21c2.485 0 4.5-4.03 4.5-9S14.485 3 12 3m0 18c-2.485 0-4.5-4.03-4.5-9S9.515 3 12 3m0 0a8.997 8.997 0 0 1 7.843 4.582M12 3a8.997 8.997 0 0 0-7.843 4.582m15.686 0A11.953 11.953 0 0 1 12 10.5c-2.998 0-5.74-1.1-7.843-2.918m15.686 0A8.959 8.959 0 0 1 21 12c0 .778-.099 1.533-.284 2.253m0 0A17.919 17.919 0 0 1 12 16.5c-3.162 0-6.133-.815-8.716-2.247m0 0A9.015 9.015 0 0 1 3 12c0-1.605.42-3.113 1.157-4.418"
|
|
/>
|
|
</svg>
|
|
|
|
{!active ? (
|
|
<div className="absolute -right-1.5 -top-1.5 bg-destructive rounded-sm w-4 h-4 flex items-center justify-center">
|
|
<X size={10} strokeWidth={4} className="text-white rounded-full" />
|
|
</div>
|
|
) : (
|
|
<div className="absolute -right-1.5 -top-1.5 bg-brand-500 rounded-sm w-4 h-4 flex items-center justify-center">
|
|
<svg
|
|
width="10"
|
|
height="10"
|
|
viewBox="0 0 10 10"
|
|
fill="none"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
>
|
|
<path
|
|
d="M8.33325 2.5L3.74992 7.08333L1.66659 5"
|
|
stroke="white"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export const CodeBlockFileHeader = ({ title }: { title: string }) => {
|
|
return (
|
|
<div className="flex items-center justify-between px-4 py-1 bg-surface-100/50 border border-b-0 border-surface rounded-t">
|
|
<div className="flex items-center gap-2">
|
|
<FileCode size={12} className="text-foreground-muted" strokeWidth={1.5} />
|
|
<span className="text-xs text-foreground-light">{title}</span>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export const ConnectionPanel = ({
|
|
type = 'direct',
|
|
badge,
|
|
title,
|
|
description,
|
|
contentFooter,
|
|
connectionString,
|
|
ipv4Status,
|
|
notice,
|
|
parameters = [],
|
|
lang = 'bash',
|
|
fileTitle,
|
|
children,
|
|
onCopyCallback,
|
|
}: PropsWithChildren<ConnectionPanelProps>) => {
|
|
const { ref: projectRef } = useParams()
|
|
const state = useDatabaseSelectorStateSnapshot()
|
|
|
|
const { data: poolingInfo } = useSupavisorConfigurationQuery({ projectRef })
|
|
const poolingConfiguration = poolingInfo?.find((x) => x.identifier === state.selectedDatabaseId)
|
|
const isSessionMode = poolingConfiguration?.pool_mode === 'session'
|
|
|
|
const links = ipv4Status.links ?? []
|
|
|
|
const isTransactionDedicatedPooler = type === 'transaction' && badge === 'Dedicated Pooler'
|
|
|
|
return (
|
|
<div className="relative text-sm flex flex-col gap-5 lg:grid lg:grid-cols-12 w-full">
|
|
<div className="col-span-4 flex flex-col">
|
|
<div className="flex items-center gap-x-2 mb-2">
|
|
<h1 className="text-sm">{title}</h1>
|
|
{!!badge && !isTransactionDedicatedPooler && <Badge>{badge}</Badge>}
|
|
</div>
|
|
<p className="text-sm text-foreground-light mb-4">{description}</p>
|
|
{contentFooter}
|
|
</div>
|
|
<div className="col-span-8 flex flex-col gap-2">
|
|
{isTransactionDedicatedPooler && (
|
|
<div className="text-xs flex items-center text-foreground-light">
|
|
Using the Dedicated Pooler:
|
|
</div>
|
|
)}
|
|
<div className="flex flex-col -space-y-px">
|
|
{fileTitle && <CodeBlockFileHeader title={fileTitle} />}
|
|
{type === 'transaction' && isSessionMode ? (
|
|
<Admonition
|
|
showIcon={false}
|
|
type="default"
|
|
className="[&>h5]:text-xs [&>div]:text-xs"
|
|
title="Transaction pooler is unavailable as pool mode is set to Session"
|
|
description="If you'd like to use transaction mode, update your pool mode to Transaction for the connection pooler in your project's Database Settings."
|
|
>
|
|
<Button asChild type="default" className="mt-2">
|
|
<Link
|
|
href={`/project/${projectRef}/database/settings#connection-pooler`}
|
|
className="text-xs text-light hover:text-foreground"
|
|
>
|
|
Database Settings
|
|
</Link>
|
|
</Button>
|
|
</Admonition>
|
|
) : (
|
|
<>
|
|
<CodeBlock
|
|
wrapperClassName={cn(
|
|
'[&_pre]:rounded-b-none [&_pre]:px-4 [&_pre]:py-3',
|
|
fileTitle && '[&_pre]:rounded-t-none'
|
|
)}
|
|
language={lang}
|
|
value={connectionString}
|
|
className="[&_code]:text-[12px] [&_code]:text-foreground [&_code]:whitespace-normal!"
|
|
hideLineNumbers
|
|
onCopyCallback={onCopyCallback}
|
|
/>
|
|
{notice && (
|
|
<div className="border px-4 py-1 w-full justify-start rounded-t-none !last:rounded-b group-data-open:rounded-b-none border-light">
|
|
{notice?.map((text: string) => (
|
|
<p key={text} className="text-xs text-foreground-lighter">
|
|
{text}
|
|
</p>
|
|
))}
|
|
</div>
|
|
)}
|
|
{parameters.length > 0 && <ConnectionParameters parameters={parameters} />}
|
|
</>
|
|
)}
|
|
</div>
|
|
<div className="flex flex-col -space-y-px w-full">
|
|
{IS_PLATFORM && (
|
|
<div className="border border-muted px-5 flex gap-7 items-center py-3 first:rounded-t last:rounded-b">
|
|
<div className="flex items-center gap-2">
|
|
<IPv4StatusIcon active={ipv4Status.type === 'success'} />
|
|
</div>
|
|
<div className="flex flex-col">
|
|
<span className="text-xs text-foreground">{ipv4Status.title}</span>
|
|
{ipv4Status.description &&
|
|
(typeof ipv4Status.description === 'string' ? (
|
|
<span className="text-xs text-foreground-lighter">
|
|
{ipv4Status.description}
|
|
</span>
|
|
) : (
|
|
ipv4Status.description
|
|
))}
|
|
{links.length > 0 && (
|
|
<div className="flex items-center gap-x-2 mt-2">
|
|
{links.map((link) => (
|
|
<Button key={link.text} asChild type="default" size="tiny">
|
|
<Link href={link.url} className="text-xs text-light hover:text-foreground">
|
|
{link.text}
|
|
</Link>
|
|
</Button>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{type === 'session' && (
|
|
<div className="border border-muted px-5 flex gap-7 items-center py-3 first:rounded-t last:rounded-b bg-alternative/50">
|
|
<div className="flex w-6 h-6 rounded-sm items-center justify-center gap-2 shrink-0 bg-surface-100">
|
|
<WarningIcon />
|
|
</div>
|
|
<div className="flex flex-col">
|
|
<span className="text-xs text-foreground">Only use on a IPv4 network</span>
|
|
<div className="flex flex-col text-xs text-foreground-lighter">
|
|
<p>Session pooler connections are IPv4 proxied for free.</p>
|
|
<p>Use Direct Connection if connecting via an IPv6 network.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{IS_PLATFORM && ipv4Status.type === 'error' && (
|
|
<Collapsible_Shadcn_ className="group -space-y-px">
|
|
<CollapsibleTrigger_Shadcn_
|
|
asChild
|
|
className="group/collapse w-full justify-start rounded-t-none !last:rounded-b group-data-open:rounded-b-none border-muted"
|
|
>
|
|
<Button
|
|
type="default"
|
|
size="tiny"
|
|
className="text-foreground-lighter bg-dash-sidebar!"
|
|
icon={
|
|
<ChevronRight
|
|
className={cn(
|
|
'group-data-open/collapse:rotate-90 text-foreground-muted transition-transform'
|
|
)}
|
|
/>
|
|
}
|
|
>
|
|
Some platforms are IPv4-only:
|
|
</Button>
|
|
</CollapsibleTrigger_Shadcn_>
|
|
<CollapsibleContent_Shadcn_ className="bg-dash-sidebar rounded-b border px-3 py-2">
|
|
<div className="flex flex-col gap-2">
|
|
<p className="text-xs text-foreground-light max-w-xs">
|
|
A few major platforms are IPv4-only and may not work with a Direct Connection:
|
|
</p>
|
|
<div className="flex gap-4">
|
|
<div className="text-foreground text-xs">Vercel</div>
|
|
<div className="text-foreground text-xs">GitHub Actions</div>
|
|
<div className="text-foreground text-xs">Render</div>
|
|
<div className="text-foreground text-xs">Retool</div>
|
|
</div>
|
|
<p className="text-xs text-foreground-lighter max-w-xs">
|
|
If you wish to use a Direct Connection with these, please purchase{' '}
|
|
<Link
|
|
href={`/project/${projectRef}/settings/addons?panel=ipv4`}
|
|
className="text-xs text-light hover:text-foreground"
|
|
>
|
|
IPv4 support
|
|
</Link>
|
|
.
|
|
</p>
|
|
<p className="text-xs text-foreground-lighter max-w-xs">
|
|
You may also use the{' '}
|
|
<span className="text-foreground-light">Session Pooler</span> or{' '}
|
|
<span className="text-foreground-light">Transaction Pooler</span> if you are on
|
|
a IPv4 network.
|
|
</p>
|
|
</div>
|
|
</CollapsibleContent_Shadcn_>
|
|
</Collapsible_Shadcn_>
|
|
)}
|
|
</div>
|
|
{children}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|