Skip to content

Commit 14f6225

Browse files
committed
improvement(chat): restore sent-attachment filenames and align chip tokens
- Revert the sent-message attachments to main's styling: the icon-only tile dropped the filename, leaving no way to tell what was sent. - Radii onto the scale: --radius is 8px, so rounded-[10px] was off-system in both files. Outer surfaces use rounded-lg, the nested icon badge rounded-md. - Pill filename uses the named text-xs rather than an arbitrary text-[11px]. - The remove badge is opaque instead of a translucent scrim, so it reads the same over a light card and over a photo rather than compositing with each.
1 parent 2cde5db commit 14f6225

2 files changed

Lines changed: 14 additions & 39 deletions

File tree

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

Lines changed: 7 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,12 @@ import { cn } from '@sim/emcn'
22
import { getDocumentIcon } from '@/components/icons/document-icons'
33
import type { ChatMessageAttachment } from '@/app/workspace/[workspaceId]/home/types'
44

5-
/**
6-
* Tile geometry shared with the thumbnail branches so a mixed row stays uniform.
7-
*
8-
* The border is load-bearing, not decoration: this renders on both the home transcript
9-
* (`--bg`) and the workflow chat panel (`--surface-1`), and against the latter the fill
10-
* is only ~8/255 away in light mode. With an icon-only tile the surface *is* the
11-
* affordance, so it needs an edge — the same reason the user message bubble pairs
12-
* `--surface-5` with a border.
13-
*/
14-
const ATTACHMENT_TILE =
15-
'size-[56px] overflow-hidden rounded-[8px] border border-[var(--border)] bg-[var(--surface-5)]'
16-
17-
/**
18-
* A sent document shows only its type icon. The filename was already read in the
19-
* composer before sending, so repeating it here costs a wide pill in the transcript
20-
* for information the hover title still carries.
21-
*/
22-
function FileAttachmentTile(props: { mediaType: string; filename: string }) {
5+
function FileAttachmentPill(props: { mediaType: string; filename: string }) {
236
const Icon = getDocumentIcon(props.mediaType, props.filename)
247
return (
25-
<div
26-
title={props.filename}
27-
// The icon carries no accessible name on its own, so without these the tile is
28-
// announced as nothing at all — the filename used to be real text.
29-
role='img'
30-
aria-label={props.filename}
31-
className={cn(ATTACHMENT_TILE, 'flex items-center justify-center text-[var(--text-icon)]')}
32-
>
33-
<Icon className='size-[18px]' />
8+
<div className='flex max-w-[140px] items-center gap-[5px] rounded-lg bg-[var(--surface-5)] px-[6px] py-[3px]'>
9+
<Icon className='size-[14px] flex-shrink-0 text-[var(--text-icon)]' />
10+
<span className='truncate text-[var(--text-body)] text-xs'>{props.filename}</span>
3411
</div>
3512
)
3613
}
@@ -55,7 +32,7 @@ export function ChatMessageAttachments(props: {
5532
{attachments.map((att) => {
5633
if (!att.previewUrl) {
5734
return (
58-
<FileAttachmentTile key={att.id} mediaType={att.media_type} filename={att.filename} />
35+
<FileAttachmentPill key={att.id} mediaType={att.media_type} filename={att.filename} />
5936
)
6037
}
6138
const isVideo = att.media_type.startsWith('video/')
@@ -64,10 +41,7 @@ export function ChatMessageAttachments(props: {
6441
return (
6542
<div
6643
key={att.id}
67-
title={att.filename}
68-
role='img'
69-
aria-label={att.filename}
70-
className={cn(ATTACHMENT_TILE, 'relative')}
44+
className='relative size-[56px] overflow-hidden rounded-lg bg-[var(--surface-5)]'
7145
>
7246
<div className='absolute inset-0 flex items-center justify-center text-[var(--text-icon)]'>
7347
<Icon className='size-[18px]' />
@@ -83,7 +57,7 @@ export function ChatMessageAttachments(props: {
8357
)
8458
}
8559
return (
86-
<div key={att.id} className={ATTACHMENT_TILE} title={att.filename}>
60+
<div key={att.id} className='size-[56px] overflow-hidden rounded-lg'>
8761
<img src={att.previewUrl} alt={att.filename} className='size-full object-cover' />
8862
</div>
8963
)

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

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import type { AttachedFile } from '@/app/workspace/[workspaceId]/w/[workflowId]/
1818
* hover steps further away in the direction each theme reads as "raised".
1919
*/
2020
const CHIP_SURFACE =
21-
'relative cursor-pointer rounded-[10px] border border-[var(--border)] bg-[var(--surface-5)] transition-colors hover-hover:bg-[var(--surface-active)] dark:hover-hover:bg-[var(--surface-6)]'
21+
'relative cursor-pointer rounded-lg border border-[var(--border)] bg-[var(--surface-5)] transition-colors hover-hover:bg-[var(--surface-active)] dark:hover-hover:bg-[var(--surface-6)]'
2222

2323
/** Height lives on the wrapper so both shapes are the same size by construction. */
2424
const CHIP_HEIGHT = 'h-[48px]'
@@ -113,7 +113,7 @@ const AttachedFileChip = React.memo(function AttachedFileChip({
113113
{/* Steps again on hover: the chip's own hover fill closes to within
114114
7/255 of this badge in light mode, which would erase it during the
115115
one interaction where it is being looked at. */}
116-
<span className='flex size-[32px] shrink-0 items-center justify-center rounded-[8px] bg-[var(--surface-6)] text-[var(--text-icon)] transition-colors group-hover:bg-[var(--surface-7)] dark:bg-[var(--surface-3)] dark:group-hover:bg-[var(--surface-3)]'>
116+
<span className='flex size-[32px] shrink-0 items-center justify-center rounded-md bg-[var(--surface-6)] text-[var(--text-icon)] transition-colors group-hover:bg-[var(--surface-7)] dark:bg-[var(--surface-3)] dark:group-hover:bg-[var(--surface-3)]'>
117117
<Icon className='size-[16px]' />
118118
</span>
119119
<span className='flex min-w-0 flex-col items-start'>
@@ -147,10 +147,11 @@ const AttachedFileChip = React.memo(function AttachedFileChip({
147147
onRemoveFile(file.id)
148148
}}
149149
aria-label={`Remove ${file.name}`}
150-
// Sits inside the chip's top-right corner. A fixed dark scrim rather than a
151-
// surface token: it overlays arbitrary photo content on the thumbnail shape,
152-
// where no theme token can guarantee contrast.
153-
className='absolute top-[2px] right-[2px] flex size-[16px] items-center justify-center rounded-full bg-black/60 text-white opacity-0 transition-opacity group-hover:opacity-100'
150+
// Opaque, not a translucent scrim: a semi-transparent fill composites with
151+
// whatever sits under it, so the same badge reads differently over a light
152+
// card than over a photo. An opaque surface plus a border keeps the glyph
153+
// contrast fixed and gives the badge an edge against any thumbnail.
154+
className='absolute top-[2px] right-[2px] flex size-[16px] items-center justify-center rounded-full border border-[var(--border)] bg-[var(--surface-1)] text-[var(--text-body)] opacity-0 transition-opacity group-hover:opacity-100'
154155
>
155156
<X className='size-[9px]' />
156157
</button>

0 commit comments

Comments
 (0)