Skip to content

Commit a7a7c86

Browse files
authored
improvement(copilot): ui/ux; refactor: store dimensions (#2636)
1 parent 97a9295 commit a7a7c86

File tree

21 files changed

+178
-158
lines changed

21 files changed

+178
-158
lines changed

apps/sim/app/_styles/globals.css

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@
55
/**
66
* CSS-based sidebar and panel widths to prevent SSR hydration mismatches.
77
* Default widths are set here and updated via blocking script before React hydrates.
8+
*
9+
* @important These values must stay in sync with stores/constants.ts
10+
* @see stores/constants.ts for the source of truth
811
*/
912
:root {
10-
--sidebar-width: 232px;
11-
--panel-width: 260px;
12-
--toolbar-triggers-height: 300px;
13-
--editor-connections-height: 200px;
14-
--terminal-height: 155px;
13+
--sidebar-width: 232px; /* SIDEBAR_WIDTH.DEFAULT */
14+
--panel-width: 290px; /* PANEL_WIDTH.DEFAULT */
15+
--toolbar-triggers-height: 300px; /* TOOLBAR_TRIGGERS_HEIGHT.DEFAULT */
16+
--editor-connections-height: 172px; /* EDITOR_CONNECTIONS_HEIGHT.DEFAULT */
17+
--terminal-height: 155px; /* TERMINAL_HEIGHT.DEFAULT */
1518
}
1619

1720
.sidebar-container {

apps/sim/app/layout.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,12 @@ export default function RootLayout({ children }: { children: React.ReactNode })
4141
}}
4242
/>
4343

44-
{/* Workspace layout dimensions: set CSS vars before hydration to avoid layout jump */}
44+
{/*
45+
Workspace layout dimensions: set CSS vars before hydration to avoid layout jump.
46+
47+
IMPORTANT: These hardcoded values must stay in sync with stores/constants.ts
48+
We cannot use imports here since this is a blocking script that runs before React.
49+
*/}
4550
<script
4651
id='workspace-layout-dimensions'
4752
dangerouslySetInnerHTML={{
@@ -84,7 +89,7 @@ export default function RootLayout({ children }: { children: React.ReactNode })
8489
var panelWidth = panelState && panelState.panelWidth;
8590
var maxPanelWidth = window.innerWidth * 0.4;
8691
87-
if (panelWidth >= 260 && panelWidth <= maxPanelWidth) {
92+
if (panelWidth >= 290 && panelWidth <= maxPanelWidth) {
8893
document.documentElement.style.setProperty('--panel-width', panelWidth + 'px');
8994
} else if (panelWidth > maxPanelWidth) {
9095
document.documentElement.style.setProperty('--panel-width', maxPanelWidth + 'px');

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/file-display.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ export const FileAttachmentDisplay = memo(({ fileAttachments }: FileAttachmentDi
107107
{fileAttachments.map((file) => (
108108
<div
109109
key={file.id}
110-
className='group relative h-16 w-16 cursor-pointer overflow-hidden rounded-md border border-border/50 bg-muted/20 transition-all hover:bg-muted/40'
110+
className='group relative h-16 w-16 cursor-pointer overflow-hidden rounded-md border border-[var(--border-1)] bg-muted/20 transition-all hover:bg-muted/40'
111111
onClick={() => handleFileClick(file)}
112112
title={`${file.filename} (${formatFileSize(file.size)})`}
113113
>

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/copilot-message.tsx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ const CopilotMessage: FC<CopilotMessageProps> = memo(
319319
onClick={handleMessageClick}
320320
onMouseEnter={() => setIsHoveringMessage(true)}
321321
onMouseLeave={() => setIsHoveringMessage(false)}
322-
className='group relative w-full cursor-pointer rounded-[4px] border border-[var(--border-1)] bg-[var(--surface-5)] px-[6px] py-[6px] transition-all duration-200 hover:border-[var(--surface-7)] hover:bg-[var(--surface-5)] dark:bg-[var(--surface-5)] dark:hover:border-[var(--surface-7)] dark:hover:bg-[var(--border-1)]'
322+
className='group relative w-full cursor-pointer rounded-[4px] border border-[var(--border-1)] bg-[var(--surface-4)] px-[6px] py-[6px] transition-all duration-200 hover:border-[var(--surface-7)] hover:bg-[var(--surface-4)] dark:bg-[var(--surface-4)] dark:hover:border-[var(--surface-7)] dark:hover:bg-[var(--border-1)]'
323323
>
324324
<div
325325
ref={messageContentRef}
@@ -350,7 +350,7 @@ const CopilotMessage: FC<CopilotMessageProps> = memo(
350350
nodes.push(
351351
<span
352352
key={`mention-${i}-${lastIndex}`}
353-
className='rounded-[6px] bg-[rgba(142,76,251,0.65)]'
353+
className='rounded-[4px] bg-[rgba(50,189,126,0.65)] py-[1px]'
354354
>
355355
{mention}
356356
</span>
@@ -365,7 +365,7 @@ const CopilotMessage: FC<CopilotMessageProps> = memo(
365365

366366
{/* Gradient fade when truncated - applies to entire message box */}
367367
{!isExpanded && needsExpansion && (
368-
<div className='pointer-events-none absolute right-0 bottom-0 left-0 h-6 bg-gradient-to-t from-0% from-[var(--surface-5)] via-40% via-[var(--surface-5)]/70 to-100% to-transparent group-hover:from-[var(--surface-5)] group-hover:via-[var(--surface-5)]/70 dark:from-[var(--surface-5)] dark:via-[var(--surface-5)]/70 dark:group-hover:from-[var(--border-1)] dark:group-hover:via-[var(--border-1)]/70' />
368+
<div className='pointer-events-none absolute right-0 bottom-0 left-0 h-6 bg-gradient-to-t from-0% from-[var(--surface-4)] via-25% via-[var(--surface-4)] to-100% to-transparent opacity-40 group-hover:opacity-30 dark:from-[var(--surface-4)] dark:via-[var(--surface-4)] dark:group-hover:from-[var(--border-1)] dark:group-hover:via-[var(--border-1)]' />
369369
)}
370370

371371
{/* Abort button when hovering and response is generating (only on last user message) */}
@@ -376,13 +376,12 @@ const CopilotMessage: FC<CopilotMessageProps> = memo(
376376
e.stopPropagation()
377377
abortMessage()
378378
}}
379-
className='h-[20px] w-[20px] rounded-full bg-[var(--c-C0C0C0)] p-0 transition-colors hover:bg-[var(--c-D0D0D0)]'
379+
className='h-[20px] w-[20px] rounded-full border-0 bg-[var(--c-383838)] p-0 transition-colors hover:bg-[var(--c-575757)] dark:bg-[var(--c-E0E0E0)] dark:hover:bg-[var(--c-CFCFCF)]'
380380
title='Stop generation'
381381
>
382382
<svg
383-
className='block h-[13px] w-[13px]'
383+
className='block h-[13px] w-[13px] fill-white dark:fill-black'
384384
viewBox='0 0 24 24'
385-
fill='black'
386385
xmlns='http://www.w3.org/2000/svg'
387386
>
388387
<rect x='4' y='4' width='16' height='16' rx='3' ry='3' />

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/components/model-selector/model-selector.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ export function ModelSelector({ selectedModel, isNearTop, onModelSelect }: Model
140140
{getModelIconComponent(option.value)}
141141
<span>{option.label}</span>
142142
{isMaxModel(option.value) && (
143-
<Badge variant='default' className='ml-auto px-[6px] py-[1px] text-[10px]'>
143+
<Badge size='sm' className='ml-auto'>
144144
MAX
145145
</Badge>
146146
)}

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/user-input.tsx

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,7 @@ const UserInput = forwardRef<UserInputRef, UserInputProps>(
590590
elements.push(
591591
<span
592592
key={`mention-${i}-${range.start}-${range.end}`}
593-
className='rounded-[6px] bg-[rgba(142,76,251,0.65)]'
593+
className='rounded-[4px] bg-[rgba(50,189,126,0.65)] py-[1px]'
594594
>
595595
{mentionText}
596596
</span>
@@ -619,7 +619,7 @@ const UserInput = forwardRef<UserInputRef, UserInputProps>(
619619
<div
620620
ref={setInputContainerRef}
621621
className={cn(
622-
'relative w-full rounded-[4px] border border-[var(--border-1)] bg-[var(--surface-5)] px-[6px] py-[6px] transition-colors dark:bg-[var(--surface-5)]',
622+
'relative w-full rounded-[4px] border border-[var(--border-1)] bg-[var(--surface-4)] px-[6px] py-[6px] transition-colors dark:bg-[var(--surface-4)]',
623623
fileAttachments.isDragging && 'ring-[1.75px] ring-[var(--brand-secondary)]'
624624
)}
625625
onDragEnter={fileAttachments.handleDragEnter}
@@ -746,7 +746,7 @@ const UserInput = forwardRef<UserInputRef, UserInputProps>(
746746
onClick={fileAttachments.handleFileSelect}
747747
title='Attach file'
748748
className={cn(
749-
'cursor-pointer rounded-[6px] bg-transparent p-[0px] dark:bg-transparent',
749+
'cursor-pointer rounded-[6px] border-0 bg-transparent p-[0px] dark:bg-transparent',
750750
(disabled || isLoading) && 'cursor-not-allowed opacity-50'
751751
)}
752752
>
@@ -758,20 +758,19 @@ const UserInput = forwardRef<UserInputRef, UserInputProps>(
758758
onClick={handleAbort}
759759
disabled={isAborting}
760760
className={cn(
761-
'h-[20px] w-[20px] rounded-full p-0 transition-colors',
761+
'h-[20px] w-[20px] rounded-full border-0 p-0 transition-colors',
762762
!isAborting
763-
? 'bg-[var(--c-C0C0C0)] hover:bg-[var(--c-D0D0D0)]'
764-
: 'bg-[var(--c-C0C0C0)]'
763+
? 'bg-[var(--c-383838)] hover:bg-[var(--c-575757)] dark:bg-[var(--c-E0E0E0)] dark:hover:bg-[var(--c-CFCFCF)]'
764+
: 'bg-[var(--c-383838)] dark:bg-[var(--c-E0E0E0)]'
765765
)}
766766
title='Stop generation'
767767
>
768768
{isAborting ? (
769-
<Loader2 className='block h-[13px] w-[13px] animate-spin text-black' />
769+
<Loader2 className='block h-[13px] w-[13px] animate-spin text-white dark:text-black' />
770770
) : (
771771
<svg
772-
className='block h-[13px] w-[13px]'
772+
className='block h-[13px] w-[13px] fill-white dark:fill-black'
773773
viewBox='0 0 24 24'
774-
fill='black'
775774
xmlns='http://www.w3.org/2000/svg'
776775
>
777776
<rect x='4' y='4' width='16' height='16' rx='3' ry='3' />
@@ -785,16 +784,19 @@ const UserInput = forwardRef<UserInputRef, UserInputProps>(
785784
}}
786785
disabled={!canSubmit}
787786
className={cn(
788-
'h-[22px] w-[22px] rounded-full p-0 transition-colors',
787+
'h-[22px] w-[22px] rounded-full border-0 p-0 transition-colors',
789788
canSubmit
790-
? 'bg-[var(--c-C0C0C0)] hover:bg-[var(--c-D0D0D0)]'
791-
: 'bg-[var(--c-C0C0C0)]'
789+
? 'bg-[var(--c-383838)] hover:bg-[var(--c-575757)] dark:bg-[var(--c-E0E0E0)] dark:hover:bg-[var(--c-CFCFCF)]'
790+
: 'bg-[var(--c-808080)] dark:bg-[var(--c-808080)]'
792791
)}
793792
>
794793
{isLoading ? (
795-
<Loader2 className='block h-3.5 w-3.5 animate-spin text-black' />
794+
<Loader2 className='block h-3.5 w-3.5 animate-spin text-white dark:text-black' />
796795
) : (
797-
<ArrowUp className='block h-3.5 w-3.5 text-black' strokeWidth={2.25} />
796+
<ArrowUp
797+
className='block h-3.5 w-3.5 text-white dark:text-black'
798+
strokeWidth={2.25}
799+
/>
798800
)}
799801
</Button>
800802
)}

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/hooks/use-panel-resize.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
import { useCallback, useEffect, useState } from 'react'
2+
import { PANEL_WIDTH } from '@/stores/constants'
23
import { usePanelStore } from '@/stores/panel/store'
34

4-
/**
5-
* Constants for panel sizing
6-
*/
7-
const MIN_WIDTH = 244
8-
const MAX_WIDTH_PERCENTAGE = 0.4 // 40% of viewport width
9-
105
/**
116
* Custom hook to handle panel resize functionality.
127
* Manages mouse events for resizing and enforces min/max width constraints.
@@ -35,9 +30,9 @@ export function usePanelResize() {
3530
const handleMouseMove = (e: MouseEvent) => {
3631
// Calculate width from the right edge of the viewport
3732
const newWidth = window.innerWidth - e.clientX
38-
const maxWidth = window.innerWidth * MAX_WIDTH_PERCENTAGE
33+
const maxWidth = window.innerWidth * PANEL_WIDTH.MAX_PERCENTAGE
3934

40-
if (newWidth >= MIN_WIDTH && newWidth <= maxWidth) {
35+
if (newWidth >= PANEL_WIDTH.MIN && newWidth <= maxWidth) {
4136
setPanelWidth(newWidth)
4237
}
4338
}

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/terminal/hooks/use-output-panel-resize.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useCallback, useEffect, useState } from 'react'
2+
import { OUTPUT_PANEL_WIDTH } from '@/stores/constants'
23
import { useTerminalStore } from '@/stores/terminal'
34

4-
const MIN_WIDTH = 440
55
const BLOCK_COLUMN_WIDTH = 240
66

77
export function useOutputPanelResize() {
@@ -26,7 +26,7 @@ export function useOutputPanelResize() {
2626
const newWidth = window.innerWidth - e.clientX - panelWidth
2727
const terminalWidth = window.innerWidth - sidebarWidth - panelWidth
2828
const maxWidth = terminalWidth - BLOCK_COLUMN_WIDTH
29-
const clampedWidth = Math.max(MIN_WIDTH, Math.min(newWidth, maxWidth))
29+
const clampedWidth = Math.max(OUTPUT_PANEL_WIDTH.MIN, Math.min(newWidth, maxWidth))
3030

3131
setOutputPanelWidth(clampedWidth)
3232
}

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import {
4444
useTerminalResize,
4545
} from '@/app/workspace/[workspaceId]/w/[workflowId]/components/terminal/hooks'
4646
import { getBlock } from '@/blocks'
47+
import { OUTPUT_PANEL_WIDTH, TERMINAL_HEIGHT } from '@/stores/constants'
4748
import { useCopilotTrainingStore } from '@/stores/copilot-training/store'
4849
import { useGeneralStore } from '@/stores/settings/general/store'
4950
import type { ConsoleEntry } from '@/stores/terminal'
@@ -53,15 +54,15 @@ import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
5354
/**
5455
* Terminal height configuration constants
5556
*/
56-
const MIN_HEIGHT = 30
57+
const MIN_HEIGHT = TERMINAL_HEIGHT.MIN
5758
const NEAR_MIN_THRESHOLD = 40
58-
const DEFAULT_EXPANDED_HEIGHT = 155
59+
const DEFAULT_EXPANDED_HEIGHT = TERMINAL_HEIGHT.DEFAULT
5960

6061
/**
6162
* Column width constants - numeric values for calculations
6263
*/
6364
const BLOCK_COLUMN_WIDTH_PX = 240
64-
const MIN_OUTPUT_PANEL_WIDTH_PX = 440
65+
const MIN_OUTPUT_PANEL_WIDTH_PX = OUTPUT_PANEL_WIDTH.MIN
6566

6667
/**
6768
* Column width constants - Tailwind classes for styling

0 commit comments

Comments
 (0)