From f66e7ed2c7cc97862fade4dc4fd03fb28dc939f5 Mon Sep 17 00:00:00 2001 From: Harshil Vasoya Date: Fri, 18 Sep 2026 13:22:46 +0530 Subject: [PATCH 1/2] chore: Enhance attachment ui --- .changeset/visible-attachment-metadata.md | 5 ++ .../trueforge-ui/src/atoms/AttachmentCard.tsx | 76 +++++++++++++++---- .../src/containers/AttachmentsContainer.tsx | 24 +++++- .../trueforge-ui/src/icons/IconRegistry.tsx | 6 ++ .../test/atoms/AttachmentCard.test.tsx | 27 ++++++- .../containers/AttachmentsContainer.test.tsx | 32 +++++++- .../containers/UserMessageContainer.test.tsx | 4 +- 7 files changed, 154 insertions(+), 20 deletions(-) create mode 100644 .changeset/visible-attachment-metadata.md diff --git a/.changeset/visible-attachment-metadata.md b/.changeset/visible-attachment-metadata.md new file mode 100644 index 000000000..a0d6689b1 --- /dev/null +++ b/.changeset/visible-attachment-metadata.md @@ -0,0 +1,5 @@ +--- +"@truefoundry/trueforge-ui": patch +--- + +Show file-type icons, filenames, and sizes for composer and sent message attachments. diff --git a/packages/trueforge-ui/src/atoms/AttachmentCard.tsx b/packages/trueforge-ui/src/atoms/AttachmentCard.tsx index 5ea2feec9..651446147 100644 --- a/packages/trueforge-ui/src/atoms/AttachmentCard.tsx +++ b/packages/trueforge-ui/src/atoms/AttachmentCard.tsx @@ -14,6 +14,7 @@ export type AttachmentCardSize = 'chip' | 'preview'; export type AttachmentCardProps = { name: string; contentType?: string; + sizeBytes?: number; previewSrc?: string; isImage?: boolean; size?: AttachmentCardSize; @@ -23,8 +24,35 @@ export type AttachmentCardProps = { className?: string; }; +const FILE_ICON_BY_EXTENSION: Record = { + pdf: 'file-text', + ppt: 'file-text', + pptx: 'file-text', + doc: 'file-text', + docx: 'file-text', + txt: 'file-text', + csv: 'file-spreadsheet', + xls: 'file-spreadsheet', + xlsx: 'file-spreadsheet', + json: 'file-code', +}; + +export function getAttachmentFileIconName(name: string): string { + const dotIndex = name.lastIndexOf('.'); + const extension = dotIndex > 0 && dotIndex < name.length - 1 ? name.slice(dotIndex + 1).toLowerCase() : undefined; + return extension == null ? 'file' : (FILE_ICON_BY_EXTENSION[extension] ?? 'file'); +} + +function formatFileSize(bytes: number): string { + if (bytes === 0) return '0 B'; + const megabytes = bytes / (1024 * 1024); + if (megabytes < 1) return `${(bytes / 1024).toFixed(2)} KB`; + return `${megabytes.toFixed(2)} MB`; +} + export function AttachmentCard({ name, + sizeBytes, previewSrc, isImage = false, size = 'chip', @@ -50,24 +78,46 @@ export function AttachmentCard({ ); } + const imageChip = isImage && previewSrc != null; + const fileIcon = getAttachmentFileIconName(name); + return (
- -
- - - {/* bg-none drops the default gradient (bg-image group), which bg-secondary-bg alone would not override. */} - - - - -
-
- {name} + {imageChip ? ( + <> +
+ + + + + + +
+ + ) : ( + <> + +
+ + {name} + + {sizeBytes != null ? ( + {formatFileSize(sizeBytes)} + ) : null} +
+ + )} {onRemove && (