Components Reference

React components in KB/src/components/. All are functional components using TypeScript and Tailwind CSS.


ArticleViewer

File: src/components/ArticleViewer.tsx

Props:

PropTypeDescription
articleKBArticle | nullThe 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 styled legal-ref-tag spans
  • Section rendering: SectionBlock sub-component handles heading levels 2–4 with appropriate typography and legalRef badges
  • Citations section: Numbered list with SourceBadge tiers, publisher/year metadata, and external links
  • Table of Contents: Sticky sidebar (hidden below xl breakpoint) when article has >2 sections

ChatMessage

File: src/components/ChatMessage.tsx

Props:

PropTypeDescription
messageChatMessageA 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-cursor CSS class appends a blinking indicator while isStreaming is true
  • Timestamp: Shows HH:MM in en-SE locale
  • Collapsible sources: Assistant messages with sources show a “Show/Hide N sources” toggle that expands into a list of WebSearchResult cards with SourceBadge, snippet, and domain

ChatPanel

File: src/components/ChatPanel.tsx

Props:

PropTypeDescription
isOpenbooleanWhether the panel is visible
onClose() => voidCallback to close the panel
currentArticleKBArticle | nullCurrently viewed article (injected as context)
anthropicKeystringAnthropic API key from settings
onOpenSettings() => voidCallback 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-enter CSS animation (0.25s ease-out from right)
  • Article context: Displays a blue context banner when currentArticle is 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:

PropTypeDescription
resultsKBArticle[]Filtered articles from Fuse.js search
querystringCurrent search term (for display)
onSelect(article: KBArticle) => voidCallback 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:

PropTypeDescription
isOpenbooleanModal visibility
onClose() => voidClose callback
settingsSettingsCurrent settings object
onSave(patch: Partial<Settings>) => voidSave callback

Purpose: Modal dialog for configuring API keys and Claude model selection.

Key Features:

  • Backdrop blur: backdrop-blur-sm with 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

File: src/components/Sidebar.tsx

Props:

PropTypeDescription
articlesKBArticle[]All articles to display
selectedIdstring | nullCurrently selected article ID
onSelect(article: KBArticle) => voidArticle selection callback
onOpenSettings() => voidSettings 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 SearchResults dropdown
  • 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:

PropTypeDefaultDescription
tierCredibilityTierCredibility 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 parliaments
    • official (blue, ◉): Government bodies, official EU institutions
    • practitioner (amber, ⚖): Legal blogs, GDPR.eu, law schools
    • uncertain (red, ?): News sites, unverified sources
  • Sizing: sm (compact, for inline use) or md (larger, for standalone display)
  • Tooltip: title attribute shows full credibility label on hover

TableOfContents

File: src/components/TableOfContents.tsx

Props:

PropTypeDescription
sectionsKBSection[]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-4 stays 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-label and title describing the action
  • Integration: Uses useTheme hook which persists to localStorage and toggles dark class on <html>

See also