# @ocelot-social/ui - Projektdokumentation > Dieses Dokument dient als zentrale Planungs- und Statusübersicht für das UI-Library Subprojekt. > Es ermöglicht das Pausieren und Wiederaufnehmen der Arbeit zu jedem Zeitpunkt. --- ## Inhaltsverzeichnis ### Schnellzugriff (Status) | Abschnitt | Beschreibung | |-----------|--------------| | [Fortschritt](#fortschritt) | Visuelle Fortschrittsanzeige | | [Aktueller Stand](#aktueller-stand) | Was zuletzt erledigt wurde | | [Meilensteine](#meilensteine) | Phasen 0-5 mit Checklisten | ### Nach Thema **[VISION](#vision)** | # | Abschnitt | |---|-----------| | 1 | [Projektziel & Vision](#1-projektziel--vision) | **[TECHNISCHE GRUNDLAGEN](#technische-grundlagen)** | # | Abschnitt | |---|-----------| | 2 | [Tech-Stack](#2-tech-stack) | | 3 | [Build & Distribution](#3-build--distribution) | | 4 | [Icon-Architektur](#4-icon-architektur) | | 5 | [Design-Token & Branding](#5-design-token--branding) | **[PROZESSE & QUALITÄT](#prozesse--qualität)** | # | Abschnitt | |---|-----------| | 6 | [CI/CD & Release](#6-cicd--release) | | 7 | [Dokumentation & DX](#7-dokumentation--dx) | | 8 | [Migrationsstrategie](#8-migrationsstrategie) | | 9 | [Dokumentationsstrategie](#9-dokumentationsstrategie) | | 10 | [Kompatibilitätstests](#10-kompatibilitätstests) | **[REFERENZ & HISTORIE](#referenz--historie)** | # | Abschnitt | |---|-----------| | 11 | [Entscheidungen](#11-entscheidungen) | | 12 | [Arbeitsprotokoll](#12-arbeitsprotokoll) | | 13 | [Komponenten-Katalog](#13-komponenten-katalog) | | 14 | [Ressourcen & Links](#14-ressourcen--links) | | 15 | [Dokumentationsstrategie (Details)](#15-dokumentationsstrategie-details) | **[ABGRENZUNGEN](#abgrenzungen)** | # | Abschnitt | |---|-----------| | 16 | [Library vs. Webapp](#16-library-vs-webapp) | | 16a | [Webapp ↔ Maintenance Code-Sharing](#16a-webapp--maintenance-code-sharing) | | 16b | [Daten-Entkopplung (ViewModel/Mapper)](#16b-daten-entkopplung-viewmodelmapper-pattern) | | 17 | [Externe Abhängigkeiten](#17-externe-abhängigkeiten) | | 18 | [Kompatibilitätstests (Details)](#18-kompatibilitätstests-details) | | 19 | [Komplexitätsanalyse](#19-komplexitätsanalyse) | --- ### Wie dieses Dokument verwendet wird **Zum Fortsetzen der Arbeit:** > "Lass uns am @ocelot-social/ui Projekt weiterarbeiten" (packages/ui) **Nach jeder Session aktualisieren:** - "Fortschritt" – Balkendiagramme aktualisieren - "Aktueller Stand" – Zuletzt erledigte Aufgaben - "Meilensteine" – Checklisten abhaken - §12 "Arbeitsprotokoll" – Neue Einträge hinzufügen - `KATALOG.md` – Komponenten-Status pflegen --- ## Fortschritt ### Gesamtprojekt ``` Phase 0: ██████████ 100% (6/6 Aufgaben) ✅ Phase 1: ██████████ 100% (6/6 Aufgaben) ✅ Phase 2: ██████████ 100% (26/26 Aufgaben) ✅ Phase 3: ██████████ 100% (24/24 Aufgaben) ✅ - Webapp-Integration komplett Phase 4: █░░░░░░░░░ 6% (1/17 Aufgaben) - OsButton ✅ Phase 5: ░░░░░░░░░░ 0% (0/7 Aufgaben) ─────────────────────────────────────── Gesamt: ████████░░ 74% (63/86 Aufgaben) ``` ### Katalogisierung (Details in KATALOG.md) ``` Webapp: ██████████ 100% (139 Komponenten erfasst) Styleguide: ██████████ 100% (38 Komponenten erfasst) Analyse: ██████████ 100% (Button, Modal, Menu detailiert) ``` ### OsButton Migration (Phase 3) ✅ ``` Scope gesamt: 133 Tags in 79 Webapp-Dateien ├─ Migriert: 133 Buttons (100%) ✅ ├─ : 0 verbleibend in Templates ├─ : 0 verbleibend in Templates └─ Cleanup: Snapshots/Tests müssen aktualisiert werden OsButton Features: ├─ variant: ✅ primary, secondary, danger, warning, success, info, default ├─ appearance: ✅ filled, outline, ghost ├─ size: ✅ sm, md, lg, xl ├─ disabled: ✅ mit hover/active-Override ├─ icon: ✅ slot-basiert (icon-system-agnostisch) ├─ circle: ✅ rounded-full, größenabhängig (p-1.5 bis p-3) └─ loading: ✅ animated SVG spinner, aria-busy (Milestone 4b) ``` --- ## Aktueller Stand **Letzte Aktualisierung:** 2026-02-13 (Session 19) **Aktuelle Phase:** Phase 3 ✅ ABGESCHLOSSEN + Code-Review-Feedback eingearbeitet **Zuletzt abgeschlossen:** - [x] Projektordner erstellt - [x] Planungsdokument erstellt - [x] Tech-Stack entschieden - [x] Branding-Architektur definiert - [x] Migrationsstrategie definiert - [x] **Phase 0: Komponenten-Analyse** (177 Komponenten katalogisiert) - [x] Button-Familie detailiert analysiert (Props, Styles, Konsolidierung) - [x] Modal-Familie detailiert analysiert (Architektur erkannt) - [x] Menu-Familie detailiert analysiert (3 Patterns identifiziert) - [x] Priorisierung erstellt (15 Komponenten in 4 Tiers) - [x] Konsolidierungsplan finalisiert - [x] **Phase 1: Vue 2.7 Upgrade** ✅ - Vue 2.6.14 → 2.7.16 - vue-template-compiler entfernt - @vue/composition-api entfernt - @nuxtjs/composition-api entfernt - Webpack-Alias für @vue/composition-api → vue - Webpack-Regel für ESM .mjs Module - **Unit-Tests: 157 Suites, 979 passed, 87 Snapshots** ✅ - **Integrationstests: bestanden** ✅ - [x] **Phase 2: Projekt-Setup** ✅ - Vite + Vue 3 Projekt initialisiert - vue-demi für Vue 2/3 Kompatibilität - Vitest konfiguriert (integriert in vite.config.ts) - npm Package-Struktur mit korrekten exports - README.md Grundgerüst - LICENSE (Apache 2.0) - Plugin-Tests geschrieben - Tailwind CSS v4 mit @tailwindcss/vite - Dual-Build (style.css + tailwind.preset) - Dark Mode Grundstruktur (via Tailwind dark: Prefix) - Prop-Types definiert (Size, Rounded, Shadow, Variant) - Branding-Architektur (keine Defaults, validateCssVariables) - eslint-config-it4c eingerichtet (v0.8.0) - ESLint Flat Config mit Vue 3 + Vitest Modulen - Prettier-Integration via eslint-plugin-prettier - GitHub Workflows (ui-lint.yml, ui-test.yml, ui-build.yml) - 100% Test-Coverage Requirement - .tool-versions (Node 25.5.0, konsistent mit Dockerfiles) - Example Apps für Kompatibilitätstests (4er-Matrix) - GitHub Workflow ui-compatibility.yml für Vue 2/3 Tests (inkl. Lint) - Eigene ESLint + Prettier Configs für Example Apps - Type Assertions für CI-Kompatibilität (`as unknown as Plugin`) - Bundle Size Check (size-limit) mit ui-size.yml Workflow - Package-Validierung (publint, arethetypeswrong) mit CJS/ESM Types - Kompatibilitätstest-Workflow mit 4 Example Apps (Vue 2/3 × Tailwind/CSS) - release-please Manifest-Konfiguration (Monorepo-Setup) - npm Publish Workflow (ui-release.yml) - CONTRIBUTING.md (Entwickler-Leitfaden) - Dependabot für UI-Package und Example Apps konfiguriert - CSS-Build separat via Tailwind CLI (closeBundle Hook) - CVA (class-variance-authority) für typsichere Varianten - cn() Utility für Tailwind-Klassen-Merge (clsx + tailwind-merge) - OsButton Komponente mit CVA-Varianten implementiert - ESLint-Konfiguration angepasst (vue/max-attributes-per-line, import-x/no-relative-parent-imports) - Storybook 10 für Dokumentation eingerichtet (Wasserfarben-Theme) - OsButton.stories.ts mit Playground + allen Varianten/Appearances/Sizes - Storybook Build-Konfiguration (viteFinal entfernt Library-Plugins) - Docker Setup (Dockerfile, docker-compose, ui-docker.yml) - Visual Regression Tests (Playwright, colocated) mit integriertem A11y-Check - Completeness Check (verify Script prüft Story, Visual, checkA11y, Keyboard, Varianten) - ESLint Plugins: vuejs-accessibility, playwright, storybook, jsdoc **Zuvor abgeschlossen (Session 18 - CodeRabbit Review Feedback: data-test Selektoren, Accessibility, Bugfixes):** - [x] Cypress-Selektoren: `.user-content-menu button` → `[data-test="content-menu-button"]` (2 Step-Definitions) - [x] Cypress-Selektoren: `.content-menu button` → `[data-test="content-menu-button"]` (Admin.PinPost + ReportContent) - [x] muted-users.vue: `data-test="unmute-btn"` + `aria-label` auf Unmute-Button - [x] blocked-users.vue: `data-test="unblock-btn"` + `aria-label` auf Unblock-Button - [x] ProfileList.vue: `data-test="load-all-connections-btn"` + FollowList.spec.js Selektoren aktualisiert - [x] FollowButton.vue: `data-test="follow-btn"` + Spec-Selektoren aktualisiert - [x] JoinLeaveButton.vue: `data-test="join-leave-btn"` + `.native` von `@mouseenter`/`@mouseleave` entfernt - [x] LoginButton.vue: `data-test="login-btn"` + `aria-label="$t('login.login')"` + Spec-Selektoren aktualisiert - [x] ReportRow.spec.js: `button[data-variant="danger"]` → `[data-test="confirm"]` - [x] CtaJoinLeaveGroup.spec.js: Selektor auf `[data-test="join-leave-btn"]` aktualisiert - [x] DisableModal.vue: `finally { this.loading = false }` für Loading-State-Reset - [x] ReleaseModal.vue: `:loading="loading"` + `this.loading = true` + `finally { this.loading = false }` - [x] ChangePassword.vue: `:disabled="errors"` → `:disabled="!!errors"` (Boolean-Cast) - [x] Password/Change.vue: Unbenutzte `disabled: true` aus data() entfernt + 2 tote Tests entfernt - [x] MenuBar.vue: Unbenutztes `ref="linkButton"` entfernt - [x] GroupForm.vue: Cancel-Button `variant="default" appearance="filled"` (per User-Anweisung) - [x] `appearance="filled"` ergänzt: donations.vue, LoginForm.vue, EnterNonce.vue - [x] LoginForm.vue: CSS `.login-form button` → `.login-form button[type='submit']` - [x] pages/index.vue: Redundantes `class="my-filter-button"` von `` entfernt - [x] MySomethingList.vue: `:title` + `:aria-label` auf Edit/Delete-Buttons (Tooltip beibehalten) - [x] A11y aria-label auf icon-only Buttons: admin/users (search + edit), AddChatRoomByUserSearch (close), EmbedComponent (close), groups/index (create), profile/_id/_slug (new post), groups/_id/_slug (new post), CustomButton (2x tooltip), HeaderMenu (hamburger), ImageUploader (crop-cancel), ContentMenu (menu), HeaderButton (filter-remove), InviteButton (invite) - [x] post/_id/_slug/index.vue: Zustandsabhängiges `aria-label` (`post.sensitiveContent.show/hide`) - [x] ComponentSlider.vue: `aria-label` mit Interpolation (`component-slider.step`) - [x] i18n: `actions.search`, `actions.close`, `actions.menu` in allen 9 Sprachdateien - [x] i18n: `site.navigation` in allen 9 Sprachdateien - [x] i18n: `post.sensitiveContent.show/hide` in allen 9 Sprachdateien - [x] i18n: `component-slider.step` in allen 9 Sprachdateien **Zuletzt abgeschlossen (Session 19 - CodeRabbit Review Feedback: Cleanup, Accessibility, Bugfixes):** - [x] donations.vue: Redundantes `:checked="showDonations"` entfernt (v-model setzt checked bereits) - [x] MySomethingList.vue: Disabled-Logik vereinfacht `!(!isEditing || (isEditing && !disabled))` → `isEditing && disabled` - [x] button.variants.ts: Hardcoded Fallback `#e5e3e8` entfernt → `var(--color-disabled)` (konsistent mit filled/index.css) - [x] CommentCard.vue: `aria-label` auf icon-only Reply-Button - [x] HashtagsFilter.vue: `aria-label` auf icon-only Clear-Button - [x] ReleaseModal.vue: `$emit('close')` im catch-Block ergänzt (fehlte im Fehlerfall) - [x] Chat.vue: `aria-label` auf Expand- und Close-Buttons - [x] i18n: `chat.expandChat` + `chat.closeChat` in allen 9 Sprachdateien (vollständig übersetzt) - [x] ChatNotificationMenu.vue: `aria-label` auf icon-only Chat-Button - [x] SearchableInput.vue: `aria-label` auf icon-only Close-Button - [x] GroupButton.vue: `aria-label` auf icon-only Groups-Button - [x] MapButton.vue: `aria-label` auf icon-only Map-Button - [x] EmotionButton.vue: `aria-label` auf icon-only Emoji-Button (`