mirror of
https://github.com/supabase/supabase.git
synced 2026-10-07 02:15:05 +03:00
give replication destinations a brand mark
This commit is contained in:
1 parent
26585dd4a4
commit
6ffa37190b
6 files changed
+74
-22
No files matched your search
@@ -0,0 +1,58 @@
|
||||
import { cn, StatusIcon } from 'ui'
|
||||
|
||||
import { DestinationIcon } from './DestinationIcon'
|
||||
import type { DestinationType } from './DestinationPanel/DestinationPanel.types'
|
||||
import { BASE_PATH } from '@/lib/constants'
|
||||
|
||||
// Destinations with a brand mark. Anything absent falls back to the line icon in the same frame,
|
||||
// so a new destination type never renders an empty square.
|
||||
const BRAND_MARK_BY_TYPE: Partial<Record<DestinationType, string>> = {
|
||||
BigQuery: `${BASE_PATH}/img/icons/bigquery-icon.svg`,
|
||||
}
|
||||
|
||||
const SIZE_CLASS_NAME = {
|
||||
small: { frame: 'h-8 w-8 rounded-md', mark: 'h-4 w-4', icon: 16 },
|
||||
large: { frame: 'h-14 w-14 rounded-lg', mark: 'h-6 w-6', icon: 24 },
|
||||
} as const
|
||||
|
||||
interface DestinationLogoProps {
|
||||
type: DestinationType
|
||||
size?: keyof typeof SIZE_CLASS_NAME
|
||||
className?: string
|
||||
/** Destructive badge on the bottom-right corner (e.g. table replication errors). */
|
||||
hasErrors?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* A destination's brand mark in a square app-icon frame, used wherever a destination is the
|
||||
* subject: the list rows, the pipeline header, and the replication diagram.
|
||||
*/
|
||||
export const DestinationLogo = ({
|
||||
type,
|
||||
size = 'small',
|
||||
className,
|
||||
hasErrors = false,
|
||||
}: DestinationLogoProps) => {
|
||||
const sizing = SIZE_CLASS_NAME[size]
|
||||
const brandMark = BRAND_MARK_BY_TYPE[type]
|
||||
|
||||
return (
|
||||
<span className={cn('relative inline-flex shrink-0', className)}>
|
||||
<span className={cn('flex items-center justify-center border bg-surface-100', sizing.frame)}>
|
||||
{brandMark === undefined ? (
|
||||
<DestinationIcon type={type} size={sizing.icon} className="text-foreground-light" />
|
||||
) : (
|
||||
<img src={brandMark} alt="" aria-hidden className={sizing.mark} />
|
||||
)}
|
||||
</span>
|
||||
{hasErrors && (
|
||||
<span
|
||||
className="absolute -bottom-1 -right-1 rounded-sm bg-background outline outline-2 outline-background"
|
||||
aria-hidden
|
||||
>
|
||||
<StatusIcon variant="destructive" />
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
+3
-11
@@ -10,7 +10,7 @@ import {
|
||||
} from 'ui'
|
||||
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
|
||||
|
||||
import { DestinationIcon } from '../DestinationIcon'
|
||||
import { DestinationLogo } from '../DestinationLogo'
|
||||
import { useDestinationInformation } from '../useDestinationInformation'
|
||||
import {
|
||||
useIsETLBigQueryPrivateAlpha,
|
||||
@@ -163,11 +163,7 @@ export const DestinationTypeSelection = () => {
|
||||
<SelectTrigger className="h-auto py-2">
|
||||
{selectedOption ? (
|
||||
<div className="flex items-center gap-x-3 text-left">
|
||||
<DestinationIcon
|
||||
type={selectedOption.value}
|
||||
size={20}
|
||||
className="shrink-0 text-foreground-light"
|
||||
/>
|
||||
<DestinationLogo type={selectedOption.value} />
|
||||
<span className="text-sm text-foreground">{selectedOption.label}</span>
|
||||
</div>
|
||||
) : (
|
||||
@@ -182,11 +178,7 @@ export const DestinationTypeSelection = () => {
|
||||
{group.options.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value} className="py-2">
|
||||
<div className="flex items-center gap-x-3">
|
||||
<DestinationIcon
|
||||
type={option.value}
|
||||
size={20}
|
||||
className="shrink-0 text-foreground-light"
|
||||
/>
|
||||
<DestinationLogo type={option.value} />
|
||||
<div className="flex flex-col gap-y-0.5">
|
||||
<span className="text-foreground">{option.label}</span>
|
||||
<span className="text-xs text-foreground-lighter">
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
import { ShimmeringLoader } from 'ui-patterns/ShimmeringLoader'
|
||||
|
||||
import { DeleteDestination } from './DeleteDestination'
|
||||
import { DestinationIcon } from './DestinationIcon'
|
||||
import { DestinationLogo } from './DestinationLogo'
|
||||
import { PipelineStatus } from './PipelineStatus'
|
||||
import { PipelineStatusName, STATUS_REFRESH_FREQUENCY_MS } from './Replication.constants'
|
||||
import { getFormattedLagValue } from './ReplicationPipelineStatus/ReplicationPipelineStatus.utils'
|
||||
@@ -149,11 +149,7 @@ export const DestinationRow = ({ destinationId }: DestinationRowProps) => {
|
||||
)}
|
||||
{isPipelineSuccess && (
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
{type ? (
|
||||
<DestinationIcon type={type} size={18} className="text-foreground-light" />
|
||||
) : null}
|
||||
</TableCell>
|
||||
<TableCell>{type ? <DestinationLogo type={type} /> : null}</TableCell>
|
||||
|
||||
<TableCell className="max-w-[180px]">
|
||||
{isPipelineLoading ? (
|
||||
|
||||
@@ -277,7 +277,7 @@ export const Destinations = () => {
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead key="type" className="w-[20px]" />
|
||||
<TableHead key="type" className="w-[40px]" />
|
||||
<TableHead key="name" className="w-[250px]">
|
||||
Name
|
||||
</TableHead>
|
||||
|
||||
@@ -4,7 +4,7 @@ import { PropsWithChildren } from 'react'
|
||||
import { AWS_REGIONS } from 'shared-data'
|
||||
import { cn, Tooltip, TooltipContent, TooltipTrigger } from 'ui'
|
||||
|
||||
import { DestinationIcon } from '../DestinationIcon'
|
||||
import { DestinationLogo } from '../DestinationLogo'
|
||||
import { getStatusName } from '../Pipeline.utils'
|
||||
import { STATUS_REFRESH_FREQUENCY_MS } from '../Replication.constants'
|
||||
import { getReplicationDestinationType } from './Nodes.utils'
|
||||
@@ -75,8 +75,7 @@ export const ReplicationNode = ({ id }: { id: string }) => {
|
||||
const type = getReplicationDestinationType(destination?.config)
|
||||
|
||||
return (
|
||||
<NodeContainer className="justify-start gap-x-3">
|
||||
{type ? <DestinationIcon type={type} size={20} className="text-foreground-light" /> : null}
|
||||
<NodeContainer>
|
||||
<div className="text-sm flex flex-col gap-y-0.5">
|
||||
<div className="flex items-center">
|
||||
<p>{type}</p>
|
||||
@@ -101,6 +100,7 @@ export const ReplicationNode = ({ id }: { id: string }) => {
|
||||
<p className="text-foreground-light">{destination?.name}</p>
|
||||
<p className="text-foreground-light">ID: {destination?.id}</p>
|
||||
</div>
|
||||
{type ? <DestinationLogo type={type} /> : null}
|
||||
<Handle type="target" position={Position.Left} className="opacity-25" />
|
||||
</NodeContainer>
|
||||
)
|
||||
|
||||
@@ -1 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64"><path fill="#4386fa" d="M14.48 58.196.558 34.082a4.163 4.163 0 0 1 0-4.164L14.48 5.805a4.163 4.163 0 0 1 3.6-2.082h27.857c1.48.007 2.845.8 3.585 2.082l13.92 24.113a4.163 4.163 0 0 1 0 4.164L49.52 58.196a4.163 4.163 0 0 1-3.6 2.082H18.07a4.167 4.167 0 0 1-3.593-2.082z"/><path d="M40.697 24.235s3.87 9.283-1.406 14.545-14.883 1.894-14.883 1.894L43.95 60.27h1.984a4.163 4.163 0 0 0 3.6-2.082L58.75 42.23z" opacity=".1"/><path fill="#fff" d="M45.267 43.23 41 38.953a.67.67 0 0 0-.158-.12 11.63 11.63 0 1 0-2.032 2.037.67.67 0 0 0 .113.15l4.277 4.277a.67.67 0 0 0 .947 0l1.12-1.12a.67.67 0 0 0 0-.947zM31.64 40.464a8.75 8.75 0 1 1 8.749-8.749 8.75 8.75 0 0 1-8.749 8.749zm-5.593-9.216v3.616a6.426 6.426 0 0 0 2.338 2.375v-6.013zm4.375-2.998v9.772a6.45 6.45 0 0 0 2.338 0V28.25zm6.764 6.606v-2.142H34.85v4.5a6.43 6.43 0 0 0 2.338-2.368z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
<path fill="#34a853" d="M311.9 418.9c-8.8 0-16-7.2-16-16V257.1c0-8.8 7.2-16 16-16s16 7.2 16 16v145.8c0 8.8-7.2 16-16 16ZM147.6 418.9c-8.8 0-16-7.2-16-16V202.4c0-8.8 7.2-16 16-16s16 7.2 16 16v200.5c0 8.8-7.2 16-16 16Z"/>
|
||||
<path fill="#34a853" d="M229.8 437.4c-8.8 0-16-7.2-16-16V147.6c0-8.8 7.2-16 16-16s16 7.2 16 16v273.7c0 8.8-7.2 16-16 16Z"/>
|
||||
<path fill="#fbbc04" d="M229.8 437.4c-114.5 0-207.6-93.1-207.6-207.6h32c0 96.8 78.8 175.6 175.6 175.6s175.6-78.8 175.6-175.6h32c0 114.5-93.1 207.6-207.6 207.6Z"/>
|
||||
<path fill="#ea4335" d="M437.4 229.8h-32c0-96.8-78.8-175.6-175.6-175.6S54.1 132.9 54.1 229.8h-32c0-114.5 93.2-207.7 207.7-207.7s207.6 93.1 207.6 207.6Z"/>
|
||||
<path fill="#4285f4" d="m487.4 464.8-100-100c32.3-37.6 49.9-85 49.9-135.1s-21.6-107.6-60.8-146.8l-22.6 22.6c33.2 33.2 51.4 77.3 51.4 124.2s-18.3 90.9-51.5 124.1c-5 5-7.5 7-11.8 10.8l122.8 122.8c3.1 3.1 7.2 4.7 11.3 4.7s8.2-1.6 11.3-4.7c6.2-6.2 6.2-16.4 0-22.6Z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 903 B After Width: | Height: | Size: 1006 B |
Reference in new issue
Block a user