ImmoSystem24 DS

Komponentenverzeichnis

Inhalt der versionierten Datei docs/KOMPONENTENVERZEICHNIS.md.

Version 1.0 · Stand 16.10.2026 · Light Mode · Vorschau-Projekt (nicht veröffentlicht)

Diese Datei ist die Übergabe-Referenz. In der Bibliothek ist sie unter „Verzeichnis“ (/verzeichnis) lesbar. Entstehungsprotokoll und Prüfstände: docs/DESIGNSYSTEM.md.

1. Stack und Quellen

PaketVersion (package.json)Verwendung
TanStack Start / Router1.168 / 1.170Routen, Suchparameter
shadcn/uiCLI 4.21.5, Stil new-york, Radix-FamilieBasis-UI in src/components/ui
Tailwind CSS4.2 (CSS-first, src/styles.css)Tokens, Textrollen
Radix UIje Primitive ^1–2Dialog, Popover, Tabs usw.
react-day-picker9.14Calendar
@tanstack/react-table8.21.3Data Table
recharts2.15.4Chart
cmdk1.1Command / Combobox
react-hook-form + zod7.71 / 3.25Formularrezept
sonner2.0Toast
lucide-react0.575einzige Iconbibliothek

Quelle der Basiskomponenten: offizielle shadcn-Registry (ui.shadcn.com, new-york-v4). Die Registry-Combobox basiert auf @base-ui/react und ist mit der Radix-Familie nicht kompatibel; stattdessen gilt das offizielle Radix-Rezept Popover + Command.

2. Schichten

OrdnerInhaltRegel
src/components/uioffizielle shadcn-Komponentennur über Tokens/cva-Varianten anpassen, keine Parallelelemente
src/components/compositionsgenerische Kompositionennur aus ui zusammengesetzt
src/components/domainImmobilien-FachkomponentenDaten per Props, Links per title/actions-Slot
src/libFormatierung, Datum, Filter, Demo-Datenreine Funktionen, getestet

3. Basis-UI (@/components/ui/<name>)

GruppeKomponentenProjektvarianten
Aktionenbutton, button-group, toggle, toggle-groupButton: default (Navy-Hauptaktion), product (Alias von default), accent (optional Blau), secondary, outline, ghost, link, destructive, quick (92-px-Kachel, ohne Schatten); Größen sm, default (40 px), lg, tile, icon, icon-sm, icon-xs
Formulareinput, input-group, textarea, field, label, form, input-otpHöhe 40 px, Radius 8, Fläche #FDFDFD, Kontur 1 px rgba(6,3,20,.50) (≥3:1, bewusst dunkler als sevdesk .20), Hover neutral rgba(6,3,20,.71), Fokus 1 px Blau + 2-px-Akzent
Auswahlcheckbox, radio-group, switch, slider, select, native-select, command–
Datumcalendardeutsch, Montag, data-day = lokaler Schlüssel JJJJ-MM-TT
Strukturcard, item, avatar, badge, separator, aspect-ratio, scroll-area, resizable, carousel, kbdCard: Radius 12, Rahmen rgba(6,3,20,.17), Schatten 0 1px 6px, Innenabstand 20/24/24
Navigationsidebar, tabs, accordion, collapsible, navigation-menu, menubar, breadcrumb, paginationTabs variant status (12/16); Pagination-Links 48 px (Basis), Data-Table-Footer kompakt; mobile Trigger 44 px; SidebarMenuButton variant quiet + size nav (40 px, Produkt-Rahmen)
Overlaysdialog, alert-dialog, sheet, drawer, popover, dropdown-menu, context-menu, tooltip, hover-cardPopover-Schatten 0 6px 14px
Feedbackalert, progress, skeleton, spinner („Lädt“), empty, sonner, attachment–
Datentable, chartTabellenkopf 40 px #F7F7F7, Zeile 64 px

4. Kompositionen (@/components/compositions/<datei>)

ExportDateiBasis
StatusBadge (success, warning, danger, info, neutral)status-badgebadge + Icon + Text
PageHeaderpage-headerbreadcrumb
ComponentDoccomponent-doccard, badge, separator
ListPageHeader, ListPanel, ListPanelToolbar, StatusTabs, ListPanelFilters, FilterField, FilterChips, SummaryLine, ListPanelFooterlist-panelListen-/Detailseiten nach sevdesk (A2); Basis tabs (variant status), badge, Card-Tokens
LibrarySidebarlibrary-sidebarsidebar
CloseMobileSidebarOnNavigateclose-mobile-sidebarsidebar (schließt mobil nach Navigation)
MadeByTagmade-by-tagfest eingeblendetes Kennzeichen unten rechts (Card-Tokens, keine Aktion)
UnitInput, parseDecimalDe (€, %, m²)unit-inputinput-group
Combobox (einzeln/mehrfach, Chips, Gruppen, Reset)comboboxpopover + command + badge
DatePicker, DateRangePicker (8 Presets), TimeInput (24 h)date-pickercalendar, popover, input-group
useDataTable, DataTableView, DataTablePagination, SortHeader, ColumnToggle, selectColumndata-tabletable + TanStack Table
useUploadQueue, UploadDropzone, UploadErrors, UploadItemListfile-uploaditem, progress, spinner, button

5. Fachkomponenten (@/components/domain/<datei>)

ExportDateiWichtige Zustände
PropertyCard, PropertyRow, PropertyHeaderpropertyLeerstand, vollvermietet, Rückstand
UnitRow, RentSummary, PaymentRowrentbelegt/leer; bezahlt, offen, teilbezahlt, überfällig
PersonSummary, TenancySummarypeopleunvollständige Kontaktdaten, fehlende Kaution
TaskRow, TaskCardworkoffen, in Bearbeitung, erledigt, überfällig; Priorität hoch/normal/niedrig
DocumentRow, DocumentPreviewworkzugeordnet, nicht zugeordnet, Demo-Upload; Vorschau als Platzhalter gekennzeichnet
ActivityTimelineworkListe, leer
Checklist, Stepperworkbedienbar/lesend; aktueller Schritt mit aria-current
NoticeCard (eigenes Fachmuster auf shadcn Alert)workinfo, success, warning, danger
ChargeStatusBadge, TaskStatusBadge, PriorityBadge, OccupancyBadgestatusimmer Icon + Text
Facts, MissingValuefacts„Noch nicht erfasst“
LinkedRecordPicker, linkedRecordslinked-record-pickerObjekt/Einheit/Mietverhältnis mit stabilen IDs
KpiCardkpi-cardLabel 13/20, Wert direkt darunter (32/40 oder kompakt 24/32), Hinweis, Trend mit Icon+Text
ChartPanel, ChartKpiHeader, useBarMarker, chartGridProps (direkt in <CartesianGrid {...chartGridProps} />), chartAxis/chartYAxis (Y_AXIS_WIDTH 64, einzeiliger Kompakttick), groupedBarSize, usePlotFrame, PLOT_HEIGHT, eurTooltip, legendLine@/components/compositions/chart-framegemeinsame Diagrammhülle (Kopf/40 px/Plot 200/24 px/Footer 56), Umbruch nach Kartenbreite, ein Marker in der Mitte des berührten Balkens
CashflowChart / CashflowContentcashflow-chartKarte (Akte) bzw. Inhalt ohne Hülle; Tag/Monat, Tabelle, leer
FinanceCard, InsetStat, StatRowLink, DashCarddashboard-cardsDashboard-Finanzkarte, warmgraue Kennzahl-Insets, Statuszeilen mit Zähl-Badge; Basis Card, Progress, Toggle
PeriodPickerperiod-pickergemeinsamer Zeitraum
ProductShell, DemoResetButtonproduct-shellReset mit Bestätigung

6. Tokens (src/styles.css)

Alle Hex-/RGBA-Referenzen sind exakt in OKLCH umgerechnet; der Ursprungswert steht als Kommentar daneben.

TokenWertVerwendung
--background, --card#FFFFFFArbeitsfläche, Karten
--sidebar#FBF9F9Sidebar
--product / --product-hover#1E3A8A / #172554Button default = Hauptaktion Navy (product ist Alias, Weiß 10,36:1)
--search-surface#F3EDEDSidebar-Suche, warmgrauer Hover (SidebarMenuButton variant="quiet")
--inset-surface#F6F4F3flache Kennzahl-Insets (InsetStat)
--foreground#100B2DHaupttext
--muted-foreground#5E5E74Sekundärtext
--subtle-foreground#717387Nebeninformation, „Noch nicht erfasst“
--primary / --ring / --info#2563EBLinks, Fokus, Diagramme, ausgewählte Kontrollen; Button accent (optional)
--primary-hover#1D4ED8Hover, Auswahltext
--selection / --accent#EFF6FFAuswahlfläche
--border, --card-border, --disabledrgba(6,3,20,.17)dekorative Konturen, deaktiviert
--inputrgba(6,3,20,.50)Kontrollkontur, 3,79–3,85:1
--input-hoverrgba(6,3,20,.71)neutrale Hover-Kontur von Feldern/Checkbox/Radio
--hover-surfacergba(6,3,20,.06)neutraler Hover von Buttons, Toggles, Menü-/Optionszeilen
--chart-line#1E40AFdünne Datenlinien, 8,72:1 auf Weiß
--input-background#FDFDFDInputfläche
--muted#F7F7F7Tabellenkopf, Feldfläche im Fokus, Readonly
--pressedrgba(6,3,20,.11)aktiver Filter-Tab
--disabled-foreground#989CAAdeaktivierter Text
--success / -soft#15803D / #DCFCE7Status grün
--warning / -soft#A16207 / #FEF9C3Status gelb
--danger / -soft#B91C1C / #FEE2E2Status rot
--neutral / -soft#5E5E74 / #F1F1F4Status grau
--chart-1 … --chart-5Blau-Familie und NeutraltöneDiagrammserien
--radius-control / --radius-card8 px / 12 pxKontrollen / Karten
--control-height40 pxButtons, Inputs
--shadow-card0 1px 6px rgba(6,3,20,.10)Karten
--shadow-control0 1px 1px rgba(6,3,20,.07)Buttons
--shadow-popover0 6px 14px rgba(6,3,20,.10)Popover
--shadow-pressedinset 0 1px 2px rgba(6,3,20,.15)gedrückt
--field-ring-value (shadow-field-focus)0 0 0 2px #2563EB/16 %einziger Außenakzent fokussierter Felder
--field-ring-error-value (shadow-field-error)0 0 0 2px Rot/16 %Fehlerfeld im Fokus

Textrollen (@utility): text-greeting 30/40 400 · text-page-title 24/32 500 · text-card-title 20/28 500 · text-ui 14/22 · text-meta 13/20 · text-small 12/16 · text-kpi 32/40 600 · text-kpi-compact 24/32 600. Raster: page-container nur Dashboard (fluide ohne Maximalbreite; horizontaler Rand stetig 32→80 px nach Breite des Hauptbereichs als Inline-Size-Container, mobil <768 px 20 px; vertikal 40 px, schmal 24 px), list-container für Listen, Akten und alle Bibliotheksseiten (32 px, mobil 20 px), dashboard-grid (2 × minmax(0, 1fr), 24 px Abstand, einspaltig nach Containerbreite; frühere 2 × max. 480 px abgelöst).

Feldzustände (@utility control-field, gültig seit Nutzerrevision Fokus): Input, Textarea, Select-Trigger, NativeSelect, InputGroup, Combobox-Feld, Kalender-Dropdown. Priorität Disabled > Invalid > Fokus > Hover > Default; Rahmen konstant 1 px. Fokus = 1 px Blau + ein 2-px-Akzent, Fläche #F7F7F7, kein weißer Spalt. Fehler bleibt beim Fokus rot. Readonly durchgezogene neutrale Kontur auf Grau, fokussierbar. Checkbox/Radio/Switch: Hover nur bei gültigen, aktiven Kontrollen; Disabled überschreibt Invalid/Gewählt. Fehler am Gruppenbesitzer + Fokus/Open im Kind → roter Akzent. Gruppen (InputGroup, Combobox) besitzen den Fokusrahmen allein; innere Buttons zeigen Fokus als Auswahlfüllung. Buttons/Links/Checkbox/Radio/Switch/Slider/Tabs/Kalendertage: nur Tastaturfokus als 2-px-Outline Blau (Fallback in @layer base mit :where, Spezifität 0, kein !important).

7. Formatierung (@/lib/format, @/lib/date)

FunktionBeispiel
formatCents(130000)1.300,00 €
formatEur, formatEur0, formatCompact1.300,00 € · 1.300 € · 1,3 Tsd.
formatDay("2026-10-03")03.10.2026 (ohne Date/UTC)
formatArea(205)205 m²
formatPercent(75, 0)75 %
MISSING, orMissing(v)Noch nicht erfasst
toDateKey, fromDateKey, parseDateDe, formatDateDe, parseTime24, presetRange, validateRangelokale Kalendertage, TT.MM.JJJJ, 24 h

8. Demo-Daten

  • @/lib/demo/immo: fiktive Daten P1 Hofgarten 12 (U1–U3), P2 Parkblick 8 (U4), Mietverhältnisse T1–T3, Forderungen Nov 2025–Okt 2026, Zahlungen, Ausgaben, Dokumente D1–D12 (7 × P1, 4 × P2, D3 nicht zugeordnet), Aufgaben A1–A3, Aktivitäten. Geld in Cent, Tage als JJJJ-MM-TT, Stichtag 16.10.2026.
  • Selektoren: periodSummary, monthlySeries, chargeViews, occupancy, taskStats, Filterfunktionen. Mutationen: recordPayment, setTaskStatus, addTask, addDocument, assignDocument.
  • @/lib/demo/store: useDemo() und demoStore im Arbeitsspeicher; reset() bzw. Neuladen stellt den Ausgangsstand wieder her (inkl. Zeitraum Oktober 2026).
  • @/lib/demo/search: URL-Parameter je Beispielseite.
  • Soll-Werte Oktober: 2.500 € Soll, 1.200 € erhalten, 1.300 € offen, 700 € Cashflow, 2 überfällige Forderungen.

9. Nutzungsregeln

  1. Erst ui, dann compositions, dann domain verwenden; keine eigene Basis bauen, wenn shadcn sie liefert.
  2. Farben nur über semantische Tokens; keine zusätzlichen Akzentfarben.
  3. Status immer Farbe + Icon + Text (StatusBadge).
  4. Kontrollen 40 px, Filter 36 px Desktop / 44 px mobil (innere Gruppenfelder erben die Höhe), mobile Trefferflächen mindestens 44 px; Radius 8 (Kontrolle) und 12 (Karte).

4a. Hauptaktion = Button default (Navy); Blau (accent) nur optional. Keine zweite Primärfarbe. 4b. Feldartige Kontrollen nutzen control-field; keine eigenen Fokusringe oder !important-Schatten hinzufügen.

  1. Fehlende Werte nie schätzen: Facts/MissingValue verwenden.
  2. Geld als Cent, Kalendertage als Schlüssel; nie toISOString() oder toLocaleDateString() für Kalendertage.
  3. Kennzahlen und Diagramme nur aus Selektoren ableiten.
  4. Destruktive Aktionen mit AlertDialog bestätigen.
  5. Neue Bibliotheksbereiche in src/lib/library-sections.ts registrieren; mit inSidebar: false bleibt ein Bereich registriert, erscheint aber nicht als Menüpunkt der Bibliotheks-Sidebar.

10. Bereiche

BereichRouteStatus
Grundlagen, App-Rahmen, Aktionen, Formulare, Auswahl, Datum/Zeit, Tabellen/Filter, Karten/Kennzahlen, Diagramme, Dokumente, Dialoge/Feedback, Zustände, Ergänzungeneigene Routenfertig
Fachmuster/fachmusterfertig
Beispielseiten/beispielseiten → /beispiele/*fertig (Demo, kein Produktmodul); nicht als Sidebar-Menüpunkt, nur über Links
Verzeichnis/verzeichnisfertig

Offen bzw. bewusste Grenzen: Hover/Pressed nicht vollständig vermessen, Demo-Zustand nicht dauerhaft gespeichert, Dokumentvorschau als Platzhalter, keine Backends.

11. Abweichungen von der sevdesk-Referenz

PunktReferenzImmoSystem24Grund
Schrift Überschriften/KPIsRoobertCabinet Grotesk Variable (Revision G), gleiche Größen/Gewichte; UI InterNutzerentscheidung; bis G historisch Inter
Akzent#534ACC Violett, #212144#2563EB / #1D4ED8 / #EFF6FFMarkenvorgabe
Dashboard-Raster1144 px fest, rechts 19 px abgeschnittenfluide volle Hauptfläche, 40/80 px Rand, 2 × 1fr nach Containerbreite, stetiger Rand 32–80 px (F1/F2; feste 1144/480 px abgelöst)Overflow nicht übernommen
Zeitraum-Popover733 × 312 px733 × ca. 359 pxzusätzliche manuelle Von/Bis-Eingabe
Uhrzeit–HH:MM-Textfeld statt type=timezuverlässiges 24-h-Format
Produkt-App-Rahmen (A1)Suche in Sidebar, keine ToplbarProductShell + SidebarMenuButton quiet/nav; aktives Icon nur stärker gezeichnetLucide ohne gefüllte Icons
Listenseiten (A2)Titel y32, Panel ab y100, 32 px RandListPanel-Komposition, gemessen identisch–
Listen-Toolbar rechtsFilter, ExportierenZeitraum, Spalten (Mieten) bzw. Ansichtkein Export ohne Funktion
Mobilenicht gemessenTrigger 44 px, Tabellen als KartenZugänglichkeit

12. Wiederverwendung im ImmoSystem24-Demoprojekt

Dieser Workspace bietet in dieser Sitzung keine Registrierung dieses Projekts als auswählbares Lovable-Designsystem; eine Registrierung ist nicht erfolgt. Nutzbare Wege:

  1. Remix/Kopie dieses Projekts (empfohlen): enthält Tokens, Komponenten, Demo-Daten und Tests. Danach Bibliotheksrouten optional entfernen, src/components/*, src/lib/* und src/styles.css behalten.
  2. Gezielte Übernahme in ein bestehendes TanStack-Start-/shadcn-Projekt:
  3. src/styles.css (Tokens, Textrollen, Raster) übernehmen bzw. Token-Blöcke einfügen; Inter per <link> im Root-Head laden; Cabinet Grotesk lokal aus public/fonts/ per @font-face (+ Lizenzdatei) übernehmen.
  4. src/components/ui (angepasste shadcn-Dateien), src/components/compositions, src/components/domain kopieren.
  5. src/lib/format.ts, date.ts, selection.ts, table-filters.ts, upload.ts, utils.ts und bei Bedarf src/lib/demo/* kopieren.
  6. Pakete aus Abschnitt 1 in denselben Hauptversionen installieren.
  7. Tests aus src/test mitnehmen und ausführen (bunx vitest run).
  8. Fachkomponenten an echte Daten anbinden, indem immo.ts-Typen beibehalten und die Selektoren mit echten Datensätzen gespeist werden; der Demo-Store wird dabei ersetzt.

Erweiterung H1 (Produktbeispiele)

BausteinPfadBasis
Workflow-Fixtures/Validatorensrc/lib/demo/workflows.tsreine TS-Funktionen
Vermieten-Boardsrc/routes/beispiele.vermieten.tsxCard, Progress, Sheet, Select, Checkbox, StatusTabs, InputGroup
Objektreportsrc/routes/beispiele.optimieren.tsxAccordion, ToggleGroup, PriorityBadge, Button
Service-Arbeitsplatzsrc/routes/beispiele.services.tsxStatusBadge, Collapsible, Field, RadioGroup, LinkedRecordPicker, NativeSelect, Input, Textarea

Keine neuen generischen Kompositionen: alle Bausteine sind bislang seitenspezifisch und nutzen vorhandene shadcn-Basis.

Erweiterung H2 (Produktbeispiele)

BausteinPfadBasis
Übergabe-/Wissen-Zustand, Validatorensrc/lib/demo/workflows.tsreine TS-Funktionen
Beitragsdaten, Filter, Kontextprüfungsrc/lib/demo/wissen.tsreine TS-Funktionen
Stepper (jetzt optional vertikal/wählbar)src/components/domain/work.tsxKomposition
ArticleCover, BookmarkToggle, ContextCheckDialogsrc/components/domain/knowledge.tsxToggle, Dialog, NativeSelect, Field, Lucide
UnitInput (Einheiten kWh, m³, Stück ergänzt)src/components/compositions/unit-input.tsxInputGroup
Übergabeprotokollsrc/routes/beispiele.uebergabe.tsxStepper, Progress, Accordion, RadioGroup, DatePicker, UnitInput, Field
Mediathek / Beitragsrc/routes/beispiele.wissen.index.tsx, beispiele.wissen.$slug.tsxToggleGroup, Toggle, InputGroup, Empty, Breadcrumb, Checklist
Made by Loui Augst