Components Reference
React components in KB/src/components/. All are functional components using TypeScript and Tailwind CSS.
ArticleViewer
File: src/components/ArticleViewer.tsx
Props:
| Prop | Type | Description |
|---|---|---|
article | KBArticle | null | The article to display, or null for welcome screen |
Purpose: Main content area for reading KB articles. Renders either a welcome screen (when no article selected) or the full article with header, summary box, sections, and citations.
Key Features:
- Welcome screen: Hero with app title, feature cards (29 articles, AI Q&A, web research), and category browser grid
- Category badge: Color-coded pill based on
CATEGORY_CONFIG(gdpr=purple, swedish-law=blue, b2b-enrichment=green, enforcement=red, templates=amber) - Applicability badge: Emoji flag (🇸🇪/🇪🇺/🌍) showing geographic scope
- Summary box: Blue info card at top of each article
- Legal reference tags: Auto-detects
[GDPR Art. 6(1)(f)]patterns and renders styledlegal-ref-tagspans - Section rendering:
SectionBlocksub-component handles heading levels 2–4 with appropriate typography andlegalRefbadges - Citations section: Numbered list with
SourceBadgetiers, publisher/year metadata, and external links - Table of Contents: Sticky sidebar (hidden below
xlbreakpoint) when article has >2 sections
ChatMessage
File: src/components/ChatMessage.tsx
Props:
| Prop | Type | Description |
|---|---|---|
message | ChatMessage | A single chat message with role, content, timestamp, sources |
Purpose: Renders individual chat bubbles in the conversation thread.
Key Features:
- Bubble styling: User messages are blue right-aligned (
chat-bubble-user); assistant messages are gray left-aligned (chat-bubble-assistant) - Bold formatting: Parses
**bold**markdown within message text - Streaming cursor:
streaming-cursorCSS class appends a blinking▋indicator whileisStreamingis true - Timestamp: Shows
HH:MMinen-SElocale - Collapsible sources: Assistant messages with
sourcesshow a “Show/Hide N sources” toggle that expands into a list ofWebSearchResultcards withSourceBadge, snippet, and domain
ChatPanel
File: src/components/ChatPanel.tsx
Props:
| Prop | Type | Description |
|---|---|---|
isOpen | boolean | Whether the panel is visible |
onClose | () => void | Callback to close the panel |
currentArticle | KBArticle | null | Currently viewed article (injected as context) |
anthropicKey | string | Anthropic API key from settings |
onOpenSettings | () => void | Callback to open settings modal |
Purpose: Slide-in chat sidebar for AI Q&A. Manages the full chat UI including message list, input, and empty states.
Key Features:
- Slide animation:
chat-panel-enterCSS animation (0.25s ease-out from right) - Article context: Displays a blue context banner when
currentArticleis set, injecting article title/summary into Claude’s system prompt - API key gate: Shows lock icon + “Open Settings” button when no Anthropic key is configured
- Suggestion prompts: Pre-filled question buttons (“What is the legal basis for B2B data enrichment?”, etc.)
- Loading indicator: Three bouncing dots when waiting for Claude’s response
- Auto-resize textarea: Grows up to 120px height based on content
- Keyboard shortcuts: Enter sends, Shift+Enter adds newline
- Clear conversation: Trash icon button to reset message history
LegalDisclaimer
File: src/components/LegalDisclaimer.tsx
Props: None
Purpose: Persistent amber banner at the top of the main content area.
Key Features:
- Dismissible: Clicking the X stores dismissal in
localStorage(kb_disclaimer_dismissed) and hides the banner permanently - Content: States that KB content is “informational only — not legal advice” and recommends consulting a licensed Swedish attorney
- Styling: Amber background (
bg-amber-50 dark:bg-amber-950/40) with warning icon
SearchResults
File: src/components/SearchResults.tsx
Props:
| Prop | Type | Description |
|---|---|---|
results | KBArticle[] | Filtered articles from Fuse.js search |
query | string | Current search term (for display) |
onSelect | (article: KBArticle) => void | Callback when user clicks a result |
Purpose: Dropdown overlay showing fuzzy search results from the sidebar search input.
Key Features:
- Empty state: “No articles found for ‘query’” when results are empty
- Result count header: Shows “N results for ‘query’”
- Article cards: Each result shows title, applicability emoji, category pill, tags, and 2-line summary
- Keyboard accessible:
role="listbox"/role="option"ARIA attributes - Click-outside dismissal: Handled by parent
Sidebar
SettingsModal
File: src/components/SettingsModal.tsx
Props:
| Prop | Type | Description |
|---|---|---|
isOpen | boolean | Modal visibility |
onClose | () => void | Close callback |
settings | Settings | Current settings object |
onSave | (patch: Partial<Settings>) => void | Save callback |
Purpose: Modal dialog for configuring API keys and Claude model selection.
Key Features:
- Backdrop blur:
backdrop-blur-smwith semi-transparent overlay - Escape to close: Keyboard handler dismisses modal on Escape
- Fields:
- Anthropic API Key (password input, links to console.anthropic.com)
- Serper API Key (password input, links to serper.dev)
- Claude Model selector (dropdown: Opus 4.6, Sonnet 4.6, Haiku 4.5)
- Save confirmation: Button shows checkmark + “Saved” for 2 seconds after save
- Privacy note: Explains keys are stored locally in browser, never on server
Sidebar
File: src/components/Sidebar.tsx
Props:
| Prop | Type | Description |
|---|---|---|
articles | KBArticle[] | All articles to display |
selectedId | string | null | Currently selected article ID |
onSelect | (article: KBArticle) => void | Article selection callback |
onOpenSettings | () => void | Settings open callback |
Purpose: Left navigation sidebar with logo, search, collapsible category tree, and footer.
Key Features:
- Logo: EnrichNode KB branding with blue book icon
- Search input: Fuse.js-powered with magnifying glass icon, clear button, and
SearchResultsdropdown - Collapsible categories: 5 categories in fixed order (GDPR Core → Swedish Law → B2B Enrichment → Enforcement Cases → Templates), each with article count
- Article list: Shows title + applicability emoji; active article highlighted with
sidebar-item-active - Settings button: Gear icon in header
- Footer: Version label (v1.0.0) +
ThemeToggle
SourceBadge
File: src/components/SourceBadge.tsx
Props:
| Prop | Type | Default | Description |
|---|---|---|---|
tier | CredibilityTier | — | Credibility level |
size | "sm" | "md" | "sm" | Badge size |
Purpose: Visual credibility indicator for citations and web search results.
Key Features:
- Four tiers:
authoritative(green, ✓): IMY, EDPB, EUR-Lex, national parliamentsofficial(blue, ◉): Government bodies, official EU institutionspractitioner(amber, ⚖): Legal blogs, GDPR.eu, law schoolsuncertain(red, ?): News sites, unverified sources
- Sizing:
sm(compact, for inline use) ormd(larger, for standalone display) - Tooltip:
titleattribute shows full credibility label on hover
TableOfContents
File: src/components/TableOfContents.tsx
Props:
| Prop | Type | Description |
|---|---|---|
sections | KBSection[] | Article sections to build TOC from |
Purpose: Sticky right sidebar showing article heading navigation.
Key Features:
- IntersectionObserver tracking: Highlights the currently visible section using
rootMargin: "-80px 0px -60% 0px" - Click to scroll: Smooth-scrolls to section heading on click
- Level filtering: Shows only level-2 headings by default (falls back to all if no h2s)
- Indentation: Supports visual indentation for h3/h4 (though displaySections filters to h2)
- Sticky positioning:
sticky top-4stays visible while scrolling
ThemeToggle
File: src/components/ThemeToggle.tsx
Props: None
Purpose: Button to toggle between light and dark mode.
Key Features:
- Icon swap: Sun icon in dark mode, moon icon in light mode
- Accessibility: Dynamic
aria-labelandtitledescribing the action - Integration: Uses
useThemehook which persists tolocalStorageand togglesdarkclass on<html>