Aller au contenu

🧩 Frontend Components

This section documents the reusable UI components in LibreFolio, organized by functional area.

📚 Component Categories

The library is split into two architectural layers: Core UI (generic atoms and molecules) and Features (domain-specific components).

Core UI

Component Details
Core UI overview Modals (ModalBase, ConfirmModal, sync modals), feedback (ToastContainer, Tooltip, InfoBanner), pickers (DateRangePicker), PageToolbar, DataEditor, atoms and inputs (PrivacyToggle, ExactDecimalInput, ExactQuantityInput, CompactDurationBadge), display blocks (KpiMetricBar, KpiDivergingFlowBar, RiskMetricCard, RiskCardGrid). Generic building blocks.
DataTable Advanced data grid with sorting, filtering, pagination, sticky columns and column management.
File Upload & Media FileUploader, ImageCropper, ImageEditModal, AssetPickerModal, LazyImage.
Select & Dropdowns SimpleSelect, SearchSelect and TreeSelect with keyboard navigation, specialized wrappers (AssetTypeSelect, CurrencySearchSelect, …) and AssetPickerPanel on SelectPopover + CheckMenu. A typed search ranks matches in the option's name or value above matches found only in its description — see Ranking the matches.

Features (Domain)

Component Details
Transaction Form Complex modal for creating/editing transactions with reactive auto-calculation and live WAC preview.
Import Wizard Multi-file staged broker import: duplicate detection (vs DB and in-batch), the file-priority batch resolver, and the N-way compare modal.
Brokers BrokerCard, BrokerForm, BrokerModal, DeleteBrokerDialog, and Broker Sharing.
Settings SettingsLayout, PreferencesTab, GlobalSettingsTab.
Authentication LoginCard, RegisterCard, ForgotPasswordCard, the password-manager contract.
Live Prices How the Assets list and the asset detail page poll POST /assets/prices/current every 30 s (60 s for the asset-detail chart head), and how a price change is shown.
Lots Analysis LotsAnalysisPanel and its chart/table/modal group: per-lot WAC vs market price, custody Gantt, unified lots table, value/return comparison, custody drill-down modal.
Risk UI The Correlation tab of the Assets page and the Dashboard's Risk tab: the selection, the requests over one shared window, the section frames and notices, and each block's rules.

🧭 App Header

lib/components/layout/Header.svelte is the bar above every authenticated page (mobile menu, privacy and theme toggles, language and help menus). It is sticky on every viewport and gives the page its height back while the user reads:

  • Scrolling down at least 8 px in a row hides it (it slides up by its own height); scrolling up at least 4 px brings it back. Within the first header-height of the page it is always shown.
  • It stays pinned — never hides — while keyboard focus is inside it, while the Help or Language menu is open, while the mobile sidebar is open, while any modal is open (it watches the ModalBase scroll-lock counter on document.body), while an onboarding guide runs, or when the keepVisible prop is set.
  • A route change, a window resize or a change of its own height shows it again.

The scroll position is sampled once per animation frame; the slide is a 200 ms transform, disabled under prefers-reduced-motion. The state is published as data-scroll-state (visible, hidden, pinned) next to data-menu-open, data-modal-open, data-sidebar-open and data-guide-active: Header.test.ts tests the state machine, e2e/layout/header-scroll.spec.ts the real geometry.

📏 Component Guidelines

  • ModalBase: ALL modals are built on ModalBase.svelte (directly, or through ConfirmModal / SyncModalBase) with configurable z-index
  • Svelte 5 Runes: Use $state, $derived, $effect, $props
  • Event handling: Use onclick instead of on:click (Svelte 5 syntax)
  • Styling: Tailwind CSS utilities + dark mode with dark: prefix — see Styling
  • HTML strings: escape user- and provider-supplied text with escapeHtml before it reaches {@html}; toasts and tooltips also sanitise what they render
  • Amounts: format money through the shared currency formatters, so the privacy toggle masks it — see Privacy masking
  • Accessibility: Keyboard navigation, ARIA labels, focus management
  • i18n: All user-facing text via $t('key') translation function