Citation Directive Implementation
This document describes the citation directive feature for highlighting text with source references.
Overview
The citation directive allows you to wrap content with source references and provides hover highlighting functionality. When a user hovers over a source reference, the associated text will be highlighted.
Syntax
Use the text directive syntax from remark-directive:
:cit[my content]{sources=1,2}
Where:
:citis the directive name[my content]is the content to be wrapped{sources=1,2}specifies the source IDs (comma-separated)
Example Usage
Old approach (still supported):
# My Answer
More content [1]
Real-world example:
In South Africa, the socks market in 2025 is expected to generate approximately US$26.62 million with a projected growth to US$32.98 million by 2029, driven by a CAGR of 5.50%, and a per capita expenditure of US$0.41 [1][2].
New approach with citation directive:
# My Answer
:cit[More content]{sources=1}
Multiple sources:
:cit[This data comes from multiple sources]{sources=1,2,3}
Component Architecture
1. remarkCitationPlugin (utils/remark-citation-plugin.ts)
- Remark plugin that parses
:cit[content]{sources=...}directives - Converts them to
<span class="citation" data-sources="1,2,3">content</span>
2. Citation (components/citation/citation.tsx)
- React component that wraps content and displays source badges
- Handles hover highlighting via the
HOVER_POPOVER_EVENTsystem - Supports both desktop (Popover) and mobile (BottomSheet) interactions
- Highlights the entire citation span when any of its sources are hovered
3. MarkdownAnswer (components/markdown-answer/markdown-answer.tsx)
- Updated to include
remarkDirectiveandremarkCitationPluginin the plugin chain - Custom
spanrenderer that detects citation spans and renders them with theCitationcomponent
Features
- ✅ Hover highlighting: When hovering over a source badge, the entire citation text is highlighted
- ✅ Multiple sources: Supports multiple source references per citation
- ✅ Desktop/Mobile support: Uses Popover on desktop and BottomSheet on mobile
- ✅ Event system: Integrates with existing
HOVER_POPOVER_EVENTfor coordinated highlighting - ✅ Backward compatible: Old
[1]syntax still works via SourceReference component
Technical Details
Dependencies
remark-directive: Core directive parsingmdast-util-directive: TypeScript types for directivesunist-util-visit: AST traversal utility
Styling
The highlight effect is achieved with:
className={`inline-block transition-all ${
isAnySourceHovered
? "bg-primary-subtle rounded"
: ""
}`}
Integration with existing code
- Reuses
Sourcetype fromsource-reference - Reuses
SourceBadge,Popover,PopoverSourceContent, andBottomSheetcomponents - Integrates with existing
HOVER_POPOVER_EVENTsystem for cross-component highlighting
Migration Path
- Backend changes: Update answer generation to use citation directive syntax
- Frontend changes: Already implemented (this PR)
- Gradual rollout: Both old and new syntax work simultaneously
- Future: Deprecate old
[n]syntax once all answers use directives
Testing
To test:
- Use markdown with citation directives in your answer
- Hover over source badges to see the text highlight
- Test on both desktop and mobile viewports
- Verify multiple sources per citation work correctly