Files
supabase/apps/studio/components/interfaces/QuerySources/DatabaseParametersSubMenu.tsx
T
Joshen Lim 09a1f431bc Mass update for all lucide icon imports to use the component with Icon suffix (#51659)
## Context

This is largely just a mechanical change here:
Opting to use lucide icons with the `Icon` suffix across all icon
imports within `studio`
- so that it’s clearer which components are icons + reduces the
possibility of name collision with our own components
- e.g <User /> vs <UserIcon />

Also added a eslint rule for this:
<img width="1069" height="167" alt="image"
src="https://github.com/user-attachments/assets/7f36f443-5ca2-4bf6-8d22-86e774513bfc"
/>

And updated `AGENTS.md` as such:
```
Icons come from `lucide-react`, always imported with the `Icon` suffix (`import { CheckIcon, Trash2Icon } from 'lucide-react'`) — never the bare names (`Check`) or `Check as CheckIcon` aliases (lint-enforced).
```
2026-10-14 12:56:55 +02:00

88 lines
3.3 KiB
TypeScript

import { IS_PLATFORM, useParams } from 'common'
import { CheckIcon, PlusIcon } from 'lucide-react'
import Link from 'next/link'
import {
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
} from 'ui'
import { getAddReadReplicaPath } from '@/components/interfaces/Settings/Infrastructure/Infrastructure.utils'
import { useReadReplicasQuery } from '@/data/read-replicas/replicas-query'
import { formatDatabaseID, formatDatabaseRegion } from '@/data/read-replicas/replicas.utils'
import { useIsFeatureEnabled } from '@/hooks/misc/useIsFeatureEnabled'
import { useIsHighAvailability } from '@/hooks/misc/useSelectedProject'
/** The label a database row/summary shows: the primary, or a replica by region + id. */
function databaseLabel(identifier: string, region: string, projectRef: string | undefined) {
if (identifier === projectRef) return 'Primary database'
return `Read replica (${formatDatabaseRegion(region)} - ${formatDatabaseID(identifier)})`
}
export const DatabaseParametersSubMenu = ({
identifier,
onIdentifierChange,
}: {
identifier?: string
onIdentifierChange: (identifier: string) => void
}) => {
const { ref: projectRef } = useParams()
const isHighAvailability = useIsHighAvailability()
const { infrastructureReadReplicas } = useIsFeatureEnabled(['infrastructure:read_replicas'])
const { data } = useReadReplicasQuery({ projectRef })
const databases = (data ?? [])
.slice()
.sort((a, b) => (a.inserted_at > b.inserted_at ? 1 : 0))
.sort((database) => (database.identifier === projectRef ? -1 : 0))
const selectedDatabaseId = identifier ?? projectRef
const selectedDatabase = databases.find((db) => db.identifier === selectedDatabaseId)
const newReplicaURL = getAddReadReplicaPath(projectRef)
return (
<DropdownMenuSub>
<DropdownMenuSubTrigger>
<div className="flex flex-col">
<span>Database</span>
<span className="text-foreground-lighter text-xs">
{selectedDatabase
? databaseLabel(selectedDatabase.identifier, selectedDatabase.region, projectRef)
: 'Primary database'}
</span>
</div>
</DropdownMenuSubTrigger>
<DropdownMenuSubContent className="w-64">
{databases.map((database) => {
const isUnhealthy = database.status !== 'ACTIVE_HEALTHY'
return (
<DropdownMenuItem
key={database.identifier}
className="justify-between"
disabled={isUnhealthy}
onClick={() => onIdentifierChange(database.identifier)}
>
<span>{databaseLabel(database.identifier, database.region, projectRef)}</span>
{database.identifier === selectedDatabaseId && <CheckIcon size={14} />}
</DropdownMenuItem>
)
})}
{IS_PLATFORM && infrastructureReadReplicas && !isHighAvailability && (
<>
<DropdownMenuSeparator />
<DropdownMenuItem asChild className="gap-x-2">
<Link href={newReplicaURL}>
<PlusIcon size={14} strokeWidth={1.5} />
Create a new read replica
</Link>
</DropdownMenuItem>
</>
)}
</DropdownMenuSubContent>
</DropdownMenuSub>
)
}