Footnote

AI Answer With Citations for React

An AI answer that shows its work. It reads its sources, dealing a chip for each one, then writes the answer, and as each claim lands its source's number lifts out of the chip and drops in at the end of the sentence. Point at a sentence and its source lights up; point at a source and the sentences it backs light up, and resting on it opens the passage the answer leans on.

  • AI
  • Text
  • Hover

Uses motion, clsx, tailwind-merge

Open in ChatGPTOpen in Claude
speed45w/s
arc26px(replays the demo)
flightDuration0.45s(replays the demo)
flightBounce0.16(replays the demo)
<Footnote />

replays the demo when you let go.

Can we move our workspace to the EU region?

Yes. Workspaces on the Business and Enterprise plans can move to Frankfurt from Settings → Data residency. The move runs in a window you pick, and the workspace is read-only for about 20 minutes per 10 GB of files. Pages, files and search move with it; audit logs older than 90 days stay in the US until they expire. EU hosting has been generally available since version 5.2.

Take this demo to your coding agent.
Add this moment from KeyframeUI to our project and adapt it to our content.

Footnote: An AI answer that shows its work. It reads its sources, dealing a chip for each one, then writes the answer, and as each claim lands its source's number lifts out of the chip and drops in at the end of the sentence. Point at a sentence and its source lights up; point at a source and the sentences it backs light up, and resting on it opens the passage the answer leans on.
This demo, Help Center: A workspace app's help assistant answers a data-residency question from its docs, status page, trust center and changelog. A community thread it read but didn't cite sits last, with a monogram.

1. Install it:
   npx shadcn@latest add @keyframeui/footnote-demo
   (If the CLI can't find @keyframeui, use https://keyframeui.com/r/footnote-demo.json instead.)
   It adds the demo, components/footnote-demo.tsx, and the component, components/ui/footnote.tsx.

2. Make it ours: our copy, data, images and colors. Keep the structure the motion depends on. If we only need the effect, use <Footnote> on its own.

3. These props set its feel. Change them before you change the file:
   - speed (default 45): How fast the answer writes itself, in words a second.
   - arc (default 26): Pixels each source's number arcs up over a straight line as it flies to its claim.
   - flightDuration (default 0.45): Seconds a number takes to fly from its source's chip into the claim's marker.
   - flightBounce (default 0.16): How much a number overshoots its marker before it settles, from `0` (none) up.

4. Don't change, in components/ui/footnote.tsx:
   - Every word, marker and chip is in the markup from the start and only shown as the run reaches it, so playing never changes the card's height.
   - The run is planned up front in ms (`buildPlan`), and one timer jumps a clock kept outside React from event to event; off screen or in a hidden tab it stops and picks up where it was.
   - Writing never waits for the numbers. A flying number re-measures its marker every frame and hands off to it in the frame it lands, and a slower flight pushes the finish back to match.
   - A link holds for a moment between claims, so moving across lines doesn't flicker; a source opens after the hover intent and closes only once the pointer has left both chip and card.
   - Reduced motion, read only after hydration, shows the finished answer at once with no dealing, streaming or flights. Links and source cards still work, and cards fade without growing.
   Its timing is all in the TIMING block at the top of that file.

Docs: https://keyframeui.com/components/footnote.md

Installation

Add the component on its own with the CLI, or copy the file in by hand.

The CLI writes components/ui/footnote.tsx and installs motion, clsx and tailwind-merge. It needs the @keyframeui registry in components.json; add it once per project.

npx shadcn@latest add @keyframeui/footnote

Examples

Finished sections built with Footnote. Each one installs whole, with the component included.

Glass Over a Photo

A trip planner's answer on a frosted card over Lisbon at dusk, in a browser frame: where to stay for two nights on foot, with walking, review, weather and transit sources.

Lisbon's rooftops at dusk under a deep blue and orange sky
saunter.app/ask

Two nights in Lisbon in November: where should we stay to walk everywhere?

Stay in Baixa: it's the flat grid between the river and the hills, and most sights are within 20 minutes on foot. Alfama is prettier but steep, and with luggage the climb from the metro is the hard part. November is mild, around 17°C, but expect rain on about one day in three. Tram 28 is packed by 10am, so ride it early or walk the same route downhill.

Take this demo to your coding agent.
Add this moment from KeyframeUI to our project and adapt it to our content.

Footnote: An AI answer that shows its work. It reads its sources, dealing a chip for each one, then writes the answer, and as each claim lands its source's number lifts out of the chip and drops in at the end of the sentence. Point at a sentence and its source lights up; point at a source and the sentences it backs light up, and resting on it opens the passage the answer leans on.
This demo, Glass Over a Photo: A trip planner's answer on a frosted card over Lisbon at dusk, in a browser frame: where to stay for two nights on foot, with walking, review, weather and transit sources.

1. Install it:
   npx shadcn@latest add @keyframeui/footnote-glass-demo
   (If the CLI can't find @keyframeui, use https://keyframeui.com/r/footnote-glass-demo.json instead.)
   It adds the demo, components/footnote-glass-demo.tsx, and the component, components/ui/footnote.tsx.

2. Make it ours: our copy, data, images and colors. Keep the structure the motion depends on. If we only need the effect, use <Footnote> on its own.

3. These props set its feel. Change them before you change the file:
   - speed (default 45): How fast the answer writes itself, in words a second.
   - arc (default 26): Pixels each source's number arcs up over a straight line as it flies to its claim.
   - flightDuration (default 0.45): Seconds a number takes to fly from its source's chip into the claim's marker.
   - flightBounce (default 0.16): How much a number overshoots its marker before it settles, from `0` (none) up.

4. Don't change, in components/ui/footnote.tsx:
   - Every word, marker and chip is in the markup from the start and only shown as the run reaches it, so playing never changes the card's height.
   - The run is planned up front in ms (`buildPlan`), and one timer jumps a clock kept outside React from event to event; off screen or in a hidden tab it stops and picks up where it was.
   - Writing never waits for the numbers. A flying number re-measures its marker every frame and hands off to it in the frame it lands, and a slower flight pushes the finish back to match.
   - A link holds for a moment between claims, so moving across lines doesn't flicker; a source opens after the hover intent and closes only once the pointer has left both chip and card.
   - Reduced motion, read only after hydration, shows the finished answer at once with no dealing, streaming or flights. Links and source cards still work, and cards fade without growing.
   Its timing is all in the TIMING block at the top of that file.

Docs: https://keyframeui.com/components/footnote.md

Follow-up Questions

A company handbook assistant with follow-up questions under the card. Pick one and the answer folds away, the card eases to its new height and the next answer reads and writes itself. Its status line says "Checked 7 handbook pages".

How many days can I work from abroad each year?

Up to 30 working days a year, in blocks of at most 10 days in a row. Each block needs your lead's approval in Kiln HR two weeks before you go. Days at a Kiln office in another country don't count toward the 30. Sanctioned countries, and any without a tax treaty, can't be approved.

Ask next
Take this demo to your coding agent.
Add this moment from KeyframeUI to our project and adapt it to our content.

Footnote: An AI answer that shows its work. It reads its sources, dealing a chip for each one, then writes the answer, and as each claim lands its source's number lifts out of the chip and drops in at the end of the sentence. Point at a sentence and its source lights up; point at a source and the sentences it backs light up, and resting on it opens the passage the answer leans on.
This demo, Follow-up Questions: A company handbook assistant with follow-up questions under the card. Pick one and the answer folds away, the card eases to its new height and the next answer reads and writes itself. Its status line says "Checked 7 handbook pages".

1. Install it:
   npx shadcn@latest add @keyframeui/footnote-follow-ups-demo
   (If the CLI can't find @keyframeui, use https://keyframeui.com/r/footnote-follow-ups-demo.json instead.)
   It adds the demo, components/footnote-follow-ups-demo.tsx, and the component, components/ui/footnote.tsx.

2. Make it ours: our copy, data, images and colors. Keep the structure the motion depends on. If we only need the effect, use <Footnote> on its own.

3. These props set its feel. Change them before you change the file:
   - speed (default 45): How fast the answer writes itself, in words a second.
   - arc (default 26): Pixels each source's number arcs up over a straight line as it flies to its claim.
   - flightDuration (default 0.45): Seconds a number takes to fly from its source's chip into the claim's marker.
   - flightBounce (default 0.16): How much a number overshoots its marker before it settles, from `0` (none) up.

4. Don't change, in components/ui/footnote.tsx:
   - Every word, marker and chip is in the markup from the start and only shown as the run reaches it, so playing never changes the card's height.
   - The run is planned up front in ms (`buildPlan`), and one timer jumps a clock kept outside React from event to event; off screen or in a hidden tab it stops and picks up where it was.
   - Writing never waits for the numbers. A flying number re-measures its marker every frame and hands off to it in the frame it lands, and a slower flight pushes the finish back to match.
   - A link holds for a moment between claims, so moving across lines doesn't flicker; a source opens after the hover intent and closes only once the pointer has left both chip and card.
   - Reduced motion, read only after hydration, shows the finished answer at once with no dealing, streaming or flights. Links and source cards still work, and cards fade without growing.
   Its timing is all in the TIMING block at the top of that file.

Docs: https://keyframeui.com/components/footnote.md

Props

question Required

Typestring

The question, at the top of the card. A new question folds the old answer away and plays the new one.

answer Required

TypeFootnoteClaim[]

The answer, claim by claim, in reading order: { text, cite? }, where cite is a source id or several. Each claim gets a marker for every source it cites.

sources Required

TypeFootnoteSource[]

The sources it read: { id, site, title, href?, snippet?, quote? }. Cited ones are numbered in the order the answer first cites them; the rest follow with a monogram. snippet is the passage shown when a source opens, with quote marked in it.

read

Typenumber

How many sources it says it read, when that's more than you list. The extra ones show as "+N more".

play

Typeboolean | "view"Default"view"

When it plays: "view" once a third of it is on screen, true as soon as it mounts, false never (the finished answer shows).

speed

TypenumberDefault45

How fast the answer writes itself, in words a second.

arc

TypenumberDefault26

Pixels each source's number arcs up over a straight line as it flies to its claim.

flightDuration

TypenumberDefault0.45

Seconds a number takes to fly from its source's chip into the claim's marker.

flightBounce

TypenumberDefault0.16

How much a number overshoots its marker before it settles, from 0 (none) up.

avatar

TypeReact.ReactNode

The badge beside the question, like your product's mark. A small spark when unset.

status

Type(read: number, done: boolean) => React.ReactNodeDefault(read) => `Read ${read} sources`

The status line's text, from the number of sources read so far and whether reading has finished.

onComplete

Type() => void

Called when an answer has finished: written, every number landed. At once when it doesn't play.

className

Typestring

Classes for the card. Override its fill, ring and blur for a glass card over imagery (bg-white/70 backdrop-blur-xl ring-white/60), and set the accent with [--footnote-accent:#0f766e].