From b7a5f22abd98134a4332da16626c3695b892fced Mon Sep 17 00:00:00 2001 From: Waleed Date: Fri, 14 Aug 2026 14:40:20 -0700 Subject: [PATCH] fix(integrations): read every service mark from one registry (#6682) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(integrations): read every service mark from one registry A service looked like itself on the canvas and like nothing in particular everywhere it was connected. `OAUTH_PROVIDERS` registers 93 icons and no colour at all, so the surfaces built on it — the connect dialog above all — drew a flat grey mark for a block whose config already carries its brand icon and `bgColor`. Bridges the two: `resolveIntegrationBlockTypeForOAuth` maps any OAuth id (a service id, a provider id, an extra authorization server) to the catalog block behind it, so a credential surface holding only an OAuth identity can still reach the registry. The connect dialog now wears the block's tile, and `ChipModalHeader` takes a rendered mark so a tile can carry its own chrome instead of being tinted with the header's grey. Folds in the copies that had grown around the gap: `IntegrationTile` resolved its fill from the registry but took its icon from whatever the caller passed — one tile, two sources — and now defaults to the registry, with an override kept for the family service-account marks that genuinely are not the block's. The letter fallback it grew alongside was reading the catalog's `bgColor` while the tile beside it read the registry's; both are the tile now. Two `getProviderIcon` implementations for the same job (one tinted, one not) become one `ProviderIcon`, the connector tile duplicated verbatim across two knowledge-base surfaces becomes one `ConnectorTile`, and the permission rows that hardcoded `text-white` — which renders white-on-white on a pale brand tile — go through `BlockTile`. Public pages keep their generated catalog: importing the registry there would ship 282 block configs to a marketing page, and `integrations.json` is generated from the same `bgColor`, so the two cannot drift. * fix(blocks): drop the dead copies of a block's colour Sweeping the surfaces above turned up colour data nothing reads and colour data two surfaces disagreed on. Dead: `BLOCK_COLORS.DEFAULT/LOOP/PARALLEL` in the tag dropdown (only `VARIABLE` was ever referenced), `BlockIconInfo.color` on table columns — whose consumer documents that it deliberately ignores the colour, so the `#2F55FF` behind it could never render — and the `bgColor` threaded into the add-resource dropdown, whose row renders a bare tinted icon. Disagreeing: the Variables tile is `#2F8BFF` in the tag dropdown and `#8B5CF6` in the preview panel, for the same "V" on the same concept. Both now read `VARIABLE_TILE_COLOR`, and the preview panel's two hand-rolled squares become `BlockTile` like every other tile. Four spellings of the neutral fallback (`#6B7280`, `#6b7280`, `#666666`, and a `cancelled` status that happened to equal it) now point at `DEFAULT_BLOCK_TILE_COLOR`. The terminal and logs resolvers stay. They look like duplicates of `accent.ts` but carry behaviour it does not have — status fills for synthesized error/validation/cancelled rows, near-black contrast correction, MCP tool-id parsing, and a model-provider branch — so folding them in is a behavioural change, not a deletion. * chore(copilot): delete the mention machinery nothing calls The workflow panel's copilot tab renders `MothershipChat`, and that component brings its own input — so `panel/components/copilot` no longer holds a component at all, only the hook library the old input used. Five of those hooks have no caller anywhere: `useMentionData`, `useMentionKeyboard`, `useCaretViewport`, `useMentionInsertHandlers`, `useTextareaAutoResize`. They are not all of it. `home/components/user-input` still imports `useFileAttachments`, `useMentionMenu`, `useMentionTokens`, `useContextManagement`, and `useIntegrationAutoMention` from this directory, so it survives as a shared hook library rather than dead weight — which is why this removes the uncalled five rather than the folder. What they alone reached goes with them: `getFolderData` / `getFolderLoading` / `getFolderEnsureLoaded` and the `FOLDER_CONFIGS` table describing every mention folder, `buildMentionHighlightNodes`, the `MentionFolderNav` type, and the slash-command tables. Of the 266-line constants file only `SCROLL_TOLERANCE` had a live reader left. * fix(integrations): never answer with a sibling's tile Two integrations can share one OAuth id: Google Slides is authenticated by Drive's `google-drive` service and Jira Service Management by Jira's `jira`. Indexing first-write-wins made those ids resolve to whichever sorted first, so the dialog connecting Slides could wear Drive's brand. An id claimed by more than one block type now resolves to neither, and the caller keeps the service-specific mark it already had. A wrong brand is worse than no tile. --- .../connect-oauth-modal.tsx | 18 +- .../components/provider-icon/index.ts | 1 + .../provider-icon/provider-icon.tsx | 35 ++ .../add-resource-dropdown.tsx | 1 - .../suggested-actions/suggested-actions.tsx | 40 +- .../[block]/integration-block-detail.tsx | 26 +- .../integrations-showcase.tsx | 31 +- .../connected-credential-detail.tsx | 19 +- .../integrations/integrations.tsx | 10 +- .../add-connector-modal.tsx | 24 +- .../connector-tile/connector-tile.tsx | 44 +++ .../[id]/components/connector-tile/index.ts | 1 + .../connectors-section/connectors-section.tsx | 23 +- .../logs/components/log-details/utils.ts | 11 +- .../[tableId]/components/table-grid/types.ts | 6 +- .../tables/[tableId]/hooks/use-table.ts | 2 +- .../components/user-input/constants.ts | 262 ------------- .../components/user-input/hooks/index.ts | 5 - .../user-input/hooks/use-caret-viewport.ts | 77 ---- .../user-input/hooks/use-mention-data.ts | 365 ------------------ .../hooks/use-mention-insert-handlers.ts | 137 ------- .../user-input/hooks/use-mention-keyboard.ts | 355 ----------------- .../hooks/use-textarea-auto-resize.ts | 232 ----------- .../copilot/components/user-input/types.ts | 11 - .../copilot/components/user-input/utils.ts | 79 ---- .../credential-selector.tsx | 16 +- .../components/tag-dropdown/tag-dropdown.tsx | 13 +- .../components/tools/credential-selector.tsx | 16 +- .../panel/components/toolbar/toolbar.tsx | 3 +- .../[workflowId]/components/terminal/utils.ts | 5 +- .../preview-editor/preview-editor.tsx | 9 +- apps/sim/blocks/accent.ts | 7 + .../components/group-detail.tsx | 19 +- apps/sim/lib/integrations/index.ts | 1 + .../lib/integrations/oauth-service.test.ts | 94 +++++ apps/sim/lib/integrations/oauth-service.ts | 66 ++++ .../src/components/chip-modal/chip-modal.tsx | 16 +- 37 files changed, 388 insertions(+), 1692 deletions(-) create mode 100644 apps/sim/app/workspace/[workspaceId]/components/provider-icon/index.ts create mode 100644 apps/sim/app/workspace/[workspaceId]/components/provider-icon/provider-icon.tsx create mode 100644 apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/connector-tile/connector-tile.tsx create mode 100644 apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/connector-tile/index.ts delete mode 100644 apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/hooks/use-caret-viewport.ts delete mode 100644 apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/hooks/use-mention-data.ts delete mode 100644 apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/hooks/use-mention-insert-handlers.ts delete mode 100644 apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/hooks/use-mention-keyboard.ts delete mode 100644 apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/hooks/use-textarea-auto-resize.ts delete mode 100644 apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/types.ts diff --git a/apps/sim/app/workspace/[workspaceId]/components/connect-oauth-modal/connect-oauth-modal.tsx b/apps/sim/app/workspace/[workspaceId]/components/connect-oauth-modal/connect-oauth-modal.tsx index a5bd8cdf51..96b2c2f8e3 100644 --- a/apps/sim/app/workspace/[workspaceId]/components/connect-oauth-modal/connect-oauth-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/components/connect-oauth-modal/connect-oauth-modal.tsx @@ -19,6 +19,7 @@ import { useSession } from '@/lib/auth/auth-client' import type { OAuthReturnContext } from '@/lib/credentials/client-state' import { ADD_CONNECTOR_SEARCH_PARAM, writeOAuthReturnContext } from '@/lib/credentials/client-state' import { defaultCredentialDisplayName } from '@/lib/credentials/display-name' +import { resolveIntegrationBlockTypeForOAuth } from '@/lib/integrations' import { getProviderIdFromServiceId, OAUTH_PROVIDERS, @@ -26,6 +27,7 @@ import { parseProvider, } from '@/lib/oauth' import { getScopeDescription, getServiceConfigByProviderId } from '@/lib/oauth/utils' +import { BlockTile } from '@/blocks/block-tile' import { useCreateCredentialDraft, useWorkspaceCredentials } from '@/hooks/queries/credentials' import { useConnectOAuthService } from '@/hooks/queries/oauth/oauth-connections' @@ -173,6 +175,20 @@ export function ConnectOAuthModal(props: ConnectOAuthModalProps) { return resolveService(provider, props.serviceId ?? providerId) }, [props.serviceName, props.serviceIcon, props.provider, props.serviceId, providerId]) + /** + * The block behind this OAuth identity, so the dialog wears the same brand + * tile the canvas and the integrations catalog do. Falls back to the bare + * `OAUTH_PROVIDERS` mark for an id no catalog integration claims. + */ + const headerIcon = useMemo(() => { + const blockType = resolveIntegrationBlockTypeForOAuth( + props.serviceId, + props.provider, + providerId + ) + return blockType ? : ProviderIcon + }, [props.serviceId, props.provider, providerId, ProviderIcon]) + const workspaceId = isConnect ? props.workspaceId : '' const { data: credentials = [], isPending: credentialsLoading } = useWorkspaceCredentials({ workspaceId, @@ -343,7 +359,7 @@ export function ConnectOAuthModal(props: ConnectOAuthModalProps) { return ( - + {title} diff --git a/apps/sim/app/workspace/[workspaceId]/components/provider-icon/index.ts b/apps/sim/app/workspace/[workspaceId]/components/provider-icon/index.ts new file mode 100644 index 0000000000..f3206a4131 --- /dev/null +++ b/apps/sim/app/workspace/[workspaceId]/components/provider-icon/index.ts @@ -0,0 +1 @@ +export { ProviderIcon } from './provider-icon' diff --git a/apps/sim/app/workspace/[workspaceId]/components/provider-icon/provider-icon.tsx b/apps/sim/app/workspace/[workspaceId]/components/provider-icon/provider-icon.tsx new file mode 100644 index 0000000000..dd5f3bbdd5 --- /dev/null +++ b/apps/sim/app/workspace/[workspaceId]/components/provider-icon/provider-icon.tsx @@ -0,0 +1,35 @@ +'use client' + +import { cn } from '@sim/emcn' +import { SquareArrowUpRight } from '@sim/emcn/icons' +import { OAUTH_PROVIDERS, type OAuthProvider, parseProvider } from '@/lib/oauth' +import { getBareIconStyle, type StyleableIcon } from '@/blocks/brand-icon-style' + +interface ProviderIconProps { + provider: OAuthProvider + className?: string +} + +/** + * The mark for an OAuth provider, tinted with the brand colour its block + * config registers. Credential rows show a bare icon rather than the filled + * tile the canvas uses, so the colour has to come through `iconColor` — but it + * still comes from the same registry, which is what keeps a provider looking + * like itself everywhere it is listed. + * + * `OAUTH_PROVIDERS` carries the icon and no colour at all, so rendering + * straight from it is what left credential surfaces grey while the same + * service was branded a panel away. Falls back to a generic mark for a + * provider that map does not know. + */ +export function ProviderIcon({ provider, className }: ProviderIconProps) { + const { baseProvider } = parseProvider(provider) + const config = OAUTH_PROVIDERS[baseProvider] + + if (!config) return + + const Icon = config.icon as StyleableIcon + return ( + + ) +} diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/components/add-resource-dropdown/add-resource-dropdown.tsx b/apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/components/add-resource-dropdown/add-resource-dropdown.tsx index 6f8653d161..8dd8d3aad3 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/components/add-resource-dropdown/add-resource-dropdown.tsx +++ b/apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/components/add-resource-dropdown/add-resource-dropdown.tsx @@ -258,7 +258,6 @@ export function useAvailableResources( id: integration.blockType, name: integration.name, iconComponent: integration.icon, - bgColor: integration.bgColor, })), }, { diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/suggested-actions/suggested-actions.tsx b/apps/sim/app/workspace/[workspaceId]/home/components/suggested-actions/suggested-actions.tsx index 8641b9b5ea..49f0be5e84 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/components/suggested-actions/suggested-actions.tsx +++ b/apps/sim/app/workspace/[workspaceId]/home/components/suggested-actions/suggested-actions.tsx @@ -7,7 +7,6 @@ import { randomFloat } from '@sim/utils/random' import { stripVersionSuffix } from '@sim/utils/string' import { useParams } from 'next/navigation' import { usePostHog } from 'posthog-js/react' -import { GmailIcon, SlackIcon } from '@/components/icons' import { INTEGRATIONS, type OAuthServiceMatch, @@ -16,6 +15,7 @@ import { } from '@/lib/integrations' import { captureEvent } from '@/lib/posthog/client' import { ConnectOAuthModal } from '@/app/workspace/[workspaceId]/components/connect-oauth-modal' +import { getBlockTileIcon } from '@/blocks/accent' import { getBareIconStyle } from '@/blocks/brand-icon-style' import { getAllBlockMeta } from '@/blocks/registry' import type { ModuleTag } from '@/blocks/types' @@ -224,6 +224,16 @@ function computeActions(services: readonly ServiceInfo[], signals: Signals): Act return [...integrations, ...prompts] } +/** + * Integrations pinned to the first paint. Named by block type so the mark comes + * from the same registry every other surface reads, rather than a second copy + * imported here that could drift from the block's own icon. + */ +const INITIAL_INTEGRATIONS = [ + { blockType: 'slack', slug: 'slack', name: 'Slack' }, + { blockType: 'gmail', slug: 'gmail', name: 'Gmail' }, +] as const + /** * Initial actions rendered on first paint, before OAuth/credentials queries * resolve. For users with no connections this is also the final result, so the @@ -231,20 +241,20 @@ function computeActions(services: readonly ServiceInfo[], signals: Signals): Act * before the personalized recompute replaces it. */ const INITIAL_ACTIONS: Action[] = [ - { - kind: 'integration', - id: 'integrate-slack', - label: 'Integrate with Slack', - icon: SlackIcon, - slug: 'slack', - }, - { - kind: 'integration', - id: 'integrate-gmail', - label: 'Integrate with Gmail', - icon: GmailIcon, - slug: 'gmail', - }, + ...INITIAL_INTEGRATIONS.flatMap(({ blockType, slug, name }) => { + const icon = getBlockTileIcon(blockType) + return icon + ? [ + { + kind: 'integration', + id: `integrate-${slug}`, + label: `Integrate with ${name}`, + icon, + slug, + }, + ] + : [] + }), toPromptAction(TABLE_STARTERS[0]), ...CANDIDATES.filter((c) => c.blockType === 'github' && c.featured) .slice(0, 1) diff --git a/apps/sim/app/workspace/[workspaceId]/integrations/[block]/integration-block-detail.tsx b/apps/sim/app/workspace/[workspaceId]/integrations/[block]/integration-block-detail.tsx index f8fbafb5e4..2a2cbf9dd2 100644 --- a/apps/sim/app/workspace/[workspaceId]/integrations/[block]/integration-block-detail.tsx +++ b/apps/sim/app/workspace/[workspaceId]/integrations/[block]/integration-block-detail.tsx @@ -8,14 +8,12 @@ import { useQueryState } from 'nuqs' import { HEADER_ACTION_CLUSTER, PAGE_HEADER_BAR } from '@/components/page-header-bar' import { isChatEnabled } from '@/lib/core/config/env-flags' import { - blockTypeToIconMap, type Integration, resolveCredentialDisplay, resolveOAuthServiceForIntegration, } from '@/lib/integrations' import { credentialProviderMatchesService } from '@/lib/oauth' import { ConnectOAuthModal } from '@/app/workspace/[workspaceId]/components/connect-oauth-modal' -import { RESOURCE_TILE_BASE } from '@/app/workspace/[workspaceId]/components/resource-tile' import { IntegrationSkillsSection } from '@/app/workspace/[workspaceId]/integrations/[block]/integration-skills-section' import { connectParam } from '@/app/workspace/[workspaceId]/integrations/[block]/search-params' import { @@ -34,7 +32,7 @@ import { SettingsResourceRow, } from '@/app/workspace/[workspaceId]/settings/components/settings-resource-row' import { SettingsSection } from '@/app/workspace/[workspaceId]/settings/components/settings-section/settings-section' -import { getTileIconColorClass } from '@/blocks/icon-color' +import { getBlockTileIcon } from '@/blocks/accent' import { storeCuratedPrompt } from '@/blocks/integration-matcher' import { getSuggestedSkillsForBlock, @@ -64,7 +62,6 @@ export function IntegrationBlockDetail({ integration, workspaceId }: Integration useOAuthReturnRouter() const router = useRouter() const [connectMode, setConnectMode] = useQueryState(connectParam.key, connectParam.parser) - const Icon = blockTypeToIconMap[integration.type] const matchingTemplates = getTemplatesForBlock(integration.type) const suggestedSkills = getSuggestedSkillsForBlock(integration.type) const oauthService = resolveOAuthServiceForIntegration(integration) @@ -233,16 +230,10 @@ export function IntegrationBlockDetail({ integration, workspaceId }: Integration >
- {Icon ? ( - - ) : ( -
- {integration.name.charAt(0)} -
- )} +

{integration.name}

{integration.description}

@@ -255,7 +246,7 @@ export function IntegrationBlockDetail({ integration, workspaceId }: Integration } + icon={} title={credential.displayName} description={ credential.description || resolveCredentialDisplay(credential).subtitle @@ -374,8 +365,7 @@ function TemplateIcons({ blockTypes }: TemplateIconsProps) { return ( {blockTypes.map((bt, idx) => { - const ToolIcon = blockTypeToIconMap[bt] - if (!ToolIcon) return null + if (!getBlockTileIcon(bt)) return null const z = TEMPLATE_TILE_Z[idx] if (!z) return null const isTrailing = idx > 0 @@ -389,7 +379,7 @@ function TemplateIcons({ blockTypes }: TemplateIconsProps) { 'outline outline-2 outline-[var(--bg)] transition-[outline-color] duration-150 group-hover:outline-[var(--surface-active)]' )} > - + ) })} diff --git a/apps/sim/app/workspace/[workspaceId]/integrations/components/integrations-showcase/integrations-showcase.tsx b/apps/sim/app/workspace/[workspaceId]/integrations/components/integrations-showcase/integrations-showcase.tsx index 43a25c08ba..e4b29e3245 100644 --- a/apps/sim/app/workspace/[workspaceId]/integrations/components/integrations-showcase/integrations-showcase.tsx +++ b/apps/sim/app/workspace/[workspaceId]/integrations/components/integrations-showcase/integrations-showcase.tsx @@ -5,6 +5,7 @@ import { RESOURCE_TILE_PLAIN, } from '@/app/workspace/[workspaceId]/components/resource-tile' import { getBlock } from '@/blocks' +import { getBlockTileIcon } from '@/blocks/accent' import { getTileIconColorClass } from '@/blocks/icon-color' /** @@ -59,7 +60,15 @@ function resolveBrandTileBg(blockType: string): string | null { interface IntegrationTileProps { blockType: string - icon: ComponentType<{ className?: string }> + /** + * Overrides the block's registered mark. Only for a tile whose identity is + * not the block itself — a credential issued by a family service account + * wears the family's corporate mark. Everything else takes the registry's, + * so the tile cannot end up with its fill and its icon from two sources. + */ + icon?: ComponentType<{ className?: string }> + /** Drawn when neither the override nor the registry supplies a mark. */ + fallbackLabel?: string framed?: boolean } @@ -68,16 +77,23 @@ interface IntegrationTileProps { * is a 36px tile used in list rows and headers; the framed variant adds an * outer 44px halo used inside the showcase grid. */ -export function IntegrationTile({ blockType, icon: Icon, framed = false }: IntegrationTileProps) { +export function IntegrationTile({ + blockType, + icon, + fallbackLabel, + framed = false, +}: IntegrationTileProps) { const brandBg = resolveBrandTileBg(blockType) + const Icon = icon ?? getBlockTileIcon(blockType) + const contentClass = getTileIconColorClass(brandBg) if (!framed) { return (
- + {Icon ? : fallbackLabel}
) } @@ -85,10 +101,13 @@ export function IntegrationTile({ blockType, icon: Icon, framed = false }: Integ return (
- + {Icon ? : fallbackLabel}
) diff --git a/apps/sim/app/workspace/[workspaceId]/integrations/connected/[credentialId]/connected-credential-detail.tsx b/apps/sim/app/workspace/[workspaceId]/integrations/connected/[credentialId]/connected-credential-detail.tsx index 2b1ae99f39..705f6647df 100644 --- a/apps/sim/app/workspace/[workspaceId]/integrations/connected/[credentialId]/connected-credential-detail.tsx +++ b/apps/sim/app/workspace/[workspaceId]/integrations/connected/[credentialId]/connected-credential-detail.tsx @@ -8,7 +8,6 @@ import { ChipInput, ChipLink, ChipTextarea, - cn, Send, toast, } from '@sim/emcn' @@ -28,10 +27,6 @@ import { UnsavedChangesModal, useCredentialDetailForm, } from '@/app/workspace/[workspaceId]/components/credential-detail' -import { - RESOURCE_TILE_BASE, - RESOURCE_TILE_PLAIN, -} from '@/app/workspace/[workspaceId]/components/resource-tile' import { ConnectServiceAccountModal, type ServiceAccountProviderId, @@ -244,15 +239,11 @@ export function ConnectedCredentialDetail({ - ) : ( -
- - {resolveProviderLabel(credential.providerId).slice(0, 1) || '?'} - -
- ) + } title={headingTitle} subtitle={display?.detailSubtitle ?? 'Connected service'} diff --git a/apps/sim/app/workspace/[workspaceId]/integrations/integrations.tsx b/apps/sim/app/workspace/[workspaceId]/integrations/integrations.tsx index 9f166f59e8..3f26e43d39 100644 --- a/apps/sim/app/workspace/[workspaceId]/integrations/integrations.tsx +++ b/apps/sim/app/workspace/[workspaceId]/integrations/integrations.tsx @@ -14,7 +14,6 @@ import { import { useParams } from 'next/navigation' import { useQueryStates } from 'nuqs' import { - blockTypeToIconMap, formatIntegrationType, INTEGRATIONS, type Integration, @@ -34,6 +33,7 @@ import { } from '@/app/workspace/[workspaceId]/integrations/search-params' import { SettingsEmptyState } from '@/app/workspace/[workspaceId]/settings/components/settings-empty-state' import { SettingsResourceRow } from '@/app/workspace/[workspaceId]/settings/components/settings-resource-row' +import { getBlockTileIcon } from '@/blocks/accent' import { useWorkspaceCredentials, type WorkspaceCredential } from '@/hooks/queries/credentials' import { useDebouncedSearchSetter } from '@/hooks/use-debounced-search-setter' import { usePermissionConfig } from '@/hooks/use-permission-config' @@ -68,7 +68,6 @@ interface IntegrationItemProps { workspaceId: string name: string description?: string | null - icon: ComponentType<{ className?: string }> unavailable?: boolean } @@ -78,13 +77,12 @@ function IntegrationItem({ workspaceId, name, description, - icon: Icon, unavailable = false, }: IntegrationItemProps) { return ( } + icon={} title={name} description={ unavailable @@ -348,8 +346,7 @@ export function Integrations() { {filteredCategorySections.map((section) => ( {section.integrations.map((integration) => { - const Icon = blockTypeToIconMap[integration.type] - if (!Icon) return null + if (!getBlockTileIcon(integration.type)) return null const availability = integrationAvailability.get(integration.type.toLowerCase()) const deploymentUnavailable = availability?.state === 'unavailable' || availability?.state === 'misconfigured' @@ -361,7 +358,6 @@ export function Integrations() { workspaceId={workspaceId} name={integration.name} description={integration.description} - icon={Icon} unavailable={integration.authType === 'oauth' && deploymentUnavailable} /> ) diff --git a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/add-connector-modal/add-connector-modal.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/add-connector-modal/add-connector-modal.tsx index a547065ff1..38b6ca8ab2 100644 --- a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/add-connector-modal/add-connector-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/add-connector-modal/add-connector-modal.tsx @@ -16,7 +16,6 @@ import { ChipModalFooter, ChipModalHeader, type ComboboxOption, - cn, handleKeyboardActivation, Search, } from '@sim/emcn' @@ -31,12 +30,11 @@ import { import { ConnectOAuthModal } from '@/app/workspace/[workspaceId]/components/connect-oauth-modal' import { ConnectorConfigFields } from '@/app/workspace/[workspaceId]/knowledge/[id]/components/connector-config-fields' import { hasWorkspaceMaxConnectorAccess } from '@/app/workspace/[workspaceId]/knowledge/[id]/components/connector-entitlements' +import { ConnectorTile } from '@/app/workspace/[workspaceId]/knowledge/[id]/components/connector-tile' import { SYNC_INTERVALS } from '@/app/workspace/[workspaceId]/knowledge/[id]/components/consts' import { MaxBadge } from '@/app/workspace/[workspaceId]/knowledge/[id]/components/max-badge' import { useConnectorConfigFields } from '@/app/workspace/[workspaceId]/knowledge/[id]/hooks/use-connector-config-fields' import { useWorkspaceHostContext } from '@/app/workspace/[workspaceId]/providers/workspace-host-provider' -import { getBlock } from '@/blocks' -import { getTileIconColorClass } from '@/blocks/icon-color' import { CONNECTOR_META_REGISTRY } from '@/connectors/registry' import type { ConnectorMeta } from '@/connectors/types' import { useCreateConnector } from '@/hooks/queries/kb/connectors' @@ -479,9 +477,6 @@ interface ConnectorTypeCardProps { } function ConnectorTypeCard({ type, config, onClick }: ConnectorTypeCardProps) { - const Icon = config.icon - const brandBg = getBlock(type)?.bgColor ?? null - return (