Skip to content

Commit d9a2d7f

Browse files
committed
refactor(types): narrow ChatMessageContext.kind to ChatContextKind union and add workflowBorderColor utility
1 parent 6e910ee commit d9a2d7f

File tree

21 files changed

+112
-105
lines changed

21 files changed

+112
-105
lines changed

apps/sim/app/(landing)/components/features/components/features-preview.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
xAIIcon,
1919
} from '@/components/icons'
2020
import { cn } from '@/lib/core/utils/cn'
21+
import { workflowBorderColor } from '@/lib/workspaces/colors'
2122

2223
interface FeaturesPreviewProps {
2324
activeTab: number
@@ -383,7 +384,7 @@ function MiniCardIcon({ variant, color }: { variant: CardVariant; color?: string
383384
className='h-[7px] w-[7px] flex-shrink-0 rounded-[1.5px] border'
384385
style={{
385386
backgroundColor: c,
386-
borderColor: `${c}60`,
387+
borderColor: workflowBorderColor(c),
387388
backgroundClip: 'padding-box',
388389
}}
389390
/>
@@ -470,7 +471,7 @@ function WorkflowCardBody({ color }: { color: string }) {
470471
className='absolute top-2.5 left-[40px] h-[14px] w-[14px] rounded-[3px] border-[2px]'
471472
style={{
472473
backgroundColor: color,
473-
borderColor: `${color}60`,
474+
borderColor: workflowBorderColor(color),
474475
backgroundClip: 'padding-box',
475476
}}
476477
/>
@@ -481,7 +482,7 @@ function WorkflowCardBody({ color }: { color: string }) {
481482
className='absolute top-[36px] left-[68px] h-[14px] w-[14px] rounded-[3px] border-[2px]'
482483
style={{
483484
backgroundColor: color,
484-
borderColor: `${color}60`,
485+
borderColor: workflowBorderColor(color),
485486
backgroundClip: 'padding-box',
486487
opacity: 0.5,
487488
}}
@@ -896,7 +897,7 @@ function MockLogDetailsSidebar({ selectedRow, onPrev, onNext }: MockLogDetailsSi
896897
className='h-[10px] w-[10px] shrink-0 rounded-[3px] border-[1.5px]'
897898
style={{
898899
backgroundColor: color,
899-
borderColor: `${color}60`,
900+
borderColor: workflowBorderColor(color),
900901
backgroundClip: 'padding-box',
901902
}}
902903
/>

apps/sim/app/(landing)/components/landing-preview/components/landing-preview-logs/landing-preview-logs.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Download } from 'lucide-react'
55
import { ArrowUpDown, Badge, Library, ListFilter, Search } from '@/components/emcn'
66
import type { BadgeProps } from '@/components/emcn/components/badge/badge'
77
import { cn } from '@/lib/core/utils/cn'
8+
import { workflowBorderColor } from '@/lib/workspaces/colors'
89

910
interface LogRow {
1011
id: string
@@ -283,7 +284,7 @@ export function LandingPreviewLogs() {
283284
className='h-[10px] w-[10px] flex-shrink-0 rounded-[3px] border-[1.5px]'
284285
style={{
285286
backgroundColor: log.workflowColor,
286-
borderColor: `${log.workflowColor}60`,
287+
borderColor: workflowBorderColor(log.workflowColor),
287288
backgroundClip: 'padding-box',
288289
}}
289290
/>

apps/sim/app/(landing)/components/landing-preview/components/landing-preview-sidebar/landing-preview-sidebar.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
Table,
1212
} from '@/components/emcn/icons'
1313
import { cn } from '@/lib/core/utils/cn'
14+
import { workflowBorderColor } from '@/lib/workspaces/colors'
1415
import type { PreviewWorkflow } from '@/app/(landing)/components/landing-preview/components/landing-preview-workflow/workflow-data'
1516

1617
export type SidebarView =
@@ -211,7 +212,7 @@ export function LandingPreviewSidebar({
211212
className='h-[14px] w-[14px] flex-shrink-0 rounded-[4px] border-[2.5px]'
212213
style={{
213214
backgroundColor: workflow.color,
214-
borderColor: `${workflow.color}60`,
215+
borderColor: workflowBorderColor(workflow.color),
215216
backgroundClip: 'padding-box',
216217
}}
217218
/>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { Blimp, Database, Folder as FolderIcon, Table as TableIcon } from '@/components/emcn/icons'
2+
import { getDocumentIcon } from '@/components/icons/document-icons'
3+
import { cn } from '@/lib/core/utils/cn'
4+
import { workflowBorderColor } from '@/lib/workspaces/colors'
5+
import type { ChatMessageContext } from '@/app/workspace/[workspaceId]/home/types'
6+
7+
interface ContextMentionIconProps {
8+
context: ChatMessageContext
9+
/** Only used when context.kind is 'workflow' or 'current_workflow'; ignored otherwise. */
10+
workflowColor?: string | null
11+
/** Applied to every icon element. Include sizing and positional classes (e.g. h-[12px] w-[12px]). */
12+
className: string
13+
}
14+
15+
/** Renders the icon for a context mention chip. Returns null when no icon applies. */
16+
export function ContextMentionIcon({ context, workflowColor, className }: ContextMentionIconProps) {
17+
switch (context.kind) {
18+
case 'workflow':
19+
case 'current_workflow':
20+
return workflowColor ? (
21+
<span
22+
className={cn('rounded-[3px] border-[2px]', className)}
23+
style={{
24+
backgroundColor: workflowColor,
25+
borderColor: workflowBorderColor(workflowColor),
26+
backgroundClip: 'padding-box',
27+
}}
28+
/>
29+
) : null
30+
case 'knowledge':
31+
return <Database className={className} />
32+
case 'table':
33+
return <TableIcon className={className} />
34+
case 'file': {
35+
const FileDocIcon = getDocumentIcon('', context.label)
36+
return <FileDocIcon className={className} />
37+
}
38+
case 'folder':
39+
return <FolderIcon className={className} />
40+
case 'past_chat':
41+
return <Blimp className={className} />
42+
default:
43+
return null
44+
}
45+
}

apps/sim/app/workspace/[workspaceId]/home/components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export { ChatMessageAttachments } from './chat-message-attachments'
2+
export { ContextMentionIcon } from './context-mention-icon'
23
export {
34
assistantMessageHasRenderableContent,
45
MessageContent,

apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/components/resource-content/resource-content.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
getFileExtension,
2323
getMimeTypeFromExtension,
2424
} from '@/lib/uploads/utils/file-utils'
25+
import { workflowBorderColor } from '@/lib/workspaces/colors'
2526
import {
2627
FileViewer,
2728
type PreviewMode,
@@ -514,7 +515,7 @@ function EmbeddedFolder({ workspaceId, folderId }: EmbeddedFolderProps) {
514515
className='h-[12px] w-[12px] flex-shrink-0 rounded-[3px] border-[2px]'
515516
style={{
516517
backgroundColor: w.color,
517-
borderColor: `${w.color}60`,
518+
borderColor: workflowBorderColor(w.color),
518519
backgroundClip: 'padding-box',
519520
}}
520521
/>

apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/components/resource-registry/resource-registry.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
import { WorkflowIcon } from '@/components/icons'
1515
import { getDocumentIcon } from '@/components/icons/document-icons'
1616
import { cn } from '@/lib/core/utils/cn'
17+
import { workflowBorderColor } from '@/lib/workspaces/colors'
1718
import type {
1819
MothershipResource,
1920
MothershipResourceType,
@@ -50,7 +51,7 @@ function WorkflowTabSquare({ workflowId, className }: { workflowId: string; clas
5051
className={cn('flex-shrink-0 rounded-[3px] border-[2px]', className)}
5152
style={{
5253
backgroundColor: color,
53-
borderColor: `${color}60`,
54+
borderColor: workflowBorderColor(color),
5455
backgroundClip: 'padding-box',
5556
}}
5657
/>
@@ -65,7 +66,7 @@ function WorkflowDropdownItem({ item }: DropdownItemRenderProps) {
6566
className='h-[14px] w-[14px] flex-shrink-0 rounded-[3px] border-[2px]'
6667
style={{
6768
backgroundColor: color,
68-
borderColor: `${color}60`,
69+
borderColor: workflowBorderColor(color),
6970
backgroundClip: 'padding-box',
7071
}}
7172
/>

apps/sim/app/workspace/[workspaceId]/home/components/user-input/user-input.tsx

Lines changed: 8 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@
33
import type React from 'react'
44
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'
55
import { useParams } from 'next/navigation'
6-
import { Blimp, Database, Folder as FolderIcon, Table as TableIcon } from '@/components/emcn/icons'
7-
import { getDocumentIcon } from '@/components/icons/document-icons'
86
import { useSession } from '@/lib/auth/auth-client'
97
import { SIM_RESOURCE_DRAG_TYPE, SIM_RESOURCES_DRAG_TYPE } from '@/lib/copilot/resource-types'
108
import { cn } from '@/lib/core/utils/cn'
119
import { CHAT_ACCEPT_ATTRIBUTE } from '@/lib/uploads/utils/validation'
10+
import { ContextMentionIcon } from '@/app/workspace/[workspaceId]/home/components/context-mention-icon'
1211
import { useAvailableResources } from '@/app/workspace/[workspaceId]/home/components/mothership-view/components/add-resource-dropdown'
1312
import type {
1413
PlusMenuHandle,
@@ -672,45 +671,13 @@ export function UserInput({
672671
: range.token
673672
const matchingCtx = contexts.find((c) => c.label === mentionLabel)
674673

675-
let mentionIconNode: React.ReactNode = null
676-
if (matchingCtx) {
677-
const iconClasses = 'absolute inset-0 m-auto h-[12px] w-[12px] text-[var(--text-icon)]'
678-
switch (matchingCtx.kind) {
679-
case 'workflow':
680-
case 'current_workflow': {
681-
const wfId = (matchingCtx as { workflowId: string }).workflowId
682-
const wfColor = workflowsById[wfId]?.color ?? '#888'
683-
mentionIconNode = (
684-
<div
685-
className='absolute inset-0 m-auto h-[12px] w-[12px] rounded-[3px] border-[2px]'
686-
style={{
687-
backgroundColor: wfColor,
688-
borderColor: `${wfColor}60`,
689-
backgroundClip: 'padding-box',
690-
}}
691-
/>
692-
)
693-
break
694-
}
695-
case 'knowledge':
696-
mentionIconNode = <Database className={iconClasses} />
697-
break
698-
case 'table':
699-
mentionIconNode = <TableIcon className={iconClasses} />
700-
break
701-
case 'file': {
702-
const FileDocIcon = getDocumentIcon('', mentionLabel)
703-
mentionIconNode = <FileDocIcon className={iconClasses} />
704-
break
705-
}
706-
case 'folder':
707-
mentionIconNode = <FolderIcon className={iconClasses} />
708-
break
709-
case 'past_chat':
710-
mentionIconNode = <Blimp className={iconClasses} />
711-
break
712-
}
713-
}
674+
const mentionIconNode = matchingCtx ? (
675+
<ContextMentionIcon
676+
context={matchingCtx}
677+
workflowColor={workflowsById[matchingCtx.workflowId ?? '']?.color ?? null}
678+
className='absolute inset-0 m-auto h-[12px] w-[12px] text-[var(--text-icon)]'
679+
/>
680+
) : null
714681

715682
elements.push(
716683
<span

apps/sim/app/workspace/[workspaceId]/home/components/user-message-content/user-message-content.tsx

Lines changed: 6 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22

33
import { useMemo } from 'react'
44
import { useParams } from 'next/navigation'
5-
import { Blimp, Database, Folder as FolderIcon, Table as TableIcon } from '@/components/emcn/icons'
6-
import { getDocumentIcon } from '@/components/icons/document-icons'
5+
import { ContextMentionIcon } from '@/app/workspace/[workspaceId]/home/components/context-mention-icon'
76
import type { ChatMessageContext } from '@/app/workspace/[workspaceId]/home/types'
87
import { useWorkflows } from '@/hooks/queries/workflows'
98

@@ -53,45 +52,13 @@ function MentionHighlight({ context }: { context: ChatMessageContext }) {
5352
return (workflowList ?? []).find((w) => w.id === context.workflowId)?.color ?? null
5453
}, [workflowList, context.kind, context.workflowId])
5554

56-
let icon: React.ReactNode = null
57-
const iconClasses = 'h-[12px] w-[12px] flex-shrink-0 text-[var(--text-icon)]'
58-
59-
switch (context.kind) {
60-
case 'workflow':
61-
case 'current_workflow':
62-
icon = workflowColor ? (
63-
<span
64-
className='inline-block h-[12px] w-[12px] flex-shrink-0 rounded-[3px] border-[2px]'
65-
style={{
66-
backgroundColor: workflowColor,
67-
borderColor: `${workflowColor}60`,
68-
backgroundClip: 'padding-box',
69-
}}
70-
/>
71-
) : null
72-
break
73-
case 'knowledge':
74-
icon = <Database className={iconClasses} />
75-
break
76-
case 'table':
77-
icon = <TableIcon className={iconClasses} />
78-
break
79-
case 'file': {
80-
const FileDocIcon = getDocumentIcon('', context.label)
81-
icon = <FileDocIcon className={iconClasses} />
82-
break
83-
}
84-
case 'folder':
85-
icon = <FolderIcon className={iconClasses} />
86-
break
87-
case 'past_chat':
88-
icon = <Blimp className={iconClasses} />
89-
break
90-
}
91-
9255
return (
9356
<span className='inline-flex items-baseline gap-1 rounded-[5px] bg-[var(--surface-5)] px-[5px]'>
94-
{icon && <span className='relative top-0.5 flex-shrink-0'>{icon}</span>}
57+
<ContextMentionIcon
58+
context={context}
59+
workflowColor={workflowColor}
60+
className='relative top-0.5 h-[12px] w-[12px] flex-shrink-0 text-[var(--text-icon)]'
61+
/>
9562
{context.label}
9663
</span>
9764
)

apps/sim/app/workspace/[workspaceId]/home/types.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ export type {
66
MothershipResourceType,
77
} from '@/lib/copilot/resource-types'
88

9+
/** Union of all valid context kind strings, derived from {@link ChatContext}. */
10+
export type ChatContextKind = ChatContext['kind']
11+
912
export interface FileAttachmentForApi {
1013
id: string
1114
key: string
@@ -260,7 +263,7 @@ export interface ChatMessageAttachment {
260263
}
261264

262265
export interface ChatMessageContext {
263-
kind: string
266+
kind: ChatContextKind
264267
label: string
265268
workflowId?: string
266269
knowledgeId?: string

0 commit comments

Comments
 (0)