---
title: "ChatAttachment"
description: "Display a file attached to a prompt or a chat message."
canonical_url: "https://ui.nuxt.com/docs/components/chat-attachment"
---
# ChatAttachment

> Display a file attached to a prompt or a chat message.

## Usage

The ChatAttachment component displays a file with its name and a description, next to an image preview or an icon.

> [!NOTE]
> 
> This component is automatically used by the [`ChatPrompt`](https://ui.nuxt.com/docs/components/chat-prompt#files) component to list the files bound with `v-model:files`.

### File

Use the `file` prop to display a `File`, such as one picked by the user. Its name, type and size are read from it and images are previewed through an object URL.

```vue
<script setup lang="ts">
defineProps<{
  file: File
}>()
</script>

<template>
  <UChatAttachment :file="file" />
</template>
```

### Name

Use the `name` and `type` props to display a file you only have the details of, like a file part of a message.

```vue
<template>
  <UChatAttachment name="quarterly-report.pdf" type="application/pdf" />
</template>
```

### Url

Use the `url` prop to preview an image. The image is displayed when `type` is an image media type, and its `name` is used as the alternative text.

```vue
<template>
  <UChatAttachment name="landscape.jpg" type="image/jpeg" url="https://picsum.photos/id/1015/200" />
</template>
```

> [!TIP]
> 
> Map a file part of a message to these props in the `#files` slot of [ChatMessage](https://ui.nuxt.com/docs/components/chat-message) or [ChatMessages](https://ui.nuxt.com/docs/components/chat-messages).
> 
> ```vue
> <template>
>   <UChatMessages :messages="messages" :status="status">
>     <template #files="{ parts }">
>       <UChatAttachment
>         v-for="(part, index) in parts"
>         :key="index"
>         :name="part.filename"
>         :type="part.mediaType"
>         :url="part.url"
>       />
>     </template>
>   </UChatMessages>
> </template>
> ```

### Description

Use the `description` prop to set the text under the name. Defaults to the file extension and, with the `file` prop, its size.

```vue
<template>
  <UChatAttachment description="Uploaded 2 minutes ago" name="quarterly-report.pdf" type="application/pdf" />
</template>
```

### Status

Use the `status` prop to show that the file is `uploading` or failed to upload with `error`. Defaults to `idle`.

> [!NOTE]
> 
> While `uploading`, the name shimmers, an image is dimmed and a file icon turns into a spinner. Pass the progress or, with `error`, the reason to the `description` prop.

```vue
<template>
  <UChatAttachment status="uploading" name="quarterly-report.pdf" type="application/pdf" />
</template>
```

### Orientation

Use the `orientation` prop to change the layout of the attachment. Defaults to `horizontal`, `vertical` gives an image a large preview.

```vue
<template>
  <UChatAttachment orientation="vertical" name="landscape.jpg" type="image/jpeg" url="https://picsum.photos/id/1015/200" />
</template>
```

### Variant

Use the `variant` prop to change the style of the attachment. Defaults to `card`, `thumbnail` only displays the image or file icon with the remove button on its corner and the name available to screen readers. Combine it with the `size` prop for a larger preview, from `40px` with `xs` to `120px` with `xl`.

```vue
<template>
  <UChatAttachment variant="thumbnail" name="landscape.jpg" type="image/jpeg" url="https://picsum.photos/id/1015/200" removable />
</template>
```

> [!NOTE]
> 
> The `orientation` prop only applies to the `card` variant.

### Size

Use the `size` prop to change the size of the attachment. Defaults to `md`.

```vue
<template>
  <UChatAttachment size="sm" name="quarterly-report.pdf" type="application/pdf" />
</template>
```

### Removable

Use the `removable` prop to display a button that emits a `remove` event.

```vue
<template>
  <UChatAttachment removable name="quarterly-report.pdf" type="application/pdf" />
</template>
```

### Icon

Use the `icon` prop to customize the [Icon](https://ui.nuxt.com/docs/components/icon) displayed for files that are not images. Defaults to `i-lucide-file`.

```vue
<template>
  <UChatAttachment icon="i-lucide-file-text" name="quarterly-report.pdf" type="application/pdf" />
</template>
```

**Nuxt:**

> [!TIP]
> See: /docs/getting-started/integrations/icons/nuxt#theme
> 
> You can customize this icon globally in your `app.config.ts` under `ui.icons.file` key.

**Vue:**

> [!TIP]
> See: /docs/getting-started/integrations/icons/vue#theme
> 
> You can customize this icon globally in your `vite.config.ts` under `ui.icons.file` key.

## API

### Props

```ts
/**
 * Props for the ChatAttachment component
 */
interface ChatAttachmentProps {
  /**
   * The element or component this component should render as.
   * @default 'div'
   */
  as?: any;
  /**
   * The file to display, its `name`, `type` and size are read from it and images are previewed.
   */
  file?: File | undefined;
  /**
   * The name of the file.
   */
  name?: string | undefined;
  /**
   * The media type of the file, images are previewed.
   */
  type?: string | undefined;
  /**
   * The URL of the file, used to preview images.
   */
  url?: string | undefined;
  /**
   * The text displayed under the name. Defaults to the file extension and size.
   */
  description?: string | undefined;
  /**
   * The upload status of the file.
   * @default 'idle'
   */
  status?: "error" | "uploading" | "idle" | undefined;
  /**
   * @default 'md'
   */
  size?: "sm" | "md" | "lg" | "xs" | "xl" | undefined;
  /**
   * The orientation of the attachment, `vertical` gives an image a large preview.
   * @default 'horizontal'
   */
  orientation?: "horizontal" | "vertical" | undefined;
  /**
   * The style of the attachment, `thumbnail` only shows the preview with the remove button on its corner.
   * @default 'card'
   */
  variant?: "card" | "thumbnail" | undefined;
  /**
   * Display a button to remove the file.
   * @default false
   */
  removable?: boolean | undefined;
  /**
   * The icon displayed for files that are not images.
   * @default appConfig.ui.icons.file
   */
  icon?: any;
  /**
   * The icon displayed while the file uploads, over the image if any.
   * @default appConfig.ui.icons.loading
   */
  loadingIcon?: any;
  /**
   * The icon displayed when the upload fails, over the image if any.
   * @default appConfig.ui.icons.error
   */
  errorIcon?: any;
  /**
   * The icon of the remove button.
   * @default appConfig.ui.icons.close
   */
  removeIcon?: any;
  ui?: { root?: SlotClass; leading?: SlotClass; leadingIcon?: SlotClass; image?: SlotClass; wrapper?: SlotClass; name?: SlotClass; description?: SlotClass; remove?: SlotClass; } | undefined;
}
```

### Emits

```ts
/**
 * Emitted events for the ChatAttachment component
 */
interface ChatAttachmentEmits {
  remove: (payload: [event: MouseEvent]) => void;
}
```

## Theme

```ts [app.config.ts]
export default defineAppConfig({
  ui: {
    chatAttachment: {
      slots: {
        root: 'group/attachment relative flex min-w-0 max-w-full w-fit shrink-0',
        leading: 'relative flex items-center justify-center shrink-0 aspect-square overflow-hidden rounded-lg bg-elevated text-muted',
        leadingIcon: 'absolute shrink-0',
        image: 'size-full object-cover',
        wrapper: 'grid grid-cols-[minmax(0,1fr)_auto] items-center min-w-0 flex-1',
        name: 'block truncate font-medium text-highlighted',
        description: 'block truncate row-start-2 text-xs text-muted',
        remove: 'shrink-0'
      },
      variants: {
        size: {
          xs: {
            root: 'gap-1.5 p-1 rounded-lg text-xs data-[orientation=vertical]:w-20 data-[variant=thumbnail]:w-10',
            leading: 'w-7 rounded-md',
            leadingIcon: 'size-3.5',
            description: 'text-[10px]/3'
          },
          sm: {
            root: 'gap-2 p-1.5 text-xs data-[orientation=vertical]:w-24 data-[variant=thumbnail]:w-12',
            leading: 'w-8',
            leadingIcon: 'size-4'
          },
          md: {
            root: 'gap-2.5 p-2 text-sm data-[orientation=vertical]:w-30 data-[variant=thumbnail]:w-14',
            leading: 'w-10',
            leadingIcon: 'size-5',
            description: 'mt-0.5'
          },
          lg: {
            root: 'gap-3 p-2.5 text-sm data-[orientation=vertical]:w-36 data-[variant=thumbnail]:w-20',
            leading: 'w-12',
            leadingIcon: 'size-6',
            description: 'mt-0.5'
          },
          xl: {
            root: 'gap-3 p-3 text-base data-[orientation=vertical]:w-44 data-[variant=thumbnail]:w-30',
            leading: 'w-14 rounded-xl',
            leadingIcon: 'size-7',
            description: 'mt-0.5 text-sm'
          }
        },
        orientation: {
          horizontal: {
            root: 'items-center min-w-40 pe-2.5',
            remove: 'col-start-2 row-start-1 -my-1 ms-1'
          },
          vertical: {
            root: 'flex-col',
            leading: 'w-full',
            leadingIcon: 'size-6',
            wrapper: 'px-1',
            remove: 'absolute top-3 end-3 rounded-full bg-default/75 backdrop-blur-xs'
          }
        },
        variant: {
          card: {
            root: 'rounded-xl border border-default bg-default'
          },
          thumbnail: {
            root: 'p-0 min-w-0',
            leading: 'w-full outline -outline-offset-1 outline-default',
            wrapper: 'contents',
            name: 'sr-only',
            description: 'sr-only',
            remove: [
              'absolute -top-1.5 -end-1.5 m-0 p-0 rounded-full bg-inverted text-inverted hover:bg-inverted/90 active:bg-inverted/90 ring-2 ring-bg [@media(hover:hover)]:opacity-0 group-hover/attachment:opacity-100 group-focus-within/attachment:opacity-100',
              'transition-opacity ease-out'
            ]
          }
        },
        status: {
          idle: '',
          uploading: {
            leading: 'has-data-[slot=image]:text-highlighted',
            leadingIcon: 'animate-spin',
            image: 'opacity-50'
          },
          error: {
            root: 'border-error/30',
            leading: 'bg-error/10 text-error outline-error/30',
            image: 'opacity-50',
            description: 'text-error'
          }
        }
      },
      defaultVariants: {
        size: 'md',
        orientation: 'horizontal',
        status: 'idle',
        variant: 'card'
      }
    }
  }
})
```

## Changelog

See commit history for [component](https://github.com/nuxt/ui/commits/v4/src/runtime/components/ChatAttachment.vue) and [theme](https://github.com/nuxt/ui/commits/v4/src/theme/chat-attachment.ts).

---

- [GitHub](https://github.com/nuxt/ui/blob/v4/src/runtime/components/ChatAttachment.vue)


## Sitemap

See the full [sitemap](https://ui.nuxt.com/sitemap.md) for all pages.
