Skip to content

Commit 80830f5

Browse files
committed
improvement: sidebar, chat
1 parent 7151e81 commit 80830f5

File tree

24 files changed

+720
-480
lines changed

24 files changed

+720
-480
lines changed

apps/sim/app/_styles/globals.css

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,22 @@
1919

2020
.sidebar-container {
2121
width: var(--sidebar-width);
22+
transition: width 200ms cubic-bezier(0.25, 0.1, 0.25, 1);
23+
}
24+
25+
.sidebar-container span,
26+
.sidebar-container .text-small {
27+
transition: opacity 120ms ease;
28+
white-space: nowrap;
29+
}
30+
31+
.sidebar-container[data-collapsed] span,
32+
.sidebar-container[data-collapsed] .text-small {
33+
opacity: 0;
34+
}
35+
36+
.sidebar-container.is-resizing {
37+
transition: none;
2238
}
2339

2440
.panel-container {

apps/sim/app/layout.tsx

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,19 @@ export default function RootLayout({ children }: { children: React.ReactNode })
110110
if (stored) {
111111
var parsed = JSON.parse(stored);
112112
var state = parsed && parsed.state;
113-
var width = state && state.sidebarWidth;
114-
var maxSidebarWidth = window.innerWidth * 0.3;
113+
var isCollapsed = state && state.isCollapsed;
115114
116-
if (width >= 248 && width <= maxSidebarWidth) {
117-
document.documentElement.style.setProperty('--sidebar-width', width + 'px');
118-
} else if (width > maxSidebarWidth) {
119-
document.documentElement.style.setProperty('--sidebar-width', maxSidebarWidth + 'px');
115+
if (isCollapsed) {
116+
document.documentElement.style.setProperty('--sidebar-width', '51px');
117+
} else {
118+
var width = state && state.sidebarWidth;
119+
var maxSidebarWidth = window.innerWidth * 0.3;
120+
121+
if (width >= 248 && width <= maxSidebarWidth) {
122+
document.documentElement.style.setProperty('--sidebar-width', width + 'px');
123+
} else if (width > maxSidebarWidth) {
124+
document.documentElement.style.setProperty('--sidebar-width', maxSidebarWidth + 'px');
125+
}
120126
}
121127
}
122128
} catch (e) {
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
'use client'
2+
3+
import { useState } from 'react'
4+
import { ChevronDown } from '@/components/emcn'
5+
import { cn } from '@/lib/core/utils/cn'
6+
import type { ToolCallStatus } from '../../../../types'
7+
import { getAgentIcon } from '../../utils'
8+
import { ToolCallItem } from './tool-call-item'
9+
10+
interface ToolCallData {
11+
id: string
12+
toolName: string
13+
displayTitle: string
14+
status: ToolCallStatus
15+
}
16+
17+
interface AgentGroupProps {
18+
agentName: string
19+
agentLabel: string
20+
tools: ToolCallData[]
21+
}
22+
23+
export function AgentGroup({ agentName, agentLabel, tools }: AgentGroupProps) {
24+
const AgentIcon = getAgentIcon(agentName)
25+
const [expanded, setExpanded] = useState(true)
26+
const hasTools = tools.length > 0
27+
28+
return (
29+
<div className='flex flex-col gap-1.5'>
30+
<button
31+
type='button'
32+
onClick={hasTools ? () => setExpanded((prev) => !prev) : undefined}
33+
className={cn('flex items-center gap-[8px]', hasTools && 'cursor-pointer')}
34+
>
35+
<div className='flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center'>
36+
<AgentIcon className='h-[16px] w-[16px] text-[var(--text-icon)]' />
37+
</div>
38+
<span className='font-[var(--sidebar-font-weight)] text-[14px] text-[var(--text-body)]'>
39+
{agentLabel}
40+
</span>
41+
{hasTools && (
42+
<ChevronDown
43+
className={cn(
44+
'h-[7px] w-[9px] text-[var(--text-icon)] transition-transform duration-150',
45+
!expanded && '-rotate-90'
46+
)}
47+
/>
48+
)}
49+
</button>
50+
{hasTools && expanded && (
51+
<div className='flex flex-col gap-1.5'>
52+
{tools.map((tool) => (
53+
<ToolCallItem
54+
key={tool.id}
55+
toolName={tool.toolName}
56+
displayTitle={tool.displayTitle}
57+
status={tool.status}
58+
/>
59+
))}
60+
</div>
61+
)}
62+
</div>
63+
)
64+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { AgentGroup } from './agent-group'
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { Loader } from '@/components/emcn'
2+
import type { ToolCallStatus } from '../../../../types'
3+
import { getToolIcon } from '../../utils'
4+
5+
function CircleCheck({ className }: { className?: string }) {
6+
return (
7+
<svg
8+
width='16'
9+
height='16'
10+
viewBox='0 0 16 16'
11+
fill='none'
12+
xmlns='http://www.w3.org/2000/svg'
13+
className={className}
14+
>
15+
<circle cx='8' cy='8' r='6.5' stroke='currentColor' strokeWidth='1.25' />
16+
<path
17+
d='M5.5 8.5L7 10L10.5 6.5'
18+
stroke='currentColor'
19+
strokeWidth='1.25'
20+
strokeLinecap='round'
21+
strokeLinejoin='round'
22+
/>
23+
</svg>
24+
)
25+
}
26+
27+
interface ToolCallItemProps {
28+
toolName: string
29+
displayTitle: string
30+
status: ToolCallStatus
31+
}
32+
33+
export function ToolCallItem({ toolName, displayTitle, status }: ToolCallItemProps) {
34+
const Icon = getToolIcon(toolName)
35+
36+
return (
37+
<div className='flex items-center gap-[8px] pl-[24px]'>
38+
<div className='flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center'>
39+
{status === 'executing' ? (
40+
<Loader className='h-[16px] w-[16px] text-[var(--text-icon)]' animate />
41+
) : Icon ? (
42+
<Icon className='h-[16px] w-[16px] text-[var(--text-icon)]' />
43+
) : (
44+
<CircleCheck className='h-[16px] w-[16px] text-[var(--text-icon)]' />
45+
)}
46+
</div>
47+
<span className='font-[var(--sidebar-font-weight)] text-[14px] text-[var(--text-body)]'>
48+
{displayTitle}
49+
</span>
50+
</div>
51+
)
52+
}

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ function extractTextContent(node: React.ReactNode): string {
3939

4040
const PROSE_CLASSES = cn(
4141
'prose prose-base dark:prose-invert max-w-none',
42-
'font-[family-name:var(--font-inter)] antialiased break-words font-[420] tracking-[0]',
42+
'font-[family-name:var(--font-inter)] antialiased break-words font-[430] tracking-[0]',
4343
'prose-headings:font-[600] prose-headings:tracking-[0] prose-headings:text-[var(--text-primary)]',
4444
'prose-headings:mb-3 prose-headings:mt-6 first:prose-headings:mt-0',
45-
'prose-p:text-[16px] prose-p:leading-7 prose-p:text-[var(--text-primary)]',
45+
'prose-p:text-[15px] prose-p:leading-[25px] prose-p:text-[var(--text-primary)]',
4646
'first:prose-p:mt-0 last:prose-p:mb-0',
47-
'prose-li:text-[16px] prose-li:leading-7 prose-li:text-[var(--text-primary)]',
47+
'prose-li:text-[15px] prose-li:leading-[25px] prose-li:text-[var(--text-primary)]',
4848
'prose-li:my-1',
4949
'prose-ul:my-4 prose-ol:my-4',
5050
'prose-strong:font-[600] prose-strong:text-[var(--text-primary)]',
@@ -106,7 +106,7 @@ const MARKDOWN_COMPONENTS: React.ComponentProps<typeof ReactMarkdown>['component
106106

107107
if (!codeString) {
108108
return (
109-
<pre className='not-prose my-6 overflow-x-auto rounded-lg bg-[var(--surface-5)] p-4 font-[420] font-mono text-[13px] text-[var(--text-primary)] leading-[21px] dark:bg-[#1F1F1F]'>
109+
<pre className='not-prose my-6 overflow-x-auto rounded-lg bg-[var(--surface-5)] p-4 font-[430] font-mono text-[13px] text-[var(--text-primary)] leading-[21px] dark:bg-[#1F1F1F]'>
110110
{children}
111111
</pre>
112112
)
@@ -125,7 +125,7 @@ const MARKDOWN_COMPONENTS: React.ComponentProps<typeof ReactMarkdown>['component
125125
)}
126126
<div className='code-editor-theme bg-[var(--surface-5)] dark:bg-[#1F1F1F]'>
127127
<pre
128-
className='m-0 overflow-x-auto whitespace-pre p-4 font-[420] font-mono text-[13px] text-[var(--text-primary)] leading-[21px] dark:text-[#eeeeee]'
128+
className='m-0 overflow-x-auto whitespace-pre p-4 font-[430] font-mono text-[13px] text-[var(--text-primary)] leading-[21px] dark:text-[#eeeeee]'
129129
dangerouslySetInnerHTML={{ __html: html }}
130130
/>
131131
</div>
@@ -156,13 +156,13 @@ const MARKDOWN_COMPONENTS: React.ComponentProps<typeof ReactMarkdown>['component
156156
li({ children, className }) {
157157
if (className?.includes('task-list-item')) {
158158
return (
159-
<li className='flex list-none items-start gap-2 text-[16px] text-[var(--text-primary)] leading-7'>
159+
<li className='flex list-none items-start gap-2 text-[15px] text-[var(--text-primary)] leading-[25px]'>
160160
{children}
161161
</li>
162162
)
163163
}
164164
return (
165-
<li className='my-1 text-[16px] text-[var(--text-primary)] leading-7 marker:text-[var(--text-primary)]'>
165+
<li className='my-1 text-[15px] text-[var(--text-primary)] leading-[25px] marker:text-[var(--text-primary)]'>
166166
{children}
167167
</li>
168168
)
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1+
export { AgentGroup } from './agent-group'
12
export { ChatContent } from './chat-content'
23
export { Options } from './options'
3-
export { Subagent } from './subagent'
4-
export { ToolCall } from './tool-calls'

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export function Options({ items, onSelect }: OptionsProps) {
1515
key={item.id}
1616
type='button'
1717
onClick={() => onSelect?.(item.id)}
18-
className='rounded-full border border-[var(--divider)] bg-[var(--bg)] px-3.5 py-1.5 font-[420] font-[family-name:var(--font-inter)] text-[14px] text-[var(--text-primary)] leading-5 transition-colors hover:bg-[var(--surface-5)]'
18+
className='rounded-full border border-[var(--divider)] bg-[var(--bg)] px-3.5 py-1.5 font-[430] font-[family-name:var(--font-inter)] text-[14px] text-[var(--text-primary)] leading-5 transition-colors hover:bg-[var(--surface-5)]'
1919
>
2020
{item.label}
2121
</button>

apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/subagent/index.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

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

Lines changed: 0 additions & 28 deletions
This file was deleted.

0 commit comments

Comments
 (0)