AI Elements
Sources
Displays the links the agent used for a reply.
Sources is a line that lists the links the agent used for a reply. It says how many there are, like "Used 3 sources", and opens into a link for each one.
Sources is built with UiTrace with a UiTraceCollapsible for the list.
Installation
Sources is built with the Trace component.
Usage
<template>
<UiTrace>
<UiTraceCollapsible>
<UiTraceCollapsibleTrigger>
<UiTraceLine>
<UiTraceIcon>
<UiIcon name="lucide:globe" />
</UiTraceIcon>
<UiTraceTitle>Used {{ sources.length }} sources</UiTraceTitle>
</UiTraceLine>
</UiTraceCollapsibleTrigger>
<UiTraceCollapsibleContent>
<UiTrace>
<a
v-for="source in sources"
:key="source.url"
:href="source.url"
target="_blank"
rel="noreferrer"
>
<UiTraceLine>
<UiTraceIcon>
<UiIcon name="lucide:globe" />
</UiTraceIcon>
<UiTraceTitle>
{{ source.title ?? getHostname(source.url) }}
<span class="sr-only"> (opens in a new tab)</span>
</UiTraceTitle>
<UiTraceIcon>
<UiIcon name="lucide:arrow-up-right" />
</UiTraceIcon>
</UiTraceLine>
</a>
</UiTrace>
</UiTraceCollapsibleContent>
</UiTraceCollapsible>
</UiTrace>
</template>
<script lang="ts" setup>
function getHostname(url: string) {
return new URL(url).hostname;
}
</script>
AI SDK
Collect the source-url parts of a message and render them after the text. The agent can cite the same page more than once, so dedupe them by url.
const sources = computed(() =>
props.message.parts
.filter((part) => part.type === "source-url")
.filter((part, index, all) => all.findIndex((other) => other.url === part.url) === index)
);
title is optional on a source-url part. Fall back to the hostname of the URL.
Accessibility
Each source is a plain link inside the list.
- Links open in a new tab. Add
sr-onlytext, like "(opens in a new tab)", so screen readers announce it. - The arrow icon is decorative. The title is the name of the link.
- The count in the trigger, like "Used 3 sources", tells the person what opens before they open it.
API Reference
See Trace.