ClickorKeyboard shortcut Alt + L

Dragto resize

Nord Design System SearchDeveloperDeveloperGetting startedUsing Web ComponentsWebfontsCDNLocalizationCSS Framework Legacy ESLint PluginWorking with AIFAQDesignDesignGetting startedFoundationsAccessibilityColor SystemColor UtilitiesPrinciplesFigma ToolkitGridIconographyNamingNordhealth BrandTypographyThemesBrand assetsToolsComponentsComponentsAccordion New Aside New Autocomplete New AvatarBadgeBannerButtonButton GroupCalendarCard Updated Chart New Chat New Chat AttachmentChat ComposerChat Composer DrawerChat Composer InputChat Dictation ButtonChat Layout Scroll ButtonChat MessageChat Message BubbleChat Message ListChat Message MetadataChat Send ButtonChat System MessageChat TokenChat Tokenized TextChat Tool CallsCheckboxCollapsible New Combobox New Command MenuData Table New Date PickerDate Range Picker New DividerDrawer Updated DropdownEmpty StateField New FieldsetFilter Bar New FooterHeaderIconInputInput Group New Item New Kbd New LayoutMessageMeter New Modal Updated NavigationNotificationNumber Field New Otp Field New Outline New Overflow List New Pagination New PopoutProgressProgress BarQrcodeRadioRangeResizable New Rich Text Editor New Scroll Area New Segmented ControlSelectSkeletonSpinnerStackTabTableTagTextareaTime Picker New Timestamp New ToastToggleTooltipTop BarTruncate New Visually HiddenDesign TokensDesign TokensTailwind CSSTailwind CSSBlocksBlocksTemplatesTemplatesIconsIconsPlaygroundPlaygroundLatest UpdatesLatest UpdatesChangelogChangelogMigration guidesMigration guides
GitHub

Clickto expandKeyboard shortcut Alt + L

Chat Attachment Alpha Light DOM & Tailwind

An image or file attached to a message, before and after sending.

This component is considered alpha. We're still finalising the API, so it may include a breaking change at any time — use it at your own risk.

Usage

Chat Attachment presents one attached image or file in the Chat family — in the composer while it is pending, and in the message log once it has been sent. The same markup works in both places.

import "@nordhealth/components/lib/ChatAttachment"

Composition

Presentation follows placement

A pending upload and a delivered one are read differently, so the element resolves its own presentation from where it sits:

  • Inside a Chat Composer or Chat Composer Drawer, an image is a compact thumbnail with the name beneath it.
  • Anywhere else, an image is a captioned card cropped to one ratio, so a thread mixing portrait and landscape uploads still reads as an even column.

Files are the same compact pill in both positions. Only images differ, which is why the two chat surfaces cannot drift apart.

src is what makes it an image

There is no kind to keep in sync. An attachment with a src renders as an image; without one there is nothing to preview, so it renders as a file. This makes contradictory combinations impossible to express.

Removal

removable adds a localized remove action and is normally used only in the composer — a sent attachment is a record, not a pending change. Listen for the cancelable nord-attachment-remove event and update the application-owned collection; the element never removes itself or revokes object URLs.

<nord-chat-composer-drawer role="group" aria-label="Attachments">
  <nord-chat-attachment
    name="recovery-photo.jpg"
    src="/recovery-photo.jpg"
    removable
  ></nord-chat-attachment>
  <nord-chat-attachment name="care-plan.pdf" removable></nord-chat-attachment>
</nord-chat-composer-drawer>

Image loading

Images load eagerly by default. A message log is anchored to its newest message, so an image that resolves after that scroll shifts the content the reader is looking at. Set loading="lazy" for long histories where most attachments start far outside the viewport.

Examples

Delivered attachments

Attachments sit alongside the message text inside the bubble:

<nord-chat-message sender="user" name="Einar Veselý">
  <nord-chat-message-bubble>
    <span class="n:flex n:flex-col n:gap-xs">
      <nord-chat-attachment
        name="recovery-photo.jpg"
        src="/recovery-photo.jpg"
      ></nord-chat-attachment>
      <span>I’ve also attached a photo from today.</span>
    </span>
  </nord-chat-message-bubble>
</nord-chat-message>

Pending attachments in the composer

Keep image previews and files in two sibling containers so the scrollable preview strip and the wrapping file pills stay independent:

Chat Composer Token is reserved for atomic inline values inside Composer Input or Tokenized Text. Do not use it as a pending attachment.

Accessibility

Use alt when the image communicates something the name does not. Otherwise leave it empty: the visible name already identifies the attachment, and a duplicate makes screen readers announce the filename twice.

When a message or composer carries several attachments, wrap them in an element with role="group" and a label describing the count, so their relationship to the message is clear.

API reference

ChatAttachment

An image or file attached to a message, in the composer before sending and in the message log after. Files render as a compact pill in both places; images render as a small thumbnail in the composer and a captioned card in a message, because a pending upload and a delivered one are read differently. Presentation follows placement, so the same markup works in either position. removable adds the remove action; a sent attachment is a record, so it is normally left off in the message log.

<nord-chat-attachment></nord-chat-attachment>

Props

PropertyAttribute Description TypeDefault
namenameAttachment name. Shown to the reader and returned with removal intents.string''
srcsrcImage source. Its presence is what makes this an image: without one there is nothing to preview, so the attachment renders as a file.string | undefined
altaltAlternative text for a meaningful image. Empty by default, because the visible name already identifies the attachment and a duplicate would be announced twice.string''
loadingloadingImage loading strategy. Eager by default: a message log is anchored to its newest message, so an image resolving after that scroll shifts what the reader is looking at. Use lazy for long histories.'eager' | 'lazy''eager'
removableremovableAdds an accessible remove action. Consumers own actual removal.booleanfalse
removeLabelremove-labelOptional complete remove-action label. Defaults to a localized label.string | undefined
EventDetail TypeDescription
nord-attachment-removeChatAttachmentRemoveEventCancellable removal intent.

CSS Properties

CSS Custom Properties provide more fine grain control over component presentation. We advise utilizing existing properties on the component before using these.

PropertyDescriptionDefault
--n-chat-attachment-tile-inline-sizeComposer thumbnail width.5.5rem
--n-chat-attachment-tile-block-sizeComposer thumbnail height.4.5rem
--n-chat-attachment-card-inline-sizeMessage card maximum width.14rem
--n-chat-attachment-card-aspect-ratioMessage card crop ratio.4 / 3
Light DOM & Tailwind. This component renders in the light DOM, so you can style it directly with your own CSS or Tailwind utility classes — there is no shadow boundary, and its default styles are low specificity, so your utilities win.