diff --git a/apps/studio/components/interfaces/Database/Replication/DestinationLogo.tsx b/apps/studio/components/interfaces/Database/Replication/DestinationLogo.tsx new file mode 100644 index 00000000000..c58c9e2b42b --- /dev/null +++ b/apps/studio/components/interfaces/Database/Replication/DestinationLogo.tsx @@ -0,0 +1,61 @@ +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> = { + 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`, +} + +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 ( + + + {brandMark === undefined ? ( + + ) : ( + + )} + + {hasErrors && ( + + + + )} + + ) +} diff --git a/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationTypeSelection.tsx b/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationTypeSelection.tsx index 8ce8a4b5167..955e9616356 100644 --- a/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationTypeSelection.tsx +++ b/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationTypeSelection.tsx @@ -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 = () => { {selectedOption ? (
- + {selectedOption.label}
) : ( @@ -182,11 +178,7 @@ export const DestinationTypeSelection = () => { {group.options.map((option) => (
- +
{option.label} diff --git a/apps/studio/components/interfaces/Database/Replication/DestinationRow.tsx b/apps/studio/components/interfaces/Database/Replication/DestinationRow.tsx index a8498f19a8e..8b553a625c5 100644 --- a/apps/studio/components/interfaces/Database/Replication/DestinationRow.tsx +++ b/apps/studio/components/interfaces/Database/Replication/DestinationRow.tsx @@ -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 && ( - - {type ? ( - - ) : null} - + {type ? : null} {isPipelineLoading ? ( diff --git a/apps/studio/components/interfaces/Database/Replication/Destinations.tsx b/apps/studio/components/interfaces/Database/Replication/Destinations.tsx index a37139e5f1e..c2cc0cc96f0 100644 --- a/apps/studio/components/interfaces/Database/Replication/Destinations.tsx +++ b/apps/studio/components/interfaces/Database/Replication/Destinations.tsx @@ -277,7 +277,7 @@ export const Destinations = () => { - + Name diff --git a/apps/studio/components/interfaces/Database/Replication/ReplicationDiagram/Nodes.tsx b/apps/studio/components/interfaces/Database/Replication/ReplicationDiagram/Nodes.tsx index 00a78324baa..df4a4716db0 100644 --- a/apps/studio/components/interfaces/Database/Replication/ReplicationDiagram/Nodes.tsx +++ b/apps/studio/components/interfaces/Database/Replication/ReplicationDiagram/Nodes.tsx @@ -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 ( - - {type ? : null} +

{type}

@@ -101,6 +100,7 @@ export const ReplicationNode = ({ id }: { id: string }) => {

{destination?.name}

ID: {destination?.id}

+ {type ? : null} ) diff --git a/apps/studio/public/img/icons/bigquery-icon.svg b/apps/studio/public/img/icons/bigquery-icon.svg index 6aee1b1f440..16453f63229 100644 --- a/apps/studio/public/img/icons/bigquery-icon.svg +++ b/apps/studio/public/img/icons/bigquery-icon.svg @@ -1 +1,7 @@ - \ No newline at end of file + + + + + + + diff --git a/apps/studio/public/img/icons/clickhouse-icon.svg b/apps/studio/public/img/icons/clickhouse-icon.svg index 5c61225e336..dd9e223dc5d 100644 --- a/apps/studio/public/img/icons/clickhouse-icon.svg +++ b/apps/studio/public/img/icons/clickhouse-icon.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + + diff --git a/apps/studio/public/img/icons/ducklake-icon.svg b/apps/studio/public/img/icons/ducklake-icon.svg new file mode 100644 index 00000000000..c65b8238022 --- /dev/null +++ b/apps/studio/public/img/icons/ducklake-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/apps/studio/public/img/icons/snowflake-icon.svg b/apps/studio/public/img/icons/snowflake-icon.svg index 1a70dd0d29f..86a17fd33d9 100644 --- a/apps/studio/public/img/icons/snowflake-icon.svg +++ b/apps/studio/public/img/icons/snowflake-icon.svg @@ -1 +1,10 @@ - \ No newline at end of file + + + + + + + + + +