Sources list

The full set of sources behind an answer: behind one button, as cards or a scrolling row, as numbered footnotes, in a side panel, or as the log of what a research run read and used.

Loading preview…

Install

  1. 1

    Run this command in your Tailwind CSS project. It adds components/ai/sources-list-stack.tsx and installs its dependencies.

    $ npx shadcn@latest add https://gradientdeck.com/ai-components/r/sources-list-stack.json

Add citations and source cards to an AI answer →

Usage & API

Example

sources-list-stack.tsx
import { SourcesStack } from "@/components/ai/sources-list-stack"

<SourcesStack
  sources={[]}
  open={true}
  onOpenChange={() => {}}
/>

Props SourcesStack

PropType & descriptionRequired
sourcesSource[]Required
openbooleanRequired
onOpenChange(open: boolean) => voidRequired
previewnumberHow many favicons to show in the closed button.Optional

Dependencies

  • React
  • Tailwind CSS
  • motion
  • lucide-react
Implementation notes

Favicon stack exports SourcesStack with sources, open, onOpenChange, and preview, default 4. A source has title, domain, color, and an optional url. The closed control is a pill: overlapping letter marks, the count as {n} sources, and a chevron. Opening it shows a numbered list, at most 232px tall, with the title and, from the @md container size, the domain. If url is set the row is a link. open is controlled. The component does not remember it. The preview data is a four-day-week reading list, starting with autonomy.work, bbc.co.uk, and theguardian.com.

Choosing a layout

Use the stack when the answer is short and the sources are a disclosure: one button, then the titles. Use cards when a handful of pages should be visible without a click, with the rest behind +n more. Use the carousel when the row is wide and a marker in the answer should light the matching card. Use footnotes when the answer is a document with a reference list and someone may need to copy it. Use the side panel when the thread stays on screen and the sources open beside it. Use the research log when the reader cares which query found a page, and which pages were paywalled, duplicated, or too old.

Do not use this list as the only citation if the claim itself needs a marker. A pill, a superscript, a domain chip, or a quoted passage is Inline citation, and it can sit in the same answer as a list. Do not use the research log as a live chain of thought. Chain of thought's research trail shows searches and notes as they arrive, one action at a time. The log is the record after the run, with a duration string and filters. A single pasted URL, with a skeleton while its title loads, is Link preview.

Which of these keep their open state for me?

SourcesStack, SourceCarousel, SourcesPanel, and ResearchLog are controlled. You pass open, expanded, tab, or filter, and the matching change callback. SourceCards keeps the more/fewer toggle itself, and there is no prop for it. FootnotedAnswer keeps the copy menu and the flash itself. If a marker in the answer should open a particular source, use the panel's expanded index or the carousel's active number, both of which you set from outside.

What does a skipped page look like in the research log?

Set status to skipped and reason to paywalled, duplicate, or older than 2023. The row shows that reason, with a lock, a copy-off mark, or a clock. A cited row shows Cited and the ref number. A read row shows Read. The Skipped filter hides the other two, and a query group with no remaining rows is removed from the list. The header count always includes every source, because it is computed before the filter. duration is not calculated from those statuses. You pass the string.