Skip to content

Commit f5d74c0

Browse files
committed
fix(blocks): give the detail headers the same tile as everything else
The tile consolidation left the large detail headers on their own treatment, so a block wore one colour on the canvas and another in the header naming it: the preview panel behind the deploy modal and the logs trace detail both painted straight from the catalog `bgColor`, showing Start's catalog blue over a neutral card, and hardcoded `#2FB3FF`/`#FEE12B` for the two subflows. Adds the 18px header slot to `BlockTile` and points all three headers at it — preview panel, trace detail, and the editor header, which had been carrying its own inline copy of the accent rule. `WorkflowTypeIcon` takes an icon class so the accent chip can draw the larger glyph the header uses.
1 parent cc7f005 commit f5d74c0

5 files changed

Lines changed: 53 additions & 84 deletions

File tree

apps/sim/app/workspace/[workspaceId]/logs/components/log-details/components/trace-view/trace-view.tsx

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ import {
4747
} from '@/app/workspace/[workspaceId]/logs/components/log-details/utils'
4848
import { BlockTile } from '@/blocks/block-tile'
4949
import { isCustomBlockType } from '@/blocks/custom/build-config'
50-
import { getTileIconColorClass } from '@/blocks/icon-color'
5150
import { useCodeViewerFeatures } from '@/hooks/use-code-viewer'
5251

5352
const DEFAULT_TREE_PANE_WIDTH = 240
@@ -708,14 +707,13 @@ const TraceDetailPane = memo(function TraceDetailPane({ span }: { span: TraceSpa
708707
<div className='flex min-h-0 flex-1 flex-col gap-3 overflow-y-auto px-3.5 pt-3 pb-4'>
709708
<div className='flex items-start gap-2'>
710709
{!isIterationType(span.type) && (
711-
<div
712-
className='mt-[2px] flex size-[18px] flex-shrink-0 items-center justify-center overflow-hidden rounded-sm [&_img]:size-full'
713-
style={{ background: bgColor }}
714-
>
715-
{BlockIcon && (
716-
<BlockIcon className={cn('size-[12px]', getTileIconColorClass(bgColor))} />
717-
)}
718-
</div>
710+
<BlockTile
711+
blockType={span.type?.toLowerCase() ?? ''}
712+
icon={BlockIcon ?? undefined}
713+
bgColor={bgColor}
714+
size='lg'
715+
className='mt-[2px]'
716+
/>
719717
)}
720718
<div className='flex min-w-0 flex-1 flex-col gap-0.5'>
721719
<h3

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/editor.tsx

Lines changed: 4 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use client'
22

33
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
4-
import { Button, ChipTag, DashedDividerLine, FieldDivider, Loader, Tooltip } from '@sim/emcn'
4+
import { Button, DashedDividerLine, FieldDivider, Loader, Tooltip } from '@sim/emcn'
55
import {
66
BookOpen,
77
Check,
@@ -12,7 +12,6 @@ import {
1212
SquareArrowUpRight,
1313
Unlock,
1414
} from '@sim/emcn/icons'
15-
import { getWorkflowTypeAccent } from '@sim/workflow-renderer'
1615
import type { BlockRetryConfig } from '@sim/workflow-types/workflow'
1716
import { isEqual } from 'es-toolkit'
1817
import { useParams } from 'next/navigation'
@@ -54,8 +53,7 @@ import {
5453
isBlockProtected,
5554
} from '@/app/workspace/[workspaceId]/w/[workflowId]/utils/block-protection-utils'
5655
import { PreviewWorkflow } from '@/app/workspace/[workspaceId]/w/components/preview'
57-
import { hasBlockAccent } from '@/blocks/accent'
58-
import { isLightTileColor } from '@/blocks/icon-color'
56+
import { BlockTile } from '@/blocks/block-tile'
5957
import { getBlock } from '@/blocks/registry'
6058
import { useFolderMap } from '@/hooks/queries/folders'
6159
import { isWorkflowEffectivelyLocked } from '@/hooks/queries/utils/folder-tree'
@@ -69,18 +67,6 @@ import { useWorkflowStore } from '@/stores/workflows/workflow/store'
6967
/** Stable empty object to avoid creating new references */
7068
const EMPTY_SUBBLOCK_VALUES = {} as Record<string, any>
7169

72-
/**
73-
* Icon component for rendering block icons.
74-
*
75-
* @param icon - The icon component to render
76-
* @param className - Optional CSS classes
77-
* @returns Rendered icon or null if no icon provided
78-
*/
79-
const IconComponent = ({ icon: Icon, className }: { icon: any; className?: string }) => {
80-
if (!Icon) return null
81-
return <Icon className={className} />
82-
}
83-
8470
/**
8571
* Editor panel component.
8672
* Provides editor configuration and customization options for the workflow.
@@ -107,8 +93,6 @@ export function Editor() {
10793
const currentWorkflow = useCurrentWorkflow()
10894
const currentBlock = currentBlockId ? currentWorkflow.getBlockById(currentBlockId) : null
10995
const blockConfig = currentBlock ? getBlock(currentBlock.type) : null
110-
const typeAccent = getWorkflowTypeAccent(currentBlock?.type ?? '')
111-
const isIntegration = blockConfig != null && !hasBlockAccent(blockConfig.type)
11296
const title = currentBlock?.name || 'Editor'
11397
const isBlockNameSearchHighlighted =
11498
activeSearchTarget?.targetKind === 'block-name' && activeSearchTarget.blockId === currentBlockId
@@ -440,21 +424,8 @@ export function Editor() {
440424
{/* Header */}
441425
<div className='mx-[-1px] flex flex-shrink-0 items-center justify-between rounded-none border border-[var(--border)] bg-[var(--surface-4)] px-3 py-1.5'>
442426
<div className='flex min-w-0 flex-1 items-center gap-2'>
443-
{(blockConfig || isSubflow) && (
444-
<ChipTag
445-
variant={isIntegration ? 'brand' : typeAccent.variant}
446-
tone={isIntegration ? undefined : typeAccent.tone}
447-
brandColor={isIntegration ? blockConfig.bgColor : undefined}
448-
brandForeground={
449-
isIntegration && isLightTileColor(blockConfig.bgColor) ? 'dark' : 'light'
450-
}
451-
className='size-[18px] justify-center px-0'
452-
>
453-
<IconComponent
454-
icon={isSubflow ? subflowConfig?.icon : blockConfig?.icon}
455-
className='size-[12px]'
456-
/>
457-
</ChipTag>
427+
{currentBlock && (blockConfig || isSubflow) && (
428+
<BlockTile blockType={currentBlock.type} size='lg' />
458429
)}
459430
{isRenaming ? (
460431
<input

apps/sim/app/workspace/[workspaceId]/w/components/preview/components/preview-editor/preview-editor.tsx

Lines changed: 3 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@ import {
2121
ChevronUp,
2222
Clipboard,
2323
Expand,
24-
Repeat,
2524
Search,
26-
Split,
2725
SquareArrowUpRight,
2826
X,
2927
} from '@sim/emcn/icons'
@@ -46,8 +44,7 @@ import { PreviewWorkflow } from '@/app/workspace/[workspaceId]/w/components/prev
4644
import { useContextMenu } from '@/app/workspace/[workspaceId]/w/components/sidebar/hooks'
4745
import { getBlock } from '@/blocks'
4846
import { BlockTile } from '@/blocks/block-tile'
49-
import { getTileIconColorClass } from '@/blocks/icon-color'
50-
import type { BlockConfig, BlockIcon, SubBlockConfig, SubBlockType } from '@/blocks/types'
47+
import type { BlockConfig, SubBlockConfig, SubBlockType } from '@/blocks/types'
5148
import { normalizeName } from '@/executor/constants'
5249
import { navigatePath } from '@/executor/variables/resolvers/reference'
5350
import { useWorkflowState } from '@/hooks/queries/workflows'
@@ -533,20 +530,6 @@ function ConnectionsSection({
533530
)
534531
}
535532

536-
/**
537-
* Icon component for rendering block icons
538-
*/
539-
function IconComponent({
540-
icon: Icon,
541-
className,
542-
}: {
543-
icon: BlockIcon | undefined
544-
className?: string
545-
}) {
546-
if (!Icon) return null
547-
return <Icon className={className} />
548-
}
549-
550533
/**
551534
* Configuration for subflow types (loop and parallel) - matches use-subflow-editor.ts
552535
*/
@@ -1083,20 +1066,13 @@ function PreviewEditorContent({
10831066

10841067
if (isSubflow) {
10851068
const isLoop = block.type === 'loop'
1086-
const SubflowIcon = isLoop ? Repeat : Split
1087-
const subflowBgColor = isLoop ? '#2FB3FF' : '#FEE12B'
10881069
const subflowName = block.name || (isLoop ? 'Loop' : 'Parallel')
10891070

10901071
return (
10911072
<div className='relative flex h-full w-full flex-col overflow-hidden border-[var(--border)] border-l bg-[var(--surface-1)]'>
10921073
{/* Header - styled like subflow header */}
10931074
<div className='mx-[-1px] flex flex-shrink-0 items-center gap-2 rounded-b-[4px] border-[var(--border)] border-x border-b bg-[var(--surface-4)] px-3 py-1.5'>
1094-
<div
1095-
className='flex size-[18px] flex-shrink-0 items-center justify-center rounded-sm'
1096-
style={{ backgroundColor: subflowBgColor }}
1097-
>
1098-
<SubflowIcon className={cn('size-[12px]', getTileIconColorClass(subflowBgColor))} />
1099-
</div>
1075+
<BlockTile blockType={block.type} size='lg' />
11001076
<span className='min-w-0 flex-1 truncate text-[var(--text-primary)] text-sm'>
11011077
{subflowName}
11021078
</span>
@@ -1183,17 +1159,7 @@ function PreviewEditorContent({
11831159
<div className='relative flex h-full w-full flex-col overflow-hidden border-[var(--border)] border-l bg-[var(--surface-1)]'>
11841160
{/* Header - styled like editor */}
11851161
<div className='mx-[-1px] flex flex-shrink-0 items-center gap-2 rounded-b-[4px] border-[var(--border)] border-x border-b bg-[var(--surface-4)] px-3 py-1.5'>
1186-
{block.type !== 'note' && (
1187-
<div
1188-
className='flex size-[18px] flex-shrink-0 items-center justify-center overflow-hidden rounded-sm [&_img]:size-full'
1189-
style={{ backgroundColor: blockConfig.bgColor }}
1190-
>
1191-
<IconComponent
1192-
icon={blockConfig.icon}
1193-
className={cn('size-[12px]', getTileIconColorClass(blockConfig.bgColor))}
1194-
/>
1195-
</div>
1196-
)}
1162+
{block.type !== 'note' && <BlockTile blockType={block.type} size='lg' />}
11971163
<span className='min-w-0 flex-1 truncate text-[var(--text-primary)] text-sm'>
11981164
{block.name || blockConfig.name}
11991165
</span>

apps/sim/blocks/block-tile.tsx

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,23 @@ import { WorkflowTypeIcon } from '@sim/workflow-renderer'
66
import { getBlockTileColor, getBlockTileIcon, hasBlockAccent } from '@/blocks/accent'
77
import { getTileIconColorClass } from '@/blocks/icon-color'
88

9-
/** Slot sizes the tile ships in: the canvas 16px chip, or 14px for dense rows. */
9+
/**
10+
* Slot sizes the tile ships in: the 18px detail header, the canvas 16px chip,
11+
* or 14px for dense rows.
12+
*/
1013
const TILE_SIZE_CLASS = {
14+
lg: 'size-[18px]',
1115
md: 'size-[16px]',
1216
sm: 'size-[14px]',
1317
} as const
1418

19+
/** Icon drawn inside each slot. Only the header tile takes the larger glyph. */
20+
const TILE_ICON_SIZE_CLASS = {
21+
lg: 'size-[12px]',
22+
md: 'size-[10px]',
23+
sm: 'size-[10px]',
24+
} as const
25+
1526
export interface BlockTileProps extends Omit<HTMLAttributes<HTMLElement>, 'children' | 'style'> {
1627
/**
1728
* Block the tile represents; decides whether it takes the canvas role accent.
@@ -54,9 +65,18 @@ export function BlockTile({
5465
}: BlockTileProps) {
5566
const Icon = icon ?? (blockType ? getBlockTileIcon(blockType) : undefined)
5667
const sizeClass = cn(TILE_SIZE_CLASS[size], className)
68+
const iconSizeClass = TILE_ICON_SIZE_CLASS[size]
5769

5870
if (blockType && Icon && hasBlockAccent(blockType)) {
59-
return <WorkflowTypeIcon type={blockType} Icon={Icon} className={sizeClass} {...props} />
71+
return (
72+
<WorkflowTypeIcon
73+
type={blockType}
74+
Icon={Icon}
75+
className={sizeClass}
76+
iconClassName={iconSizeClass}
77+
{...props}
78+
/>
79+
)
6080
}
6181

6282
const fill = bgColor ?? (blockType ? getBlockTileColor(blockType) : undefined)
@@ -70,7 +90,8 @@ export function BlockTile({
7090
{Icon ? (
7191
<Icon
7292
className={cn(
73-
'size-[10px] transition-transform duration-100 group-hover:scale-110',
93+
iconSizeClass,
94+
'transition-transform duration-100 group-hover:scale-110',
7495
getTileIconColorClass(fill, true)
7596
)}
7697
/>

packages/workflow-renderer/src/workflow-block/workflow-block-view.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,10 +183,18 @@ export const getWorkflowTypeAccent = (type: string) =>
183183
export interface WorkflowTypeIconProps extends Omit<HTMLAttributes<HTMLSpanElement>, 'children'> {
184184
type: string
185185
Icon: ComponentType<{ className?: string }>
186+
/** Overrides the glyph size when the chip is rendered at a non-default slot. */
187+
iconClassName?: string
186188
}
187189

188190
/** Shared compact core-block icon used by workflow discovery surfaces. */
189-
export function WorkflowTypeIcon({ type, Icon, className, ...props }: WorkflowTypeIconProps) {
191+
export function WorkflowTypeIcon({
192+
type,
193+
Icon,
194+
className,
195+
iconClassName,
196+
...props
197+
}: WorkflowTypeIconProps) {
190198
const typeAccent = getWorkflowTypeAccent(type)
191199

192200
return (
@@ -197,7 +205,12 @@ export function WorkflowTypeIcon({ type, Icon, className, ...props }: WorkflowTy
197205
data-workflow-type-icon={type}
198206
{...props}
199207
>
200-
<Icon className='size-[10px] transition-transform duration-100 group-hover:scale-110' />
208+
<Icon
209+
className={cn(
210+
'size-[10px] transition-transform duration-100 group-hover:scale-110',
211+
iconClassName
212+
)}
213+
/>
201214
</ChipTag>
202215
)
203216
}

0 commit comments

Comments
 (0)