Files
supabase/apps/studio/components/interfaces/Database/Replication/DestinationLogo.tsx
T
Danny White 4f0be099e7 fix(studio): restore the Snowflake destination mark (#51075)
## Problem

The Snowflake destination still uses a neutral text monogram even though
its Studio asset is available. Supporting that monogram also leaves a
separate rendering path used by no other destination.

## Solution

Restore Snowflake through the shared brand-icon registry introduced by
#51073. Simplify `DestinationLogo` back to a map of destination marks,
removing the monogram type, configuration, and rendering branch.

| After |
| --- |
| <img width="924" height="730" alt="CleanShot 2026-09-30 at 15 14
59@2x"
src="https://github.com/user-attachments/assets/7409d483-3371-45ec-bf54-0ddc6ad22857"
/> |

## Review instructions

1. Open `/project/<ref>/database/replication` with a Snowflake pipeline.
2. Confirm the Snowflake mark appears in the pipeline list and diagram.
3. Open the pipeline child route and confirm the same mark appears in
its header.
4. Confirm the other destination marks remain unchanged in light and
dark themes.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Visual Updates**
* Snowflake replication destinations now display a themed brand icon
instead of the “SF” monogram. Other destinations retain their existing
icons.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-10-01 18:00:55 +10:00

65 lines
2.2 KiB
TypeScript

import { useTheme } from 'next-themes'
import { cn, StatusIcon } from 'ui'
import { DestinationIcon } from './DestinationIcon'
import type { DestinationType } from './DestinationPanel/DestinationPanel.types'
import { BRAND_ICONS, resolveThemedIconSrc, type ThemedIconSrc } from '@/lib/brand-icons'
import { resolveThemeOverrideMode } from '@/lib/theme-overrides'
const BRAND_MARK_BY_TYPE: Partial<Record<DestinationType, ThemedIconSrc>> = {
BigQuery: BRAND_ICONS.bigquery,
ClickHouse: BRAND_ICONS.clickhouse,
DuckLake: BRAND_ICONS.ducklake,
Snowflake: BRAND_ICONS.snowflake,
}
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-8 w-8', icon: 32 },
} 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 { resolvedTheme } = useTheme()
const isDark = resolveThemeOverrideMode(resolvedTheme) === 'dark'
const sizing = SIZE_CLASS_NAME[size]
const brandMark = BRAND_MARK_BY_TYPE[type]
const brandMarkSrc = brandMark === undefined ? undefined : resolveThemedIconSrc(brandMark, isDark)
return (
<span className={cn('relative inline-flex shrink-0', className)}>
<span className={cn('flex items-center justify-center border bg-surface-100', sizing.frame)}>
{brandMarkSrc === undefined ? (
<DestinationIcon type={type} size={sizing.icon} className="text-foreground-light" />
) : (
<img src={brandMarkSrc} 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>
)
}