Files
HiveGrid-Wireframes/hivegrid-cloud/docs/boilerplate-inventory/ui-shell.md
T

25 KiB

Boilerplate-Inventur: UI-Layer & App-Shell

Faktische Bestandsaufnahme des Bereichs "UI-Layer & App-Shell" der Boilerplate (/Users/raffaelsheikh/Documents/GitHub/boilerplate). Stand: Read-only-Inventur, keine Aenderungen vorgenommen.

Inventarisierte Pakete/Pfade: packages/ui, packages/ui-app, packages/ui-mock, packages/ui-subframe, packages/view-models (Vertrags-Fundament), apps/web, apps/storybook.

TL;DR — Reale Layer-Trennung

Die Layer-Trennung ist noch nicht voll aktiviert. Sie ist als bewusst strukturierte "Adapter-/Vertrags-Grenze" angelegt, waehrend die echten Laufzeit-Komponenten weiterhin in apps/web/app/ leben.

  • @toolctrl/view-models — reine TypeScript-Typen + kleine Helfer: View-Model- Statusmodell (VMState), Shell-Registry-Typen (Sidebar/Breadcrumb/Mobile/ Portal), i18n-Key-Validierung. Kein React.
  • @toolctrl/ui-app — App-Shell-Registry-Factories + headless AppShell-Stub (rendert nur data-*-Attribute, kein echtes Layout). Konsumiert view-models.
  • @toolctrl/ui-mock — Fixture-/Mock-Generator fuer Hot-Swap- und Visual-Tests (erzeugt statisches HTML + serialisierbares Modul aus einem MockPage).
  • @toolctrl/ui-subframe — leerer Platzhalter (createSubframePlaceholder() liefert { status: "empty" }). Subframe-Adapter ist reserviert, nicht gebaut.
  • @toolctrl/ui — source-only Adapter-Metadaten (keine React-Komponenten). Beschreibt nur stabile Namen + Verweise auf die echten Implementierungen in apps/web/app/.
  • apps/web/app/ — echte Laufzeit: App-Shell (shadcn/Radix), Sidebar-Konfig, RR7-Routing, ~707 .tsx-Komponenten, Theme/Dark-Mode, i18n.
  • apps/storybook — Storybook 8 (react-vite) ueber die packages/ui-Stories.

Verbindung von Vertrag → echter Code laeuft ueber stabile data-ui-id-IDs (packages/.../application/ui/uiRegistry.ts) und die maschinenlesbare Inventur in docs/ui-inventory/ (von Tests gegen das Dateisystem geprueft).


Paket: @toolctrl/view-models

Zweck: Vertrags-Fundament fuer View-Model → UI. Reine Typen + winzige Validierungs-/Konstruktor-Helfer, ohne React-Abhaengigkeit. Bildet die gemeinsame Sprache, gegen die ui-app, ui-mock und die echte App komponieren.

Zentrale Datei: /Users/raffaelsheikh/Documents/GitHub/boilerplate/packages/view-models/src/index.ts package.json: /Users/raffaelsheikh/Documents/GitHub/boilerplate/packages/view-models/package.json (Name @toolctrl/view-models, Export . → ./src/index.ts)

Haupt-Exporte (Typen):

Export Bedeutung
VMStatus "idle" | "loading" | "ready" | "empty" | "error"
VMState<T> Diskriminierte Union ueber VMStatus; error traegt { messageKey; code? } (i18n-Key, nicht Klartext)
ActionCallbacks<T> onCreate/onUpdate/onDelete/onRefresh — Standard-CRUD-Callback-Vertrag
I18nLabel { labelKey; descriptionKey? } — UI-Labels sind immer i18n-Keys
RegistryGate { permission?; flag? } — Sichtbarkeits-Gate (Permission/Feature-Flag) pro Registry-Item
SidebarRegistryItem id/href/icon?/children? + I18nLabel + RegistryGate
BreadcrumbRegistryItem id/href? + Label + Gate
MobileRegistryItem id/href/priority? + Label + Gate
PortalRegistryItem id/slot/order? + Label + Gate
ShellRegistries { sidebar?; breadcrumbs?; mobile?; portals? } — das Shell-Konfig-Aggregat

Helfer-Funktionen: ready<T>(data), empty<T>(), assertI18nLabel(label) (erzwingt Regex ^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)*$ fuer Label- und Description-Keys).

HiveGrid-Relevanz: Hoch und querschnittlich. Das VMState-Statusmodell und der i18n-Key-Zwang sind direkt uebernehmbar als Daten-/UI-Vertrag fuer alle HiveGrid-Module (Listen/Detail/Editoren), und die ShellRegistries-Typen sind die Grundlage fuer datengetriebene Navigation (App-Shell-Querschnitt).


Paket: @toolctrl/ui-app

Zweck: App-Shell-Schicht. Liefert Registry-Factories (sortiert/normalisiert Sidebar/Breadcrumb/Mobile/Portal-Items) und einen headless AppShell-Stub. Der Stub rendert kein echtes Layout — nur ein <div> mit data-ui-shell und Zaehler-Attributen. Echte Shell lebt in apps/web.

Zentrale Datei: /Users/raffaelsheikh/Documents/GitHub/boilerplate/packages/ui-app/src/index.ts package.json: /Users/raffaelsheikh/Documents/GitHub/boilerplate/packages/ui-app/package.json (deps: @toolctrl/view-models, react; Test-Subpath-Exports fuer axe/a11y-Template)

Haupt-Exporte:

Export Art Verhalten
AppShellProps Typ { registries?: ShellRegistries; children? }
createSidebarRegistry(items) fn Kopie der Items
createBreadcrumbRegistry(items) fn Kopie der Items
createMobileRegistry(items) fn sortiert nach priority (default 100)
createPortalRegistry(items) fn sortiert nach order (default 100)
createShellRegistries(input) fn aggregiert + normalisiert alle 4 Registries
EmptyPage({ labelKey }) Komponente Empty-State-Stub (data-page-state="empty")
AppShell({ registries, children }) Komponente headless Shell-Stub mit data-*-Zaehlern

a11y-Test-Vertrag: /Users/raffaelsheikh/Documents/GitHub/boilerplate/packages/ui-app/src/test-utils/a11y-template.ts exportiert generateA11yTest(Component, defaultProps, options) — kanonisches axe-Test-Template (jede Komponente in ui-app/ui-subframe soll eine co-lokierte <Name>.a11y.test.tsx mitliefern). axe-Setup unter test-setup/axe.ts.

HiveGrid-Relevanz: App-Shell-/Navigations-Querschnitt. Die Registry- Factories sind die kanonische Art, HiveGrid-Sidebars/Breadcrumbs aus Daten zu bauen (mit Priority/Order-Sortierung und Permission/Flag-Gating). generateA11yTest ist als Compliance-/a11y-Querschnitt direkt nutzbar.


Paket: @toolctrl/ui-mock

Zweck: Hot-Swap-/Visual-Test-Fundament. Erzeugt aus einem deklarativen MockPage-Deskriptor deterministisch (a) ein serialisierbares JS-Modul und (b) statisches HTML inkl. eigenem Inline-CSS — als "Drop-in"-Ersatz fuer eine echte Seite. Liefert stabile Hashes/Metriken fuer Visual-Snapshots.

Zentrale Datei: /Users/raffaelsheikh/Documents/GitHub/boilerplate/packages/ui-mock/src/index.ts package.json: /Users/raffaelsheikh/Documents/GitHub/boilerplate/packages/ui-mock/package.json (dep: @toolctrl/view-models) Visual-Baseline: /Users/raffaelsheikh/Documents/GitHub/boilerplate/packages/ui-mock/visual-baseline/

Haupt-Exporte:

Export Art Verhalten
MockPage<T> Typ { id; route; title?/titleKey?; description?/descriptionKey?; state: VMState<T>; registries? }
HotSwapDrillData Typ { cards[]; activity[] } — Demo-Datenform
MockVisualSnapshot Typ htmlHash/moduleHash/stateHash (FNV-1a) + Byte-/Item-Metriken
MockArtifacts Typ { module; html; snapshot }
createMockPage(page) fn Identitaet (Typ-Anker)
createMockRegistry(pages) fn Map<route, MockPage>
generateHotSwapMock(page) fn erzeugt export const mockPage = ... Modul-String
generateMockPageHtml(page) fn volles statisches HTML (Sidebar/Breadcrumbs/Cards/Activity/State)
createVisualSnapshot(page, artifacts?) fn Snapshot mit stabilen Hashes
generateMockArtifacts(page) fn { module, html, snapshot } in einem Schritt
createHotSwapDrillPage() fn fertige Referenz-MockPage (/mock/phase-c/hot-swap)

Enthaelt eine eingebaute Mini-Uebersetzungstabelle (defaultMockTranslations) fuer die Mock-Texte (i18n-Keys → Klartext, deterministisch).

HiveGrid-Relevanz: Test-/QA-Querschnitt. Das Mock-Drop-in-Muster (deklarativer Deskriptor → deterministisches HTML + Hash) ist als Vorlage fuer HiveGrid-Visual- Regression und fuer das Bauen von Hot-Swap-/Whitelabel-Vorschauen verwendbar.


Paket: @toolctrl/ui-subframe

Zweck: Reservierte, leere Paket-Grenze fuer kuenftige Subframe-generierte UI. Bewusst leer, bis ein spaeterer Slice Import-Regeln + Review-Gates definiert.

Zentrale Datei: /Users/raffaelsheikh/Documents/GitHub/boilerplate/packages/ui-subframe/src/index.ts

  • uiSubframeRegistry = [] as const
  • createSubframePlaceholder() → { status: "empty" }

README: /Users/raffaelsheikh/Documents/GitHub/boilerplate/packages/ui-subframe/README.md ("Reserved package boundary for future Subframe-generated UI imports. Exports an empty registry.")

HiveGrid-Relevanz: Niedrig (Stub). Relevant nur als Marker dafuer, dass der Subframe-Adapter-Layer der Boilerplate nicht gebaut ist — siehe MEMORY.md ("Subframe mandatory for all routes"). HiveGrid muesste diese Grenze selbst fuellen.


Paket: @toolctrl/ui

Zweck: Source-only Adapter-Metadaten ("category migration boundary"). Enthaelt keine React-Komponenten und importiert React nicht. Beschreibt stabile Namen pro Kategorie und zeigt per source-Feld auf die echten Implementierungen in apps/web/app/. Erlaubt Agenten/Tools, stabile Namen anzusprechen, bevor Laufzeit-Imports migriert sind.

README: /Users/raffaelsheikh/Documents/GitHub/boilerplate/packages/ui/README.md package.json: /Users/raffaelsheikh/Documents/GitHub/boilerplate/packages/ui/package.json Migration-Doku: /Users/raffaelsheikh/Documents/GitHub/boilerplate/packages/ui/docs/migration.md

Subpath-Exporte (Kategorien): ., ./buttons, ./inputs, ./dialogs, ./tables, ./layout, ./navigation, ./feedback.

Zentrale Dateien:

Datei Inhalt
src/index.ts Re-Exporte aller Kategorien
src/types.ts uiAdapterCategories, UiAdapterDefinition, UiAdapterLifecycle (placeholder/available/deprecated), createEmptyAdapterRegistry, isUiAdapterCategory
src/navigation.ts navigationAdapters (status available): AppSidebar, AdminSidebar, DocsSidebar, NavMain, NavSecondary, NavQuickLinks, NavActions, SidebarPrimitives — mit source-Pfaden in apps/web/app/...
src/layout.ts layoutAdapters: ShadcnSidebarLayout, UiRegistry
src/buttons.ts buttonAdapters (Button, buttonVariants)
src/inputs.ts, dialogs.ts, tables.ts, feedback.ts derzeit leere Readonly-Registries (Placeholder bis Migrations-Phase)
src/stories/*.stories.tsx ~21 Storybook-Stories (Button, Input, Select, Dialog, DataTable, Table, Tabs, Toast, Tooltip, Popover, Card, Badge, Avatar, Checkbox, Radio, Switch, Textarea, Form, EmptyState, LoadingState, Sidebar) ueber _demo-primitives.tsx

Alle source-Pfade aus navigation.ts/layout.ts (absolut): /Users/raffaelsheikh/Documents/GitHub/boilerplate/apps/web/app/application/sidebar/AppSidebar.tsx, .../AdminSidebar.tsx, .../DocsSidebar.ts, .../components/layouts/sidebars/shadcn/nav-main.tsx, nav-secondary.tsx, nav-quick-links.tsx, nav-actions.tsx, .../components/ui/sidebar.tsx, .../components/layouts/sidebars/shadcn/ShadcnSidebarLayout.tsx, .../application/ui/uiRegistry.ts.

HiveGrid-Relevanz: Konventions-Querschnitt. Liefert die Taxonomie (buttons/inputs/dialogs/tables/layout/navigation/feedback) und das Lifecycle- Modell, an dem sich eine HiveGrid-Komponentenbibliothek ausrichten kann. Faktisch ist es jedoch nur Metadaten — die echten Komponenten liegen in apps/web.


App: apps/web — echte App-Shell, Sidebar-Konfig, Routing

package.json: /Users/raffaelsheikh/Documents/GitHub/boilerplate/apps/web/package.json Stack: React Router 7 (RR7), Vite, Tailwind v4, shadcn/Radix. SaasRock-aehnliche Struktur.

App-Shell / Layout

Asset Pfad Was
AppLayout apps/web/app/components/app/AppLayout.tsx Einstieg: SkipToContent + CommandPalette + ShadcnSidebarLayout; Prop layout: "app" | "admin" | "docs"
ShadcnSidebarLayout apps/web/app/components/layouts/sidebars/shadcn/ShadcnSidebarLayout.tsx Authentifizierte Shell: SidebarProvider → ShadcnAppSidebar + SidebarInset (Header mit Breadcrumb/SidebarTrigger/NavActions, <main id="main-content">). Liest Tenant-themeConfig + Dark-Mode → injiziert --sidebar* CSS-Variablen.
ShadcnAppSidebar apps/web/app/components/layouts/sidebars/shadcn/app-sidebar.tsx Waehlt je layout die Menue-Quelle: AppSidebar/AdminSidebar/DocsSidebar; wendet Permission-/Sichtbarkeits-Filter (getVisibleItem) + Active-State an; rendert NavMain/NavSecondary
NavMain .../shadcn/nav-main.tsx Rendert SidebarGroupDto[] → shadcn SidebarMenu mit collapsible Untermenues; setzt data-ui-id-Attribute via getUiIdAttributes
weitere Nav .../shadcn/nav-secondary.tsx, nav-quick-links.tsx, nav-actions.tsx, nav-user.tsx, team-switcher.tsx Sekundaer-Nav, Quick-Links, Header-Aktionen (Search/AI/Notifications/Feedback), User-/Team-Switcher

Sidebar-Konfiguration (datengetrieben)

Asset Pfad Was
SideBarItem (Interface) apps/web/app/application/sidebar/SidebarItem.ts Item-Vertrag: id/title/path/icon/items/permission/adminOnly/tenantUserTypes/isCollapsible/isSecondary/isQuickLink/redirectTo/uiIdPattern/uiIdParams/...
SidebarGroupDto apps/web/app/application/sidebar/SidebarGroupDto.ts { id?; items: SideBarItem[]; title?; type?: "main"|"secondary"|"quick-link" }
AppSidebar(props) apps/web/app/application/sidebar/AppSidebar.tsx Baut Tenant-App-Menue dynamisch aus entities, entityGroups, productAccess (Feature-Gating: crm-basic, email-marketing, workflow-engine, api, ai-credits); host-aware Pfade via appPath/tenantPath
AdminSidebar(props) apps/web/app/application/sidebar/AdminSidebar.tsx Statisches Admin-Menue in Segmenten Manage/Build/Market/Settings; Permission-getaggt; Plugin-Routen via enabledAdminRouteItem/disabledPluginRouteSlugs ausblendbar
DocsSidebar() apps/web/app/application/sidebar/DocsSidebar.ts Statischer Docs-Baum; vergibt stabile ui.nav.docs.*-IDs (withDocsSidebarIds)

UI-Registry (stabile IDs / data-ui-id)

Asset Pfad Was
uiRegistry.ts apps/web/app/application/ui/uiRegistry.ts Single source of truth fuer stabile UI-IDs: UI_SURFACE_IDS, UI_ACTION_IDS, UI_NAV_IDS, UI_ID_PATTERNS; Helfer getSidebarSurfaceId(layout), uiIdSegment(value), getUiIdAttributes(item) (erzeugt data-ui-id / -pattern / -param-*)

RR7-Routing-Konvention (app/routes)

Asset Pfad Was
Route-Manifest apps/web/app/routes.ts Nutzt Remix-v1-Flat-Folder-Convention ueber remixConfigRoutes + createRoutesFromFolders (NICHT die RR7-Default-Convention). Definiert defaultIgnoredRouteFilePatterns (*.test.*, *.server.*, *.css, dotfiles) und defaultDisabledPluginRouteFilePatterns (deaktivierbare Plugin-Routen)
Convention-Impl apps/web/app/utils/compat/v1-route-convention.ts Kopie von remix-run/v1-compat-utils; Param-Prefix $, Escape [ ], Optional ( ), Module-Exts .js/.jsx/.ts/.tsx/.md/.mdx
react-router.config.ts apps/web/react-router.config.ts RR7-App-Config
Routen-Tests apps/web/app/routes.test.ts, apps/web/app/utils/compat/v1-route-convention.test.ts Verifizieren das Manifest

Routen-Topologie (Auszug, apps/web/app/routes/, ~102 Eintraege):

  • Tenant-Space: app.$tenant.tsx (Layout) + app.$tenant/ (dashboard, crm, email-marketing, notifications, settings, forms, g.$group, sites, internal, __portals, __widgets, __workflows, $entity.__autogenerated).
  • Admin-Space: admin.tsx + admin/ (accounts, analytics, entities, workflow-engine, api, feature-flags, navigation, portals, prompts, email-marketing, marketing-leads, knowledge-base, help-desk, onboarding, metrics, settings, audit-trails, events).
  • Docs: docs/. Auth: auth.*, forgot-password.*, login-Flows. Fehlerseiten: 401/403/404/500/$.
  • Hot-Swap-Demo (dev-only): apps/web/app/routes/hot-swap-demo.tsx.

Shell-Verdrahtung: app.$tenant.tsx wrappt Tenant-Routen ueber <AppLayout layout="app">; app-sidebar.tsx zieht die Menue-Daten ueber useAppOrAdminData() (RR7 Loader-Daten) und ruft die passende Sidebar-Factory.

Theme / Dark-Mode

Asset Pfad Was
root.tsx apps/web/app/root.tsx Setzt dark-Klasse aus userSession.lightOrDarkMode (gated ueber DARK_MODE_IN_APP), theme-${rootData.theme} (+ -scaled); Actions toggleLightOrDarkMode, setTheme, setLocale (Persistenz in User-Session/DB)
themes.css apps/web/app/themes.css (86 KB) Vordefinierte Themes als CSS-Variablen
globals.css apps/web/app/globals.css Globale Tokens/Tailwind-Base
Theme-Enum apps/web/app/application/enums/shared/Theme.ts LIGHT | DARK
Theme-Preview-Store apps/web/app/stores/themePreviewStore.ts (via useThemePreviewStore) Live-Preview-Override im Shell-Layout
parseThemeConfig / ThemeConfig apps/web/app/utils/theme/ThemeConfig.ts Parst Tenant-themeConfig (Farben inkl. darkColors, sidebar*-Farben)
tailwind.config.ts boilerplate/tailwind.config.ts (Repo-Root) Tailwind-Setup

Prisma-Bezug (Theme/Shell-State):

  • prisma/schema/accounts.prisma:17 — User.lightOrDarkMode String? (Hell/Dunkel-Praeferenz pro User).
  • prisma/schema/accounts.prisma:188 — Tenant.themeConfig String? (Per-Tenant-Whitelabel-Theme als serialisierter JSON-String).
  • prisma/schema/portals.prisma — Portal, PortalPage, ... (Portal-Feature; Bezug zu PortalRegistryItem/Admin-Portals-Nav).

i18n in der UI

Asset Pfad Was
Web-i18n-Setup apps/web/app/locale/ (i18n.ts, i18next.server.ts, i18next.global.server.ts, format.ts, date-fns.ts) i18next + RR7 SSR-Integration
Locale-Daten apps/web/public/locales/{de,en}/*.json Namespaces: translations (legacy Bulk), common, errors, mail, settings, billing, crm, auth, emailMarketing
Shared-Paket packages/i18n/src/index.ts (@toolctrl/i18n) defaultLocale="de", supportedLocales=["de","en"], i18nNamespaces, i18nConfig, getDirection/isRTL (RTL-Support vorbereitet), Re-Exporte formatNumber/Currency/Date/RelativeTime/List, formatIcu, createUseTranslate

Sidebars/Registries verwenden durchgaengig i18n-Keys (t(...) bzw. labelKey), nie Klartext — assertI18nLabel (view-models) erzwingt das auf Vertragsebene.

Komponenten-/Page-Bibliothek (real, in apps/web)

Insgesamt ~707 .tsx-Komponenten (ohne *.test.tsx/*.stories.tsx) unter apps/web/app/components/. Verzeichnis-Highlights:

Bereich Pfad Inhalt (Auszug)
Primitives (shadcn/Radix) apps/web/app/components/ui/ button.tsx, input.tsx, select.tsx, dialog.tsx, sheet.tsx, drawer.tsx, popover.tsx, table.tsx, tabs.tsx, form.tsx, sidebar.tsx, command.tsx, toast.tsx/sonner.tsx, badge.tsx, card.tsx, calendar.tsx, chart.tsx, multi-select.tsx, stepper.tsx, pagination.tsx, ...
Tabellen apps/web/app/components/ui/tables/ TableSimple.tsx, TableNew.tsx, TablePagination.tsx, GridPagination.tsx, ColumnSelector.tsx, CollapsibleRow.tsx, RowsLoadMoreCard.tsx, PreviewTableSimple.tsx
Formulare apps/web/app/components/ui/forms/, .../input, .../selectors, .../editors FormGroup.tsx, InputGroup.tsx + reichhaltige Input-/Selector-/Editor-Komponenten
Modale/Dialoge apps/web/app/components/ui/modals/, .../slideOvers Modal.tsx, ModalOrSlide.tsx, ConfirmDialog.tsx, ConfirmModal.tsx, ActionResultModal.tsx, ErrorModal.tsx, SuccessModal.tsx, OpenModal.tsx, ...
Empty/Loading apps/web/app/components/ui/emptyState, .../loaders Empty-/Loading-States
Command-Palette apps/web/app/components/ui/commandPalettes/CommandPalette Kommando-Palette (im Shell verdrahtet)
Entitaeten/Editoren apps/web/app/components/entities, .../editors, .../json, .../pdf Entity-Builder-UI, Rich-Editoren, JSON-/PDF-Viewer
Weitere aceternity, ai-elements, analytics, audit, brand, cookies, dashboard, images, motion-primitives, notifications, pages, public, recaptcha App-spezifische Komponenten-Cluster

Hot-Swap-Aktivierung (Drop-in, real verdrahtet)

Asset Pfad Was
Renderer apps/web/app/components/ui/hot-swap/HotSwapPageRenderer.tsx Bruecke: MockPage-Deskriptor (@toolctrl/ui-mock) → RR7-JSX, nutzt createShellRegistries() aus @toolctrl/ui-app
Demo-Route apps/web/app/routes/hot-swap-demo.tsx Rendert createHotSwapDrillPage(); gated auf NODE_ENV !== "production"
Renderer-Test apps/web/app/components/ui/hot-swap/HotSwapPageRenderer.test.tsx Prueft Deskriptor → DOM (Sidebar/Breadcrumbs/Header/Cards/Activity)

HiveGrid-Relevanz (apps/web gesamt): Sehr hoch. Dies ist der reale, sofort wiederverwendbare Fundus: vollstaendige authentifizierte App-Shell (App/Admin/Docs), datengetriebene Sidebar mit Permission-/Feature-Gating, RR7-Flat-Folder-Routing inkl. Tenant- (app.$tenant) und Admin-Trennung, Theme/Dark-Mode mit Per-Tenant-Whitelabel (Tenant.themeConfig), i18n (de/en), und eine breite shadcn/Radix-Komponentenbibliothek (Tabellen/Forms/Modale). Querschnittlich relevant fuer praktisch jedes HiveGrid-Modul.


App: apps/storybook

Zweck: Storybook-8-Workbench + Visual-Regression (lost-pixel) + a11y-Addon.

package.json: /Users/raffaelsheikh/Documents/GitHub/boilerplate/apps/storybook/package.json (@storybook/react-vite 8.6, Addons: essentials/a11y/interactions/themes; lost-pixel 3.22; dep @toolctrl/i18n)

Zentrale Dateien:

Asset Pfad Was
Storybook-Config apps/storybook/.storybook/main.ts Stories aus apps/storybook/src/** und packages/{ui,ui-app,ui-subframe,ui-mock}/src/**/*.stories.*; Tailwind-v4-Vite-Plugin; Alias ~ → apps/web/app
i18n-Bootstrap apps/storybook/.storybook/i18n.ts, preview.tsx, preview.css i18next + Theme-Decorator in Preview
Lost-Pixel apps/storybook/lostpixel.config.ts, .lostpixel/ Visual-Regression-Config + Baselines
Test-Runner apps/storybook/.storybook/test-runner.ts axe-playwright-basierte a11y-Checks im Test-Runner
Docs (MDX) apps/storybook/src/Introduction.mdx, src/ThemeGuide.mdx Einfuehrung + Theme-Guide
Scripts package.json storybook (dev :6006), build-storybook, test:storybook, visual-regression(:update)

Status: Stories sind aktuell (~21) groesstenteils inline-styled Demos ueber packages/ui/src/stories/_demo-primitives.tsx (CSS-Variablen-Tokens aus preview.css); der "echte Tailwind-v4-Pipeline"-Pfad ist im main.ts als Migrations-Vorbereitung schon vorhanden (Tailwind-Plugin no-op fuer heutige Stories).

HiveGrid-Relevanz: QA-/Design-Querschnitt. Direkt nutzbar als Visual- Regression- und a11y-Gate fuer eine HiveGrid-Komponentenbibliothek; der Alias auf apps/web/app erlaubt, echte App-Komponenten in Stories zu ziehen.


Maschinenlesbare UI-Inventur & Verifikations-Gates

Verbindet Vertrag ↔ echte Komponenten und wird von der Test-Suite geprueft.

Asset Pfad Was
Komponenten-Inventur docs/ui-inventory/components.json 71 Eintraege (stableName/path/category/library/status); Schema docs/ui-inventory/schema.json
Surface-Map docs/ui-inventory/surfaces.json (+ surfaces.schema.json, surface-map.md) Mapping stabiler data-ui-id → Quelldateien/Renderer
Inventur-Test apps/web/app/application/ui/uiInventory.test.ts Prueft, dass Inventur-Pfade existieren, alle components/ui/*.tsx-Primitives gelistet sind und Registry-IDs in der Surface-Map stehen
Adapter-Test apps/web/app/application/ui/uiAdapters.test.ts, uiRegistry.test.ts Prueft @toolctrl/ui-Adapter ↔ App-Registry-Konsistenz
Hot-Swap-Status docs/ui-inventory/hot-swap-status.md Dokumentiert, was verdrahtet ist (ui-app/ui-mock aktiv, ui-subframe Platzhalter) + Aktivierungs-Checkliste
Boundary-Gate scripts/verify-phase-c-boundaries.mjs (npm verify:phase-c-boundaries) Erzwingt, dass Aktivierung keine Laufzeit-Layer-Grenze verletzt
Hot-Swap-Verify scripts/verify-ui-hot-swap.ts (npm verify:ui-hot-swap, test:hot-swap) Mock-getriebener Hot-Swap-Drill
Visual-Verify scripts/verify-ui-mock-visual.ts (npm verify:ui-visual) Mock-Visual-Baseline

HiveGrid-Relevanz: Governance-/Konventions-Querschnitt. Das Muster "stabile ID-Registry + maschinenlesbare Inventur + dateisystem-geprueftes Gate" ist direkt als HiveGrid-UI-Governance uebertragbar (Whitelabel/Hot-Swap-Faehigkeit mit hartem CI-Schutz der Layer-Grenzen).


Wichtige Vorbehalte (Anti-Erfindung)

  • @toolctrl/ui enthaelt keine lauffaehigen Komponenten — nur Adapter-Metadaten, die auf apps/web/app/... verweisen. Echte Primitives = apps/web/app/components/ui/*.
  • @toolctrl/ui-subframe ist leer (Placeholder). Es gibt keinen gebauten Subframe-Adapter-Layer in der Boilerplate.
  • Der AppShell in @toolctrl/ui-app ist ein headless Stub (nur data-*), nicht die echte sichtbare Shell. Sichtbare Shell = ShadcnSidebarLayout.
  • Hot-Swap ist nur an der dev-only Demo-Route (hot-swap-demo.tsx) end-to-end aktiv; Produktiv-Routen rendern weiterhin direkt aus apps/web/app/components/.
  • Routing nutzt die Remix-v1-Flat-Folder-Convention (Compat-Layer), nicht die RR7-Default-routes.ts-Convention.
  • Es gibt keine Prisma-Modelle, die exklusiv zu den UI-Paketen gehoeren; UI-relevant sind User.lightOrDarkMode und Tenant.themeConfig (accounts.prisma) sowie Portal* (portals.prisma).