+ ${attachments.map((attachment) => this.__renderAttachment(attachment))}
+
+ `;
+ }
+
+ /**
+ * Renders a single attachment.
+ * @param {Object} attachment - The attachment object with name, url, and type properties
+ * @return {import('lit').TemplateResult}
+ * @private
+ */
+ __renderAttachment(attachment) {
+ const isImage = attachment.type && attachment.type.startsWith('image/');
+
+ if (isImage) {
+ return html`
+ ` is a Web Component for showing an ordered list of messages. The messages are rendered as
diff --git a/packages/message-list/src/vaadin-message-list.js b/packages/message-list/src/vaadin-message-list.js
index 239edb12d0b..e2753e04e86 100644
--- a/packages/message-list/src/vaadin-message-list.js
+++ b/packages/message-list/src/vaadin-message-list.js
@@ -92,6 +92,45 @@ class MessageList extends SlotStylesMixin(MessageListMixin(ElementMixin(Themable
${tag} :where(vaadin-markdown > :is(h1, h2, h3, h4, h5, h6, p, ul, ol):last-child) {
margin-bottom: 0;
}
+
+ ${tag} .vaadin-message-attachments {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 6px;
+ }
+
+ ${tag} .vaadin-message-attachment {
+ display: inline-flex;
+ align-items: center;
+ color: inherit;
+ }
+
+ ${tag} .vaadin-message-attachment-image img {
+ display: block;
+ max-width: 200px;
+ max-height: 150px;
+ }
+
+ ${tag} .vaadin-message-attachment-file {
+ gap: 6px;
+ }
+
+ ${tag} .vaadin-message-attachment-icon {
+ display: inline-block;
+ width: 1em;
+ height: 1em;
+ background: currentColor;
+ mask-image: url('data:image/svg+xml;utf8,');
+ mask-size: contain;
+ mask-repeat: no-repeat;
+ flex-shrink: 0;
+ }
+
+ ${tag} .vaadin-message-attachment-name {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
`,
];
}
diff --git a/packages/message-list/src/vaadin-message.js b/packages/message-list/src/vaadin-message.js
index ea993fd326c..51126c70868 100644
--- a/packages/message-list/src/vaadin-message.js
+++ b/packages/message-list/src/vaadin-message.js
@@ -23,6 +23,12 @@ import { MessageMixin } from './vaadin-message-mixin.js';
* user-img = "/static/img/avatar.jpg">There is no real ending. It's just the place where you stop the story.
* ```
*
+ * ### Slots
+ *
+ * Slot name | Description
+ * --------------|----------------
+ * `attachments` | Content to be displayed above the message text. Used for file and image attachments.
+ *
* ### Styling
*
* The following shadow DOM parts are available for styling:
@@ -70,6 +76,7 @@ class Message extends MessageMixin(ElementMixin(ThemableMixin(PolylitMixin(LumoI
${this.userName}
${this.time}
+
`;
diff --git a/packages/message-list/test/dom/__snapshots__/message.test.snap.js b/packages/message-list/test/dom/__snapshots__/message.test.snap.js
index 5694b873e8d..02a54a41729 100644
--- a/packages/message-list/test/dom/__snapshots__/message.test.snap.js
+++ b/packages/message-list/test/dom/__snapshots__/message.test.snap.js
@@ -11,6 +11,8 @@ snapshots["vaadin-message default"] =
+
+
@@ -30,6 +32,8 @@ snapshots["vaadin-message userName"] =
+
+
@@ -49,6 +53,8 @@ snapshots["vaadin-message time"] =
long ago
+
+
diff --git a/packages/message-list/test/typings/message-list.types.ts b/packages/message-list/test/typings/message-list.types.ts
index 6e7f414603f..98126efe1ef 100644
--- a/packages/message-list/test/typings/message-list.types.ts
+++ b/packages/message-list/test/typings/message-list.types.ts
@@ -3,7 +3,7 @@ import '../../vaadin-message-list.js';
import type { FocusMixinClass } from '@vaadin/a11y-base/src/focus-mixin.js';
import type { ElementMixinClass } from '@vaadin/component-base/src/element-mixin.js';
import type { ThemableMixinClass } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
-import type { MessageListItem } from '../../vaadin-message-list.js';
+import type { MessageListItem, MessageListItemAttachment } from '../../vaadin-message-list.js';
const assertType = (value: TExpected) => value;
@@ -24,6 +24,13 @@ assertType(item.userImg);
assertType(item.userColorIndex);
assertType(item.theme);
assertType(item.className);
+assertType(item.attachments);
+
+// Attachment properties
+const attachment: MessageListItemAttachment = item.attachments ? item.attachments[0] : {};
+assertType(attachment.name);
+assertType(attachment.url);
+assertType(attachment.type);
// Mixins
assertType(list);