Skip to main content
The main component for rendering AI-generated content. Automatically detects and renders artifacts including code blocks, forms, social previews, images, videos, and more.

Import

import { ArtifactuseAgentMessage } from 'artifactuse/vue'

Usage

<template>
  <ArtifactuseAgentMessage 
    :content="message.content"
    :message-id="message.id"
    :typing="isStreaming"
    :is-last-message="isLastMessage"
    @artifact-detected="onDetected"
    @artifact-open="onOpen"
    @form-submit="onFormSubmit"
    @form-cancel="onFormCancel"
    @form-button-click="onFormButtonClick"
    @social-copy="onSocialCopy"
    @media-open="onMediaOpen"
  />
</template>

Props

PropTypeDefaultDescription
contentstringRequiredRaw message content from AI (Markdown, code blocks, JSON artifacts)
messageIdstringRequiredUnique identifier for the message
typingbooleanfalseShow typing indicator (use while streaming)
inlineCardsbooleantrueShow clickable cards for panel artifacts inline
isLastMessagebooleanfalseWhether this is the last message in the conversation. Keeps forms active after page reload.

Events

EventPayloadDescription
artifact-detectedArtifact[]Fired when artifacts are detected in content
artifact-openArtifactFired when user clicks an artifact card to open panel
form-submit{ formId, action, values, timestamp }Fired when an inline form is submitted
form-cancel{ formId, action, buttonName, timestamp }Fired when an inline form is cancelled
form-button-click{ formId, action, buttonName, buttonLabel, values, timestamp }Fired when a custom button is clicked
social-copy{ platform, text }Fired when social preview text is copied
media-open{ type, src, alt, caption }Fired when image/PDF is opened in lightbox viewer
Event names use kebab-case in Vue (@form-submit) and camelCase in React (onFormSubmit). Svelte uses kebab-case with on: prefix (on:form-submit).

Artifact Rendering

The component automatically renders different artifact types:
Artifact TypeRendering
code (HTML, React, Vue, etc.)Clickable card → Opens in Panel
form with display: "inline"Inline form directly in message
form with display: "panel"Clickable card → Opens in Panel
socialInline social media preview
ImagesInline with lightbox on click
VideosInline embed (YouTube, Vimeo, etc.)
Other embedsInline (maps, documents, etc.)

Form Collapse Behavior

Inline forms automatically collapse after user interaction to prevent duplicate submissions and keep the chat clean.

Form States

StateDescriptionVisual
activeInteractive, user can fill and submitFull form with fields
submittedUser clicked submit or action buttonCollapsed with ✓ checkmark
cancelledUser clicked cancelCollapsed with ✗ icon
inactiveHistorical form (page refresh)Collapsed with — dash

Behavior Rules

  • Current session: Forms stay active until user interacts
  • After submit/cancel/custom action: Form collapses immediately
  • After page refresh:
    • Last message forms stay active (via isLastMessage prop)
    • Older message forms collapse as inactive
  • Reset action: Form stays active (doesn’t collapse)

Example with isLastMessage

<template>
  <ArtifactuseAgentMessage 
    v-for="(msg, index) in messages"
    :key="msg.id"
    :content="msg.content"
    :message-id="msg.id"
    :is-last-message="index === messages.length - 1"
    @form-submit="handleFormSubmit"
  />
</template>

Media Lightbox

Images and PDFs automatically open in a fullscreen lightbox viewer when clicked. The viewer supports:
  • Zoom - Click image or zoom button to toggle zoom
  • Download - Download the original file
  • Keyboard - Press Escape to close
  • Click outside - Click overlay to close
<ArtifactuseAgentMessage 
  :content="content"
  :message-id="id"
  @media-open="({ type, src }) => console.log('Opened:', type, src)"
/>

Typing Indicator

Show a typing indicator while streaming AI responses:
<ArtifactuseAgentMessage 
  :content="partialContent"
  :message-id="id"
  :typing="isStreaming"
/>
The typing indicator displays animated loading bars that disappear when typing becomes false.

Example: Full Integration

<template>
  <div class="chat">
    <ArtifactuseAgentMessage 
      v-for="(msg, index) in messages"
      :key="msg.id"
      :content="msg.content"
      :message-id="msg.id"
      :typing="msg.isStreaming"
      :is-last-message="index === messages.length - 1"
      @form-submit="handleFormSubmit"
      @form-cancel="handleFormCancel"
      @form-button-click="handleFormButtonClick"
      @social-copy="handleSocialCopy"
      @media-open="handleMediaOpen"
    />
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { ArtifactuseAgentMessage } from 'artifactuse/vue'

const messages = ref([])

function handleFormSubmit({ formId, values }) {
  // Send form data back to AI
  sendToAI(`User submitted form: ${JSON.stringify(values)}`)
}

function handleFormCancel({ formId }) {
  // User cancelled the form
  console.log('Form cancelled:', formId)
}

function handleFormButtonClick({ formId, action, buttonName, values }) {
  // Handle custom button actions
  console.log('Button clicked:', buttonName, action)
}

function handleSocialCopy({ platform, text }) {
  // Track analytics
  analytics.track('social_copy', { platform })
}

function handleMediaOpen({ type, src }) {
  // Track media views
  analytics.track('media_view', { type, src })
}
</script>