InlineCitation
A source-reference chip that sits inside prose and emits rather than navigating.
InlineCitation
Basic Usage
Inline Citation
The chip is typeset with the text around it: 18px tall, mono face, nudged up a pixel so its cap height lines up with the prose instead of sitting on the baseline.
Loading demo...
Citations in a Streaming Answer
The citation lands when the prose reaches it, which is exactly what the pop-in entrance is for. The whole sequence is orchestrated by the demo; the component only ever renders one chip.
Streaming answer
Word-by-word reveal, an inline citation, stacked sources and a follow-up list.
Loading demo...
API
Props
| Name | Type | Default | Description |
|---|---|---|---|
source | AiSourceItem | — | The reference, shaped { id, url, title?, favicon? }. Required. |
label | string | — | Chip text. Falls back to source.title, then the hostname of url with www. stripped. |
appear | boolean | true | Plays the entrance pop. Set false when re-rendering a settled answer so a paragraph of citations does not re-pop. |
When url cannot be parsed by URL, the fallback chain ends at the raw url string rather than rendering an empty chip.
Events
| Name | Payload | Description |
|---|---|---|
open | (source: AiSourceItem) | Emitted on click. The default navigation is prevented; opening is the host's call. |
Slots
| Name | Scope | Description |
|---|---|---|
default | { source, label } | Replaces the chip text, rich content included. |
icon | { source } | Replaces the leading favicon — a hand-drawn category mark, for instance. |
Interaction Contract
- The link never navigates on its own. It renders a real
<a href>, but a click callspreventDefault()and emitsopen. This is mandatory inside an Electron renderer — walking the whole app away is the last thing a citation in body text should do. - The
hrefstays in the DOM, so the browser's own "open in new tab" and "copy link address" menus keep working. - A favicon that fails to load is recorded and stops rendering; the chip degrades to text rather than holding a broken-image placeholder.
- The icon carries
alt=""andaria-hidden; the accessible name comes from the chip text. - The chip sits in the text flow with
vertical-align: middleplus a 1px lift. Line height belongs to the surrounding paragraph — the component sets none of its own. - The entrance plays once, on mount.
appearis a render-time decision; flipping it later does not replay anything.
Best Practices
- Listen for
open, or clicking a citation does nothing at all. - Keep it to two or three citations per paragraph. Chips are visually heavier than words, and a dense run reads as a list rather than a sentence.
- Leaving
labelempty is usually better: the hostname fallback tells the reader where a claim came from, and a custom label tends to hide that. - Use stable
source.idvalues in streaming surfaces. The failed-icon record is per instance, so stable data is what stops a bad favicon being retried as nodes are reused. - When you want the source list at the end of an answer rather than a reference inside it, reach for
TxSources. The two are complementary and often appear together.
Source
- Component source:
packages/tuffex/packages/components/src/inline-citation/src/TxInlineCitation.vue. - Types:
packages/tuffex/packages/components/src/inline-citation/src/types.ts. - Tested behaviour:
packages/tuffex/packages/components/src/inline-citation/__tests__/inline-citation.test.ts(7 cases) covers the hostname fallback andwww.stripping, thelabel/titleprecedence, the unparseable-URL fallback, click emittingopeninstead of navigating, the favicon disappearing after a load failure, andappeargating the entrance class. - Adapted from Beautiful UI (https://www.beautifului.dev), © 2026 Shane Levine, MIT.
查看源码
packages/tuffex/packages/components/src/inline-citation/index.ts