Mischief

15 / Agent UI

Inline Citations

Numbered markers placed inside generated text, each linking to its entry in a source list underneath.

Live previewSource

Postgres treats nulls as distinct inside a unique indexSource 1: PostgreSQL — Unique indexes, so the constraint itself will not reject the empty rows. The failure comes from the ordering in the migrationSource 2: 0004_add_email_index.sql, where the index is created before anything backfills the column.

Sources

  1. 1PostgreSQL — Unique indexes(opens in a new tab)Null values are not considered equal by a unique constraint.
  2. 20004_add_email_index.sqlCreates the index before the backfill statement runs.

Installation

Copy the source into your project, or keep it behind a package.

Copy the component into your project and make it yours.

Usage

const sources = [
  { id: "docs", title: "Agent UI docs", url: "https://example.com/docs" },
]

export function Answer() {
  return (
    <InlineCitations sources={sources}>
      <p>
        Streaming is supported<Citation id="docs" />.
      </p>
    </InlineCitations>
  )
}

API

sourcesCitationSource[]Id, title, and optional url and snippet. Order sets the numbering.
childrenReactNodeThe text, with Citation markers placed inline.
showSourceListbooleanRenders the numbered list below the text. Defaults to true.
sourceListLabelReactNodeHeading for the source list.
id (Citation)stringWhich source this marker points at.

Accessibility

Markers are real anchors to their list entry, so they work without hover or a pointer. Each one has an accessible name giving the number and the source title, and the visible digit is hidden from assistive technology to avoid reading it twice. A marker whose id is not in sources renders nothing rather than a dead link. External source links say that they open in a new tab.

Dependencies

lucide-react