Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions apps/sim/app/chat/[subdomain]/chat.css
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,12 @@
color: hsl(var(--foreground));
}

/* Tooltip overrides - keep tooltips black with white text for consistency */
.chat-light-wrapper [data-radix-tooltip-content] {
background-color: hsl(0 0% 3.9%) !important;
color: hsl(0 0% 98%) !important;
}

/* Force color scheme */
.chat-light-wrapper {
color-scheme: light !important;
Expand Down
2 changes: 1 addition & 1 deletion apps/sim/app/chat/components/input/input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export const ChatInput: React.FC<{
<VoiceInput onVoiceStart={handleVoiceStart} disabled={isStreaming} large={true} />
</div>
</TooltipTrigger>
<TooltipContent side='top' className='border border-gray-200 bg-white text-gray-900'>
<TooltipContent side='top'>
<p>Start voice conversation</p>
</TooltipContent>
</Tooltip>
Expand Down
17 changes: 5 additions & 12 deletions apps/sim/app/chat/components/message/message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import { memo, useMemo, useState } from 'react'
import { Check, Copy } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
import MarkdownRenderer from './components/markdown-renderer'

Expand Down Expand Up @@ -80,10 +79,8 @@ export const ClientChatMessage = memo(
<TooltipProvider>
<Tooltip delayDuration={300}>
<TooltipTrigger asChild>
<Button
variant='ghost'
size='sm'
className='flex items-center gap-1.5 px-2 py-1'
<button
className='text-muted-foreground transition-colors hover:bg-muted'
Comment on lines +82 to +83
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Replacing Button component with native button removes accessibility features like focus management and consistent styling from the design system

onClick={() => {
const contentToCopy =
typeof cleanTextContent === 'string'
Expand All @@ -95,15 +92,11 @@ export const ClientChatMessage = memo(
}}
>
{isCopied ? (
<>
<Check className='h-3.5 w-3.5 text-green-500' />
</>
<Check className='h-3 w-3' strokeWidth={2} />
) : (
<>
<Copy className='h-3.5 w-3.5 text-muted-foreground' />
</>
<Copy className='h-3 w-3' strokeWidth={2} />
)}
</Button>
</button>
</TooltipTrigger>
<TooltipContent side='top' align='center' sideOffset={5}>
{isCopied ? 'Copied!' : 'Copy to clipboard'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ interface WorkspacePermissionsContextType {
permissionsLoading: boolean
permissionsError: string | null
updatePermissions: (newPermissions: WorkspacePermissions) => void
refetchPermissions: () => Promise<void>

// Computed user permissions (connection-aware)
userPermissions: WorkspaceUserPermissions & { isOfflineMode?: boolean }
Expand All @@ -32,6 +33,7 @@ const WorkspacePermissionsContext = createContext<WorkspacePermissionsContextTyp
permissionsLoading: false,
permissionsError: null,
updatePermissions: () => {},
refetchPermissions: async () => {},
userPermissions: {
canRead: false,
canEdit: false,
Expand Down Expand Up @@ -74,6 +76,7 @@ export function WorkspacePermissionsProvider({ children }: WorkspacePermissionsP
loading: permissionsLoading,
error: permissionsError,
updatePermissions,
refetch: refetchPermissions,
} = useWorkspacePermissions(workspaceId)

// Get base user permissions from workspace permissions
Expand Down Expand Up @@ -113,10 +116,18 @@ export function WorkspacePermissionsProvider({ children }: WorkspacePermissionsP
permissionsLoading,
permissionsError,
updatePermissions,
refetchPermissions,
userPermissions,
setOfflineMode: setIsOfflineMode,
}),
[workspacePermissions, permissionsLoading, permissionsError, updatePermissions, userPermissions]
[
workspacePermissions,
permissionsLoading,
permissionsError,
updatePermissions,
refetchPermissions,
userPermissions,
]
)

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export function SuccessView({ deployedUrl, existingChat, onDelete, onUpdate }: S
href={deployedUrl}
target='_blank'
rel='noopener noreferrer'
className='flex h-10 flex-1 items-center break-all rounded-l-md border border-r-0 p-2 font-medium text-primary text-sm'
className='flex h-10 flex-1 items-center break-all rounded-l-md border border-r-0 p-2 font-medium text-foreground text-sm'
>
{subdomainPart}
</a>
Expand All @@ -67,7 +67,7 @@ export function SuccessView({ deployedUrl, existingChat, onDelete, onUpdate }: S
href={deployedUrl}
target='_blank'
rel='noopener noreferrer'
className='text-primary hover:underline'
className='text-foreground hover:underline'
>
this URL
</a>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ export function WandPromptBar({
variant='ghost'
size='icon'
onClick={() => onSubmit(promptValue)}
className='h-8 w-8 rounded-full text-primary hover:bg-primary/10 hover:text-primary'
className='h-8 w-8 rounded-full text-muted-foreground hover:bg-primary/10 hover:text-foreground'
disabled={isLoading || isStreaming || !promptValue.trim()}
>
<SendIcon className='h-4 w-4' />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { highlight, languages } from 'prismjs'
import 'prismjs/components/prism-javascript'
import 'prismjs/components/prism-json'
import 'prismjs/themes/prism.css'

import { Wand2 } from 'lucide-react'
import Editor from 'react-simple-code-editor'
import { cn } from '@/lib/utils'

Expand All @@ -19,6 +19,9 @@ interface CodeEditorProps {
onKeyDown?: (e: React.KeyboardEvent) => void
disabled?: boolean
schemaParameters?: Array<{ name: string; type: string; description: string; required: boolean }>
showWandButton?: boolean
onWandClick?: () => void
wandButtonDisabled?: boolean
}

export function CodeEditor({
Expand All @@ -32,6 +35,9 @@ export function CodeEditor({
onKeyDown,
disabled = false,
schemaParameters = [],
showWandButton = false,
onWandClick,
wandButtonDisabled = false,
}: CodeEditorProps) {
const [code, setCode] = useState(value)
const [visualLineHeights, setVisualLineHeights] = useState<number[]>([])
Expand Down Expand Up @@ -206,7 +212,23 @@ export function CodeEditor({
className
)}
>
{code.split('\n').length > 5 && (
{showWandButton && onWandClick && (
<button
onClick={onWandClick}
disabled={wandButtonDisabled}
className={cn(
'absolute top-2 right-2 z-10 flex h-8 w-8 items-center justify-center rounded-full border border-transparent bg-muted/80 p-0 text-foreground shadow-sm transition-all duration-200',
'hover:border-primary/20 hover:bg-muted hover:text-foreground hover:shadow',
'opacity-0 transition-opacity group-hover:opacity-100',
wandButtonDisabled && 'cursor-not-allowed opacity-50'
)}
aria-label='Generate with AI'
>
<Wand2 className='h-4 w-4' />
</button>
)}

{!showWandButton && code.split('\n').length > 5 && (
<button
onClick={() => setIsCollapsed(!isCollapsed)}
className={cn(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useEffect, useMemo, useRef, useState } from 'react'
import { Code, FileJson, Trash2, Wand2, X } from 'lucide-react'
import { Code, FileJson, Trash2, X } from 'lucide-react'
import { useParams } from 'next/navigation'
import {
AlertDialog,
Expand Down Expand Up @@ -934,25 +934,6 @@ try {
<Label htmlFor='json-schema' className='font-medium'>
JSON Schema
</Label>
<Button
variant='ghost'
size='icon'
className='h-5 w-5 rounded-full border border-transparent bg-muted/80 p-0 text-muted-foreground shadow-sm transition-all duration-200 hover:border-primary/20 hover:bg-muted hover:text-primary hover:shadow'
onClick={() => {
logger.debug('Schema AI button clicked')
logger.debug(
'showPromptInline function exists:',
typeof schemaGeneration.showPromptInline === 'function'
)
schemaGeneration.isPromptVisible
? schemaGeneration.hidePromptInline()
: schemaGeneration.showPromptInline()
}}
disabled={schemaGeneration.isLoading || schemaGeneration.isStreaming}
aria-label='Generate schema with AI'
>
<Wand2 className='h-3 w-3' />
</Button>
</div>
{schemaError &&
!schemaGeneration.isStreaming && ( // Hide schema error while streaming
Expand All @@ -963,6 +944,18 @@ try {
value={jsonSchema}
onChange={handleJsonSchemaChange}
language='json'
showWandButton={true}
onWandClick={() => {
logger.debug('Schema AI button clicked')
logger.debug(
'showPromptInline function exists:',
typeof schemaGeneration.showPromptInline === 'function'
)
schemaGeneration.isPromptVisible
? schemaGeneration.hidePromptInline()
: schemaGeneration.showPromptInline()
}}
wandButtonDisabled={schemaGeneration.isLoading || schemaGeneration.isStreaming}
placeholder={`{
"type": "function",
"function": {
Expand Down Expand Up @@ -1004,25 +997,6 @@ try {
<Label htmlFor='function-code' className='font-medium'>
Code (optional)
</Label>
<Button
variant='ghost'
size='icon'
className='h-5 w-5 rounded-full border border-transparent bg-muted/80 p-0 text-muted-foreground shadow-sm transition-all duration-200 hover:border-primary/20 hover:bg-muted hover:text-primary hover:shadow'
onClick={() => {
logger.debug('Code AI button clicked')
logger.debug(
'showPromptInline function exists:',
typeof codeGeneration.showPromptInline === 'function'
)
codeGeneration.isPromptVisible
? codeGeneration.hidePromptInline()
: codeGeneration.showPromptInline()
}}
disabled={codeGeneration.isLoading || codeGeneration.isStreaming}
aria-label='Generate code with AI'
>
<Wand2 className='h-3 w-3' />
</Button>
</div>
{codeError &&
!codeGeneration.isStreaming && ( // Hide code error while streaming
Expand Down Expand Up @@ -1050,6 +1024,18 @@ try {
value={functionCode}
onChange={handleFunctionCodeChange}
language='javascript'
showWandButton={true}
onWandClick={() => {
logger.debug('Code AI button clicked')
logger.debug(
'showPromptInline function exists:',
typeof codeGeneration.showPromptInline === 'function'
)
codeGeneration.isPromptVisible
? codeGeneration.hidePromptInline()
: codeGeneration.showPromptInline()
}}
wandButtonDisabled={codeGeneration.isLoading || codeGeneration.isStreaming}
placeholder={
'// This code will be executed when the tool is called. You can use environment variables with {{VARIABLE_NAME}}.'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1415,7 +1415,7 @@ export function ToolInput({
</Toggle>
</TooltipTrigger>
<TooltipContent className='max-w-[280px] p-2' side='top'>
<p className='text-muted-foreground text-xs'>
<p className='text-xs'>
Control how the model uses this tool in its response.
{tool.usageControl === 'auto' && (
<span>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { cn } from '@/lib/utils'
import { getDocumentIcon } from '@/app/workspace/[workspaceId]/knowledge/components/icons/document-icons'

interface Document {
id: string
name: string
tagValue: string
}

interface DocumentListProps {
documents: Document[]
totalCount: number
maxHeight?: 'max-h-32' | 'max-h-80'
showMoreText?: boolean
}

export function DocumentList({
documents,
totalCount,
maxHeight = 'max-h-32',
showMoreText = true,
}: DocumentListProps) {
const displayLimit = 5
const hasMore = totalCount > displayLimit

return (
<div className='rounded-md border border-border bg-background'>
<div className={cn(maxHeight, 'overflow-y-auto')}>
{documents.slice(0, displayLimit).map((doc) => {
const DocumentIcon = getDocumentIcon('', doc.name)
return (
<div
key={doc.id}
className='flex items-center gap-3 border-border/50 border-b p-3 transition-colors last:border-b-0 hover:bg-muted/30'
>
<DocumentIcon className='h-4 w-4 flex-shrink-0' />
<div className='min-w-0 flex-1 overflow-hidden'>
<div className='truncate font-medium text-sm' style={{ maxWidth: '300px' }}>
{doc.name}
Comment on lines +38 to +39
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Consider using Tailwind's max-w-[300px] instead of inline styles for consistency with the project's styling approach

Suggested change
<div className='truncate font-medium text-sm' style={{ maxWidth: '300px' }}>
{doc.name}
<div className='truncate font-medium text-sm max-w-[300px]'>
{doc.name}

</div>
{doc.tagValue && (
<div className='mt-1 text-muted-foreground text-xs'>
Tag value: <span className='font-medium'>{doc.tagValue}</span>
</div>
)}
</div>
</div>
)
})}
{hasMore && showMoreText && (
<div className='flex items-center gap-3 p-3 text-muted-foreground text-sm'>
<div className='h-4 w-4' />
<div className='font-medium'>and {totalCount - displayLimit} more documents...</div>
</div>
)}
</div>
</div>
)
}
Loading