--- phase: 4 slug: marketplace-portal-navigation status: draft shadcn_initialized: false preset: none created: 2026-06-22 --- # Phase 4 — UI Design Contract > Visual and interaction contract for Marketplace & Portal Navigation. Generated by gsd-ui-researcher, verified by gsd-ui-checker. --- ## Design System | Property | Value | |----------|-------| | Tool | none (hand-rolled components with shadcn-compatible CSS variable naming) | | Preset | not applicable | | Component library | none (custom components, Radix-compatible token structure) | | Icon library | Inline SVG (project convention from Phase 1-3, no external icon library) | | Font | Inter, system-ui, -apple-system, sans-serif (declared as `--font-sans` in globals.css) | **Note:** The project uses shadcn-compatible CSS custom property naming (`--primary`, `--card`, `--muted`, etc.) and Tailwind v4 `@theme inline` mapping, but does not have `components.json`. All UI components are hand-rolled. This phase continues that pattern. --- ## Spacing Scale Declared values (must be multiples of 4): | Token | Value | Usage | |-------|-------|-------| | xs | 4px | Icon gaps, inline badge padding, chip internal spacing | | sm | 8px | Compact element spacing, card internal gaps, filter chip gaps | | md | 16px | Default element spacing, card padding, search bar padding | | lg | 24px | Section padding, space between marketplace header and grid | | xl | 32px | Layout gaps, space between major page sections | | 2xl | 48px | Empty state vertical padding, page top/bottom padding | | 3xl | 64px | Not used in this phase | Exceptions: Sidebar search input height at 36px (not a spacing token — component-specific dimension for comfortable text input within narrow 240px sidebar). Marketplace card minimum height at 180px for visual consistency in the grid. --- ## Typography | Role | Size | Weight | Line Height | Usage in Phase 4 | |------|------|--------|-------------|-------------------| | Body | 14px | 400 (regular) | 1.5 | Card descriptions, sidebar module names, filter labels | | Label | 12px | 600 (semibold) | 1.4 | Category badges, status badges, sidebar section headers, version text | | Heading | 20px | 700 (bold) | 1.2 | Page titles ("Marktplatz"), section headings | | Display | 28px | 700 (bold) | 1.2 | Not used in this phase (reserved for Dashboard phase) | **Font weights used:** 400 (regular) and 600 (semibold). 700 (bold) only for page headings per existing codebase convention (`text-2xl font-bold` in admin pages). --- ## Color All values in OKLCH (project convention from Phase 1, defined in `globals.css`). | Role | Light Mode | Dark Mode | Usage | |------|-----------|-----------|-------| | Dominant (60%) | `oklch(0.99 0 0)` — near-white | `oklch(0.23 0.01 260)` — dark gray-blue | Page background, marketplace grid background | | Secondary (30%) | `oklch(1 0 0)` / `oklch(0.96 0 0)` — white/light gray | `oklch(0.27 0.01 260)` / `oklch(0.30 0.01 260)` — dark card/muted | Marketplace cards (`bg-card`), sidebar (`bg-sidebar`), filter bar background, tenant selector dropdown | | Accent (10%) | `oklch(0.91 0.19 102)` — Tessera yellow | `oklch(0.91 0.19 102)` — same yellow | See reserved-for list below | | Destructive | `oklch(0.55 0.2 27)` — red | `oklch(0.55 0.2 27)` — same red | Deactivation confirmation dialog only | | Success | `oklch(0.55 0.16 145)` — green | `oklch(0.55 0.16 145)` — green | "Aktiviert" status badge, activation success toast | **Accent reserved for:** 1. "Aktivieren" / "Modul aktivieren" primary CTA button background 2. Active module card border highlight on hover (`hover:border-primary/30` — existing pattern) 3. Active sidebar item background accent (`bg-sidebar-accent`) 4. Marketplace search input focus ring (`ring-ring` maps to primary) 5. Tenant context selector active state indicator 6. Toggle switch active state (existing pattern from admin/modules) **Accent explicitly NOT used for:** - Category badges (use `bg-muted` with `text-muted-foreground`) - Status text (use semantic green/red) - Card backgrounds (use `bg-card`) --- ## Component Inventory ### New Components (Phase 4) | Component | Location | Purpose | |-----------|----------|---------| | `MarketplaceCard` | `apps/web/src/app/(portal)/marketplace/components/MarketplaceCard.tsx` | Module card for marketplace grid — extends ModuleCard pattern with activation toggle and status badge | | `MarketplaceSearch` | `apps/web/src/app/(portal)/marketplace/components/MarketplaceSearch.tsx` | Search input with live filter, debounced 300ms | | `CategoryFilter` | `apps/web/src/app/(portal)/marketplace/components/CategoryFilter.tsx` | Horizontal chip/pill row for category filtering | | `StatusFilter` | `apps/web/src/app/(portal)/marketplace/components/StatusFilter.tsx` | Tab bar: "Alle" / "Aktiviert" / "Verfuegbar" for filtering by activation status | | `TenantContextSelector` | `apps/web/src/app/(portal)/marketplace/components/TenantContextSelector.tsx` | Dropdown for Super-Admin to switch tenant context in marketplace | | `ModuleDetailView` | `apps/web/src/app/(portal)/marketplace/[slug]/page.tsx` | Compact detail page for a single module | | `ActivationDialog` | `apps/web/src/app/(portal)/marketplace/components/ActivationDialog.tsx` | Confirmation dialog for deactivation only (activation is immediate with undo toast) | | `SidebarSearch` | `apps/web/src/components/layout/sidebar-search.tsx` | Inline search/filter field within sidebar categories section | ### Reused Components (from Phase 1-3) | Component | Source | Reuse | |-----------|--------|-------| | `ModuleCard` | `apps/web/src/app/(portal)/modules/[category]/components/ModuleCard.tsx` | Pattern reference for MarketplaceCard — same card structure, extended with activation controls | | `Sidebar` | `apps/web/src/components/layout/sidebar.tsx` | Extended with SidebarSearch and individual module links per category | | `Header` | `apps/web/src/components/layout/header.tsx` | Unchanged — breadcrumb updates for marketplace route | | `AppShell` | `apps/web/src/components/layout/app-shell.tsx` | Unchanged — marketplace pages render within existing shell | --- ## Layout Specifications ### Marketplace Page (`/marketplace`) ``` +----------------------------------------------------------+ | Header (sticky, 60px) | +--------+-------------------------------------------------+ | Sidebar | Marketplace Page | | 240px | | | | [Tenant Selector - Super-Admin only] | | | | | | Marktplatz (h1, 20px bold) | | | Entdecken Sie verfuegbare Module (14px muted) | | | | | | [Search input, full width] | | | [StatusTabs: Alle | Aktiviert | Verfuegbar] | | | [CategoryChips: Alle | Domain-Tools | Utils...] | | | | | | +--------+ +--------+ +--------+ | | | | Card 1 | | Card 2 | | Card 3 | | | | +--------+ +--------+ +--------+ | | | +--------+ +--------+ +--------+ | | | | Card 4 | | Card 5 | | Card 6 | | | | +--------+ +--------+ +--------+ | +--------+-------------------------------------------------+ ``` **Grid responsive breakpoints:** - Mobile (<768px): 1 column, sidebar hidden - Tablet (768px-1023px): 2 columns, sidebar collapsed or hidden - Desktop (1024px-1279px): 3 columns, sidebar expanded - Wide (1280px+): 4 columns, sidebar expanded **Grid gap:** 16px (`gap-4`) ### MarketplaceCard Anatomy ``` +------------------------------------------+ | [Icon 24x24] Module Name | | Category Badge Status Badge| | | | Localized description text, max 2 lines | | with line-clamp-2 truncation. | | | | v1.0.0 [Aktivieren] (button) | +------------------------------------------+ ``` - Card padding: 20px (`p-5`) - Card border: `border border-border` (1px) - Card background: `bg-card` - Card border-radius: 8px (`rounded-lg`) - Card hover: `hover:shadow-md hover:border-primary/30` (existing pattern) - Icon container: `rounded-md bg-muted p-2.5` (40px total, existing pattern) - Status badge (activated): `bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400` rounded-full px-2 py-0.5 text-xs - Status badge (available): `bg-muted text-muted-foreground` rounded-full px-2 py-0.5 text-xs - Category badge: `bg-muted text-muted-foreground` rounded-full px-2 py-0.5 text-xs - Activation button (activate): `bg-primary text-primary-foreground` rounded-md px-3 py-1.5 text-sm font-medium - Activation button (deactivate): `border border-border text-foreground hover:bg-muted` rounded-md px-3 py-1.5 text-sm font-medium ### Module Detail Page (`/marketplace/[slug]`) Compact detail view (appropriate for v1 module count). Single-column layout within main content area. ``` +------------------------------------------+ | < Zurueck zum Marktplatz | | | | [Icon 48x48] | | Module Name (h1, 20px bold) | | Category Badge v1.0.0 | | | | Full localized description text. | | No line clamping. Renders full text. | | | | Status: Aktiviert / Nicht aktiviert | | [Aktivieren / Deaktivieren] (button) | +------------------------------------------+ ``` - Back link: `text-sm text-muted-foreground hover:text-foreground` with left chevron icon - Icon container: `rounded-lg bg-muted p-4` (56px total) — larger than card icon - Max content width: `max-w-2xl` (672px) ### Sidebar Enhancement ``` Sidebar (240px expanded): +----------------------------------+ | [Dashboard icon] Dashboard | | [Cart icon] Marktplatz | +----------------------------------+ | [Search input _______________] | <-- NEW: SidebarSearch +----------------------------------+ | KATEGORIEN [chevron] | | [Folder] Domain Tools (1) | | - Domaincheck | | [Folder] Utilities (2) | | - Tool A | | - Tool B | +----------------------------------+ | VERWALTUNG | | [Users icon] Benutzer | | [Home icon] Mandanten | (Super-Admin only) | [Box icon] Module | | [Layers icon] LDAP | +----------------------------------+ | [Collapse] | | [User Info] | +----------------------------------+ Sidebar (64px collapsed): +--------+ | [Dash] | | [Cart] | +--------+ | [Usr] | | [Home] | (Super-Admin only) | [Box] | | [Lyrs] | +--------+ | [<] | | [Avtr] | +--------+ ``` **Sidebar Search (SidebarSearch):** - Position: Between main nav (Dashboard/Marketplace) and Categories section - Height: 36px - Padding: 8px horizontal within sidebar's 12px padding (`px-3` within `p-3` nav) - Placeholder text: "Module suchen..." (14px, muted-foreground) - Border: `border border-border rounded-md` - Focus: `focus:ring-2 focus:ring-ring focus:border-transparent` - Behavior: Filters visible module names and category names in real-time. Categories with no matching modules are hidden. - Collapsed sidebar: Search field hidden (not enough space at 64px) **Sidebar collapsed mode decision:** Show main navigation icons (Dashboard, Marketplace) and admin icons. Do NOT show individual module icons -- category/module list is hidden when collapsed. This keeps the collapsed sidebar clean and avoids icon overload. ### Tenant Context Selector ``` +------------------------------------------+ | Mandanten-Kontext: [Dropdown v] | | +--------------------------------------+ | | | Firma A GmbH [x] | | <-- currently selected | | Firma B AG | | | | Test-Mandant | | | +--------------------------------------+ | +------------------------------------------+ ``` - Position: Top of marketplace page, above title, only visible for `SUPER_ADMIN` role - Container: `bg-muted/50 rounded-lg p-3 mb-4 border border-border` - Label: "Mandanten-Kontext:" 12px semibold text-muted-foreground - Dropdown: Native `