fix(studio): use neutral fallbacks for pending destination marks (#51003)

## Problem

Some Pipelines destinations should not display third-party brand marks
until their use is confirmed.

## Solution

Render neutral text monograms for destinations with pending brand marks.
Keep approved destination marks unchanged and preserve the existing
assets so they can be restored with a small configuration change.

| After |
| --- |
| <img width="1022" height="936" alt="CleanShot 2026-09-29 at 11 44
37@2x"
src="https://github.com/user-attachments/assets/d94fca61-aa02-4efb-aa78-47ada5d149d3"
/> |

## Review instructions

1. Open `/project/<ref>/database/replication`.
2. Open the destination picker and confirm destinations with pending
marks use neutral two-letter monograms.
3. Confirm the other destination marks are unchanged.

## Checklist

- [x] I have read
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)

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

* **Style**
* ClickHouse and Snowflake destinations now display “CH” and “SF”
monograms instead of image marks. BigQuery and DuckLake continue to
display their image marks, while destinations without configured
branding continue to show their destination icons. These logo treatments
make the configured destination branding visible in the replication
destination interface.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Danny White authored and GitHub committed 2026-09-30 09:13:06 +10:00
1 parent d451bdc264
commit 3b1867f314
1 file changed
+23 -11
@@ -4,13 +4,13 @@ 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`,
ClickHouse: `${BASE_PATH}/img/icons/clickhouse-icon.svg`,
DuckLake: `${BASE_PATH}/img/icons/ducklake-icon.svg`,
Snowflake: `${BASE_PATH}/img/icons/snowflake-icon.svg`,
type DestinationBrand = { type: 'mark'; src: string } | { type: 'monogram'; label: string }
const BRAND_BY_TYPE: Partial<Record<DestinationType, DestinationBrand>> = {
BigQuery: { type: 'mark', src: `${BASE_PATH}/img/icons/bigquery-icon.svg` },
ClickHouse: { type: 'monogram', label: 'CH' },
DuckLake: { type: 'mark', src: `${BASE_PATH}/img/icons/ducklake-icon.svg` },
Snowflake: { type: 'monogram', label: 'SF' },
}
const SIZE_CLASS_NAME = {
@@ -37,15 +37,27 @@ export const DestinationLogo = ({
hasErrors = false,
}: DestinationLogoProps) => {
const sizing = SIZE_CLASS_NAME[size]
const brandMark = BRAND_MARK_BY_TYPE[type]
const brand = BRAND_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 ? (
{brand === undefined && (
<DestinationIcon type={type} size={sizing.icon} className="text-foreground-light" />
) : (
<img src={brandMark} alt="" aria-hidden className={sizing.mark} />
)}
{brand?.type === 'mark' && (
<img src={brand.src} alt="" aria-hidden className={sizing.mark} />
)}
{brand?.type === 'monogram' && (
<span
className={cn(
'font-mono font-medium leading-none text-foreground-muted',
size === 'small' ? 'text-xs' : 'text-lg'
)}
aria-hidden
>
{brand.label}
</span>
)}
</span>
{hasErrors && (