From 794b4dabfa67c4e071549e25aa98568fb13b36f4 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Fri, 13 Feb 2026 17:27:33 +0100 Subject: [PATCH] refactor(webapp): vue3 migration - button - icon + circle + loading (#9208) --- ..._open_the_content_menu_of_post_{string}.js | 2 +- ..._Post_from_the_content_menu_of_the_post.js | 2 +- .../I_should_see_the_{string}_button.js | 2 +- ...m_the_content_menu_in_the_user_info_box.js | 2 +- .../I_delete_a_social_media_link.js | 2 +- ...m_the_content_menu_in_the_user_info_box.js | 2 +- packages/ui/.storybook/storybook.css | 1 + packages/ui/KATALOG.md | 251 ++----- packages/ui/PROJEKT.md | 440 ++++++++--- .../src/components/OsButton/OsButton.spec.ts | 372 ++++++++++ .../components/OsButton/OsButton.stories.ts | 424 ++++++++++- .../OsButton/OsButton.visual.spec.ts | 81 +++ .../ui/src/components/OsButton/OsButton.vue | 183 ++++- .../chromium/circle-appearances.png | Bin 0 -> 14011 bytes .../__screenshots__/chromium/circle-sizes.png | Bin 0 -> 25790 bytes .../__screenshots__/chromium/circle.png | Bin 0 -> 8544 bytes .../chromium/icon-appearances.png | Bin 0 -> 17805 bytes .../__screenshots__/chromium/icon-only.png | Bin 0 -> 2477 bytes .../__screenshots__/chromium/icon-sizes.png | Bin 0 -> 6589 bytes .../__screenshots__/chromium/icon.png | Bin 0 -> 6891 bytes .../__screenshots__/chromium/loading.png | Bin 0 -> 18417 bytes .../components/OsButton/button.variants.ts | 10 +- packages/ui/src/styles/animations.css | 29 + packages/ui/src/styles/index.css | 1 + webapp/components/ActionButton.vue | 15 +- webapp/components/Button/FollowButton.spec.js | 6 +- webapp/components/Button/FollowButton.vue | 28 +- webapp/components/Button/JoinLeaveButton.vue | 28 +- .../JoinLeaveButton.spec.js.snap | 4 +- .../CategoriesSelect/CategoriesSelect.vue | 15 +- .../Chat/AddChatRoomByUserSearch.vue | 16 +- webapp/components/Chat/Chat.vue | 28 +- .../ChatNotificationMenu.vue | 14 +- webapp/components/CommentCard/CommentCard.vue | 14 +- webapp/components/CommentForm/CommentForm.vue | 105 +-- .../ComponentSlider/ComponentSlider.spec.js | 2 +- .../ComponentSlider/ComponentSlider.vue | 34 +- webapp/components/ContentMenu/ContentMenu.vue | 16 +- .../ContentMenu/GroupContentMenu.vue | 18 +- .../GroupContentMenu.spec.js.snap | 80 +- .../ContributionForm/ContributionForm.vue | 13 +- .../components/CustomButton/CustomButton.vue | 25 +- webapp/components/DeleteData/DeleteData.vue | 16 +- webapp/components/Editor/ContextMenu.vue | 6 +- webapp/components/Editor/Editor.vue | 11 +- webapp/components/Editor/MenuBar.vue | 180 +++-- webapp/components/Editor/MenuBarButton.vue | 16 - webapp/components/Editor/MenuLegend.vue | 40 +- webapp/components/Embed/EmbedComponent.vue | 20 +- .../EmotionButton/EmotionButton.vue | 15 +- .../CallToAction/CtaJoinLeaveGroup.spec.js | 2 +- .../Empty/CallToAction/CtaUnblockAuthor.vue | 10 +- .../CtaJoinLeaveGroup.spec.js.snap | 5 +- .../CtaUnblockAuthor.spec.js.snap | 4 +- webapp/components/EnterNonce/EnterNonce.vue | 8 +- .../FilterMenu/CategoriesFilter.spec.js | 15 +- .../FilterMenu/CategoriesFilter.vue | 31 +- .../FilterMenu/EmotionsFilter.spec.js.old | 8 +- .../components/FilterMenu/EventsByFilter.vue | 30 +- .../components/FilterMenu/FilterMenu.spec.js | 8 +- webapp/components/FilterMenu/FilterMenu.vue | 25 +- .../FilterMenu/FollowingFilter.spec.js | 18 +- .../components/FilterMenu/FollowingFilter.vue | 48 +- webapp/components/FilterMenu/HeaderButton.vue | 54 +- .../FilterMenu/LanguagesFilter.spec.js.old | 8 +- .../FilterMenu/OrderByFilter.spec.js | 28 +- .../components/FilterMenu/OrderByFilter.vue | 30 +- webapp/components/Group/GroupButton.vue | 19 +- webapp/components/Group/GroupForm.vue | 12 +- .../HashtagsFilter/HashtagsFilter.spec.js | 2 +- .../HashtagsFilter/HashtagsFilter.vue | 18 +- webapp/components/HeaderMenu/HeaderMenu.vue | 19 +- .../components/InviteButton/InviteButton.vue | 23 +- .../LoginButton/LoginButton.spec.js | 2 +- webapp/components/LoginButton/LoginButton.vue | 15 +- webapp/components/LoginForm/LoginForm.vue | 18 +- webapp/components/Map/MapButton.vue | 23 +- webapp/components/Modal/ConfirmModal.vue | 24 +- webapp/components/Modal/DeleteUserModal.vue | 17 +- webapp/components/Modal/DisableModal.vue | 14 +- webapp/components/Modal/ReportModal.vue | 38 +- .../NotificationMenu/NotificationMenu.vue | 51 +- webapp/components/Password/Change.spec.js | 8 - webapp/components/Password/Change.vue | 13 +- .../PasswordReset/ChangePassword.vue | 12 +- webapp/components/PasswordReset/Request.vue | 11 +- webapp/components/Registration/Signup.vue | 10 +- .../components/ReleaseModal/ReleaseModal.vue | 19 +- .../components/Select/LocationSelect.spec.js | 6 +- webapp/components/Select/LocationSelect.vue | 25 +- webapp/components/Uploader/ImageUploader.vue | 50 +- .../__snapshots__/ActionButton.spec.js.snap | 38 +- .../__snapshots__/ObserveButton.spec.js.snap | 38 +- .../__snapshots__/ShoutButton.spec.js.snap | 76 +- .../features/Invitations/CreateInvitation.vue | 14 +- .../_new/features/Invitations/Invitation.vue | 28 +- .../CreateInvitation.spec.js.snap | 38 +- .../__snapshots__/Invitation.spec.js.snap | 76 +- .../__snapshots__/InvitationList.spec.js.snap | 114 ++- .../MySomethingList/MySomethingList.spec.js | 12 +- .../MySomethingList/MySomethingList.vue | 41 +- .../generic/BaseButton/BaseButton.story.js | 85 --- .../_new/generic/BaseButton/BaseButton.vue | 201 ----- .../_new/generic/BaseCard/BaseCard.story.js | 79 -- .../generic/LabeledButton/LabeledButton.vue | 14 +- .../PaginationButtons/PaginationButtons.vue | 25 +- .../features/ProfileList/FollowList.spec.js | 6 +- .../features/ProfileList/ProfileList.vue | 11 +- .../features/ReportRow/ReportRow.spec.js | 2 +- .../features/ReportRow/ReportRow.vue | 14 +- .../SearchableInput/SearchableInput.vue | 22 +- webapp/locales/de.json | 21 +- webapp/locales/en.json | 21 +- webapp/locales/es.json | 21 +- webapp/locales/fr.json | 21 +- webapp/locales/it.json | 21 +- webapp/locales/nl.json | 21 +- webapp/locales/pl.json | 21 +- webapp/locales/pt.json | 21 +- webapp/locales/ru.json | 21 +- webapp/pages/admin/donations.spec.js | 4 +- webapp/pages/admin/donations.vue | 9 +- .../users/__snapshots__/index.spec.js.snap | 160 ++-- webapp/pages/admin/users/index.vue | 24 +- .../_id/__snapshots__/_slug.spec.js.snap | 688 ++++++++++++------ webapp/pages/groups/_id/_slug.vue | 43 +- .../_id/__snapshots__/invites.spec.js.snap | 57 +- webapp/pages/groups/index.vue | 19 +- webapp/pages/index.vue | 81 ++- webapp/pages/post/_id/_slug/index.vue | 17 +- .../_id/__snapshots__/_slug.spec.js.snap | 210 ++++-- webapp/pages/profile/_id/_slug.vue | 35 +- .../__snapshots__/notifications.spec.js.snap | 230 +++++- webapp/pages/settings/blocked-users.spec.js | 2 +- webapp/pages/settings/blocked-users.vue | 14 +- webapp/pages/settings/data-download.vue | 16 +- webapp/pages/settings/index.vue | 15 +- webapp/pages/settings/muted-users.spec.js | 2 +- webapp/pages/settings/muted-users.vue | 14 +- .../settings/my-email-address/enter-nonce.vue | 8 +- .../pages/settings/my-email-address/index.vue | 17 +- webapp/pages/settings/my-social-media.spec.js | 6 +- webapp/pages/settings/notifications.spec.js | 22 +- 143 files changed, 4230 insertions(+), 1936 deletions(-) create mode 100644 packages/ui/src/components/OsButton/__screenshots__/chromium/circle-appearances.png create mode 100644 packages/ui/src/components/OsButton/__screenshots__/chromium/circle-sizes.png create mode 100644 packages/ui/src/components/OsButton/__screenshots__/chromium/circle.png create mode 100644 packages/ui/src/components/OsButton/__screenshots__/chromium/icon-appearances.png create mode 100644 packages/ui/src/components/OsButton/__screenshots__/chromium/icon-only.png create mode 100644 packages/ui/src/components/OsButton/__screenshots__/chromium/icon-sizes.png create mode 100644 packages/ui/src/components/OsButton/__screenshots__/chromium/icon.png create mode 100644 packages/ui/src/components/OsButton/__screenshots__/chromium/loading.png create mode 100644 packages/ui/src/styles/animations.css delete mode 100644 webapp/components/Editor/MenuBarButton.vue delete mode 100644 webapp/components/_new/generic/BaseButton/BaseButton.story.js delete mode 100644 webapp/components/_new/generic/BaseButton/BaseButton.vue delete mode 100644 webapp/components/_new/generic/BaseCard/BaseCard.story.js diff --git a/cypress/support/step_definitions/Admin.PinPost/I_open_the_content_menu_of_post_{string}.js b/cypress/support/step_definitions/Admin.PinPost/I_open_the_content_menu_of_post_{string}.js index dca7b9e7f..822ee2068 100644 --- a/cypress/support/step_definitions/Admin.PinPost/I_open_the_content_menu_of_post_{string}.js +++ b/cypress/support/step_definitions/Admin.PinPost/I_open_the_content_menu_of_post_{string}.js @@ -2,6 +2,6 @@ import { defineStep } from '@badeball/cypress-cucumber-preprocessor' defineStep('I open the content menu of post {string}', (title) => { cy.contains('.post-teaser', title) - .find('.content-menu .base-button') + .find('[data-test="content-menu-button"]') .click() }) diff --git a/cypress/support/step_definitions/Moderation.ReportContent/I_click_on_Report_Post_from_the_content_menu_of_the_post.js b/cypress/support/step_definitions/Moderation.ReportContent/I_click_on_Report_Post_from_the_content_menu_of_the_post.js index bcfc362cd..810bf52b8 100644 --- a/cypress/support/step_definitions/Moderation.ReportContent/I_click_on_Report_Post_from_the_content_menu_of_the_post.js +++ b/cypress/support/step_definitions/Moderation.ReportContent/I_click_on_Report_Post_from_the_content_menu_of_the_post.js @@ -2,7 +2,7 @@ import { defineStep } from '@badeball/cypress-cucumber-preprocessor' defineStep('I click on "Report Post" from the content menu of the post', () => { cy.contains('.base-card', 'The Truth about the Holocaust') - .find('.content-menu .base-button') + .find('[data-test="content-menu-button"]') .click() cy.get('.popover .ds-menu-item-link') diff --git a/cypress/support/step_definitions/User.Block/I_should_see_the_{string}_button.js b/cypress/support/step_definitions/User.Block/I_should_see_the_{string}_button.js index a6e014130..88d331fa3 100644 --- a/cypress/support/step_definitions/User.Block/I_should_see_the_{string}_button.js +++ b/cypress/support/step_definitions/User.Block/I_should_see_the_{string}_button.js @@ -1,6 +1,6 @@ import { defineStep } from '@badeball/cypress-cucumber-preprocessor' defineStep('I should see the {string} button', button => { - cy.get('.base-card .action-buttons .base-button') + cy.get('.base-card .action-buttons button') .should('contain', button) }) diff --git a/cypress/support/step_definitions/User.Block/I_{string}_see_{string}_from_the_content_menu_in_the_user_info_box.js b/cypress/support/step_definitions/User.Block/I_{string}_see_{string}_from_the_content_menu_in_the_user_info_box.js index fa568efeb..f9d966299 100644 --- a/cypress/support/step_definitions/User.Block/I_{string}_see_{string}_from_the_content_menu_in_the_user_info_box.js +++ b/cypress/support/step_definitions/User.Block/I_{string}_see_{string}_from_the_content_menu_in_the_user_info_box.js @@ -1,7 +1,7 @@ import { defineStep } from '@badeball/cypress-cucumber-preprocessor' defineStep('I {string} see {string} from the content menu in the user info box', (condition, link) => { - cy.get('.user-content-menu .base-button').click() + cy.get('.user-content-menu [data-test="content-menu-button"]').click() cy.get('.popover .ds-menu-item-link') .should(condition === 'should' ? 'contain' : 'not.contain', link) }) diff --git a/cypress/support/step_definitions/UserProfile.SocialMedia/I_delete_a_social_media_link.js b/cypress/support/step_definitions/UserProfile.SocialMedia/I_delete_a_social_media_link.js index 4adf6d0d6..e075b3151 100644 --- a/cypress/support/step_definitions/UserProfile.SocialMedia/I_delete_a_social_media_link.js +++ b/cypress/support/step_definitions/UserProfile.SocialMedia/I_delete_a_social_media_link.js @@ -1,6 +1,6 @@ import { defineStep } from '@badeball/cypress-cucumber-preprocessor' defineStep('I delete a social media link', () => { - cy.get(".base-button[title='Delete']") + cy.get("button[title='Delete']") .click() }) diff --git a/cypress/support/step_definitions/common/I_click_on_{string}_from_the_content_menu_in_the_user_info_box.js b/cypress/support/step_definitions/common/I_click_on_{string}_from_the_content_menu_in_the_user_info_box.js index 8912b5974..676dc12c1 100644 --- a/cypress/support/step_definitions/common/I_click_on_{string}_from_the_content_menu_in_the_user_info_box.js +++ b/cypress/support/step_definitions/common/I_click_on_{string}_from_the_content_menu_in_the_user_info_box.js @@ -2,7 +2,7 @@ import { defineStep } from '@badeball/cypress-cucumber-preprocessor' defineStep('I click on {string} from the content menu in the user info box', button => { - cy.get('.user-content-menu .base-button').click() + cy.get('.user-content-menu [data-test="content-menu-button"]').click() cy.get('.popover .ds-menu-item-link') .contains(button) .click({ diff --git a/packages/ui/.storybook/storybook.css b/packages/ui/.storybook/storybook.css index bbca58d0d..ba41e93b2 100644 --- a/packages/ui/.storybook/storybook.css +++ b/packages/ui/.storybook/storybook.css @@ -1,4 +1,5 @@ @import "tailwindcss"; +@import "../src/styles/animations.css"; /* Watercolor theme for Storybook - vibrant colors inspired by aquarelle paints */ /* All colors meet WCAG AA contrast requirements (4.5:1 for normal text) */ diff --git a/packages/ui/KATALOG.md b/packages/ui/KATALOG.md index 6a5381dd5..0165d7001 100644 --- a/packages/ui/KATALOG.md +++ b/packages/ui/KATALOG.md @@ -10,9 +10,9 @@ ### Übersicht ``` Phase 0: Analyse ██████████ 100% (8/8 Schritte) -Phase 3: Migration ████░░░░░░ 36% (32/90 Buttons) +Phase 3: Migration ██████████ 100% (132/132 Buttons) ✅ ─────────────────────────────────────────── -Aktuelle Phase: Phase 3 - Milestone 4a ✅, nächster: Milestone 4b +Phase 3 ABGESCHLOSSEN: M4a ✅, M4b ✅, M4c ✅ — 0 verbleibend ``` ### Statistiken @@ -25,108 +25,30 @@ Aktuelle Phase: Phase 3 - Milestone 4a ✅, nächster: Milestone 4b | Duplikate gefunden | 5 direkte + 3 Familien | | Zur Migration priorisiert | 15 Kern-Komponenten | -### OsButton Migration (Phase 3) +### OsButton Migration (Phase 3) ✅ | Status | Anzahl | Details | |--------|--------|---------| -| ✅ Migriert | 32 | Erste Welle (16) + Milestone 4a (14) + NotificationMenu (2) | -| ⏳ Ausstehend (mit neuen Props) | ~60 | Milestone 4c (benötigen icon/circle/loading) | -| **Gesamt** | **~90** | In ~50 Dateien | +| ✅ Migriert | 132 | 78 Dateien, alle `` ersetzt | +| ⬜ Verbleibend | 0 | Nur BaseButton.vue Definition + Test/Snapshot-Dateien | +| **Gesamt** | **132** | **100% erledigt** | -**Migrierte Komponenten (32):** +**Alle 132 Buttons migriert in 78 Dateien ✅** -*Erste Welle (16):* -- UserTeaserPopover.vue (1 Button) -- GroupForm.vue (1 Button - Cancel) -- EmbedComponent.vue (2 Buttons - Cancel, Play Now) -- DonationInfo.vue (1 Button) -- CommentCard.vue (1 Button - Show More) -- MapStylesButtons.vue (1 Button) -- GroupMember.vue (1 Button) -- embeds.vue (2 Buttons) -- notifications.vue (3 Buttons) -- privacy.vue (1 Button) -- terms-and-conditions-confirm.vue (2 Buttons) +Migration vollständig abgeschlossen. 0 `` Tags verbleiben in Vue-Templates. -*Milestone 4a (14) ✅:* -- ✅ DisableModal.vue (1 Button - Cancel) -- ✅ DeleteUserModal.vue (1 Button - Cancel) -- ✅ ReleaseModal.vue (1 Button - Cancel) -- ✅ ContributionForm.vue (1 Button - Cancel) -- ✅ EnterNonce.vue (1 Button - Submit) -- ✅ MySomethingList.vue (1 Button - Cancel) -- ✅ ImageUploader.vue (2 Buttons - Crop) -- ✅ admin/donations.vue (1 Button - Save) -- ✅ profile/_id/_slug.vue (2 Buttons - Unblock, Unmute) -- ✅ settings/badges.vue (1 Button - Remove) -- ✅ notifications/index.vue (1 Button - Mark All Read) -- ✅ ReportRow.vue (1 Button - More Details) +**Erkenntnisse aus der Migration:** +- `type="submit"` muss explizit gesetzt werden (OsButton Default: `type="button"`) +- DsForm `errors` ist ein Objekt → `!!errors` für Boolean-Cast bei `:disabled` +- CSS `.base-button` Selektoren → `> button` oder `button` +- Position/Dimensions brauchen `!important` für Tailwind-Override +- Filter-Buttons nutzen `:appearance="condition ? 'filled' : 'outline'"` Pattern +- Circle-Buttons mit Icon: `` -*Sonstige (2):* -- ✅ NotificationMenu.vue (2 Buttons - Mark All Read, Notification Page) - -**Ausstehend - benötigen neue Props (~60):** - -*Button-Komponenten mit icon/circle/loading:* -- ActionButton.vue: 3 Buttons (icon, circle) -- LabeledButton.vue: 1 Button (icon) -- MenuBarButton.vue: 1 Button (icon) -- EmotionButton.vue: 1 Button (icon) -- ShoutButton.vue: 1 Button (icon) -- FollowButton.vue: 1 Button (icon, loading) -- JoinLeaveButton.vue: 1 Button (icon, loading) -- ObserveButton.vue: 1 Button (icon, loading) -- InviteButton.vue: 1 Button (icon, loading) -- MapButton.vue: 1 Button (icon) -- PaginationButtons.vue: 2 Buttons (icon, circle) - -*Navigation mit icon:* -- LocaleSwitch.vue: 1 Button (icon) -- HeaderMenu.vue: 2 Buttons (icon) -- AvatarMenu.vue: 1 Button (icon, circle) -- NotificationMenu.vue: 1 Button (icon, circle) -- ChatNotificationMenu.vue: 1 Button (icon, circle) -- FilterMenu.vue: 1 Button (icon) - -*Editor-Buttons:* -- Editor.vue: ~10 Toolbar-Buttons (icon) -- ContextMenu.vue: 3 Buttons (icon) -- LinkInput.vue: 2 Buttons (icon, circle) - -*Filter-Buttons:* -- CategoriesFilter.vue: 1 Button (icon) -- HashtagsFilter.vue: 1 Button (icon) -- DropdownFilter.vue: 1 Button (icon) -- FilterMenuSection.vue: 2 Buttons (icon) -- DateTimeRange.vue: 2 Buttons (icon) - -*Chat-Buttons:* -- Chat.vue: 2 Buttons (icon) -- AddChatRoomByUserSearch.vue: 1 Button (icon, circle) - -*Form-Buttons:* -- CommentForm.vue: 1 Button (icon, loading) -- SearchField.vue: 1 Button (icon, circle) -- ShowPassword.vue: 1 Button (icon) - -*Modal-Buttons:* -- ConfirmModal.vue: 1 Button (loading) -- ReportModal.vue: 1 Button (loading) - -*Feature-Buttons:* -- CreateInvitation.vue: 1 Button (icon) -- Invitation.vue: 1 Button (icon, circle) -- SocialMediaListItem.vue: 1 Button (icon, circle) -- Request.vue: 1 Button (icon, loading) -- GroupButton.vue: 1 Button (icon) -- CtaJoinLeaveGroup.vue: 1 Button (icon) -- data-download.vue: 1 Button (icon, loading) -- AddGroupMember.vue: 1 Button (icon) -- GroupForm.vue Submit: 1 Button (icon) - -*Page-Buttons:* -- CommentCard.vue Reply: 1 Button (icon, circle) -- EmbedComponent.vue Close: 1 Button (icon, circle) -- PostTeaser.vue: 2 Buttons (icon) +**Verbleibende Cleanup-Aufgaben:** +- [ ] Snapshot-Dateien aktualisieren (enthalten noch `base-button` Referenzen) +- [ ] Test-Dateien aktualisieren (Selektoren `.base-button` → `button` oder `os-button-stub`) +- [ ] BaseButton.vue Komponente ggf. entfernen (wenn nicht mehr referenziert) +- [ ] CSS-Selektor `.base-button` in ImageUploader.vue entfernen --- @@ -154,7 +76,7 @@ Aktuelle Phase: Phase 3 - Milestone 4a ✅, nächster: Milestone 4b ### Data Input | # | Komponente | Status | Webapp-Duplikat | Varianten | Priorität | Notizen | |---|------------|--------|-----------------|-----------|-----------|---------| -| 13 | Button | ⏳ Migration | BaseButton, CustomButton, ActionButton, ... | | | → OsButton (16/90 migriert) | +| 13 | Button | ⏳ Migration | BaseButton, CustomButton, ActionButton, ... | | | → OsButton (41/90 migriert) | | 14 | CopyField | ⬜ Ausstehend | | | | | | 15 | Form | ⬜ Ausstehend | | | | | | 16 | FormItem | ⬜ Ausstehend | | | | | @@ -219,7 +141,7 @@ Aktuelle Phase: Phase 3 - Milestone 4a ✅, nächster: Milestone 4b | 7 | BadgeSelection | ⬜ Ausstehend | Input | | | | 8 | Badges | ⬜ Ausstehend | Display | | | | 9 | BadgesSection | ⬜ Ausstehend | Display | | | -| 10 | BaseButton | ⏳ Migration | Button | Button | 🔄 → OsButton (16/90 migriert) | +| 10 | BaseButton | ⏳ Migration | Button | Button | 🔄 → OsButton (41/90 migriert) | | 11 | BaseCard | ⬜ Ausstehend | Layout | Card | 🔗 DUPLIKAT | | 12 | BaseIcon | ⬜ Ausstehend | Display | Icon | 🔗 DUPLIKAT | @@ -228,7 +150,7 @@ Aktuelle Phase: Phase 3 - Milestone 4a ✅, nächster: Milestone 4b |---|------------|--------|-----------|-------------------|---------| | 13 | CategoriesFilter | ⬜ Ausstehend | Filter | | | | 14 | CategoriesMenu | ⬜ Ausstehend | Navigation | Menu | | -| 15 | CategoriesSelect | ⬜ Ausstehend | Input | Select | | +| 15 | CategoriesSelect | ⏳ Teilweise | Input | Select | Buttons → OsButton (icon) | | 16 | ChangePassword | ⬜ Ausstehend | Feature | | Auth-spezifisch | | 17 | Change | ⬜ Ausstehend | Feature | | | | 18 | Chat | ⬜ Ausstehend | Feature | | Chat-spezifisch | @@ -241,12 +163,12 @@ Aktuelle Phase: Phase 3 - Milestone 4a ✅, nächster: Milestone 4b | 25 | ContentMenu | ⬜ Ausstehend | Navigation | Menu | | | 26 | ContentViewer | ⬜ Ausstehend | Display | | | | 27 | ContextMenu | ⬜ Ausstehend | Navigation | Menu | | -| 28 | ContributionForm | ⬜ Ausstehend | Feature | Form | Post-spezifisch | +| 28 | ContributionForm | ⏳ Teilweise | Feature | Form | Cancel → OsButton | | 29 | CounterIcon | ⬜ Ausstehend | Display | Icon | | | 30 | CountTo | ⬜ Ausstehend | Display | Number | Animation | | 31 | CreateInvitation | ⬜ Ausstehend | Feature | | | | 32 | CtaJoinLeaveGroup | ⬜ Ausstehend | Button | Button | 🔄 Button-Familie | -| 33 | CtaUnblockAuthor | ⬜ Ausstehend | Button | Button | 🔄 Button-Familie | +| 33 | CtaUnblockAuthor | ✅ Migriert | Button | Button | Button → OsButton (icon) | | 34 | CustomButton | ⬜ Ausstehend | Button | Button | 🔄 Button-Familie | ### D-E @@ -254,8 +176,8 @@ Aktuelle Phase: Phase 3 - Milestone 4a ✅, nächster: Milestone 4b |---|------------|--------|-----------|-------------------|---------| | 35 | DateTimeRange | ⬜ Ausstehend | Input | | | | 36 | DeleteData | ⬜ Ausstehend | Feature | | | -| 37 | DeleteUserModal | ⬜ Ausstehend | Feedback | Modal | 🔄 Modal-Familie | -| 38 | DisableModal | ⬜ Ausstehend | Feedback | Modal | 🔄 Modal-Familie | +| 37 | DeleteUserModal | ⏳ Teilweise | Feedback | Modal | 🔄 Modal-Familie, Buttons → OsButton | +| 38 | DisableModal | ⏳ Teilweise | Feedback | Modal | 🔄 Modal-Familie, Buttons → OsButton | | 39 | DonationInfo | ✅ Migriert | Display | | Button → OsButton | | 40 | Dropdown | ⬜ Ausstehend | Input | Select | | | 41 | DropdownFilter | ⬜ Ausstehend | Filter | Select | | @@ -265,7 +187,7 @@ Aktuelle Phase: Phase 3 - Milestone 4a ✅, nächster: Milestone 4b | 45 | EmotionButton | ⬜ Ausstehend | Button | Button | | | 46 | Emotions | ⬜ Ausstehend | Feature | | | | 47 | Empty | ⬜ Ausstehend | Feedback | Placeholder | | -| 48 | EnterNonce | ⬜ Ausstehend | Feature | | Auth | +| 48 | EnterNonce | ⏳ Teilweise | Feature | | Auth, Submit → OsButton | ### F-G | # | Komponente | Status | Kategorie | Styleguide-Pendant | Notizen | @@ -293,7 +215,7 @@ Aktuelle Phase: Phase 3 - Milestone 4a ✅, nächster: Milestone 4b | 65 | HashtagsFilter | ⬜ Ausstehend | Filter | | | | 66 | HeaderButton | ⬜ Ausstehend | Button | Button | 🔄 Button-Familie | | 67 | HeaderMenu | ⬜ Ausstehend | Navigation | Menu | | -| 68 | ImageUploader | ⬜ Ausstehend | Input | | | +| 68 | ImageUploader | ⏳ Teilweise | Input | | Crop-Buttons → OsButton | | 69 | index | ⬜ Ausstehend | ? | | Prüfen | | 70 | InternalPage | ⬜ Ausstehend | Layout | Page | | | 71 | Invitation | ⬜ Ausstehend | Feature | | | @@ -305,7 +227,7 @@ Aktuelle Phase: Phase 3 - Milestone 4a ✅, nächster: Milestone 4b | 77 | LoadingSpinner | ⬜ Ausstehend | Feedback | Spinner | 🔗 DUPLIKAT | | 78 | LocaleSwitch | ⬜ Ausstehend | Navigation | | | | 79 | LocationInfo | ⬜ Ausstehend | Display | | | -| 80 | LocationSelect | ⬜ Ausstehend | Input | Select | | +| 80 | LocationSelect | ⏳ Teilweise | Input | Select | Close-Button → OsButton (icon) | | 81 | LocationTeaser | ⬜ Ausstehend | Display | Card | | | 82 | LoginButton | ⬜ Ausstehend | Button | Button | | | 83 | LoginForm | ⬜ Ausstehend | Feature | Form | Auth | @@ -322,8 +244,8 @@ Aktuelle Phase: Phase 3 - Milestone 4a ✅, nächster: Milestone 4b | 90 | MenuBarButton | ⬜ Ausstehend | Button | Button | 🔄 Button-Familie | | 91 | MenuLegend | ⬜ Ausstehend | Navigation | | | | 92 | Modal | ⬜ Ausstehend | Feedback | Modal | 🔗 DUPLIKAT | -| 93 | MySomethingList | ⬜ Ausstehend | Display | List | | -| 94 | NotificationMenu | ⬜ Ausstehend | Navigation | Menu | | +| 93 | MySomethingList | ⏳ Teilweise | Display | List | Cancel → OsButton | +| 94 | NotificationMenu | ⏳ Teilweise | Navigation | Menu | 2/3 Buttons → OsButton | | 95 | NotificationsTable | ⬜ Ausstehend | Display | Table | | | 96 | ObserveButton | ⬜ Ausstehend | Button | Button | | | 97 | OrderByFilter | ⬜ Ausstehend | Filter | | | @@ -333,7 +255,7 @@ Aktuelle Phase: Phase 3 - Milestone 4a ✅, nächster: Milestone 4b |---|------------|--------|-----------|-------------------|---------| | 98 | PageFooter | ⬜ Ausstehend | Layout | | | | 99 | PageParamsLink | ⬜ Ausstehend | Navigation | | | -| 100 | PaginationButtons | ⬜ Ausstehend | Navigation | | | +| 100 | PaginationButtons | ✅ Migriert | Navigation | | 2 Buttons → OsButton (icon, circle) | | 101 | PostTeaser | ⬜ Ausstehend | Display | Card | | | 102 | PostTypeFilter | ⬜ Ausstehend | Filter | | | | 103 | ProfileAvatar | ⬜ Ausstehend | Display | Avatar | | @@ -345,10 +267,10 @@ Aktuelle Phase: Phase 3 - Milestone 4a ✅, nächster: Milestone 4b | 109 | RegistrationSlideNonce | ⬜ Ausstehend | Feature | | Auth | | 110 | RegistrationSlideNoPublic | ⬜ Ausstehend | Feature | | Auth | | 111 | RegistrationSlider | ⬜ Ausstehend | Feature | | Auth | -| 112 | ReleaseModal | ⬜ Ausstehend | Feedback | Modal | 🔄 Modal-Familie | +| 112 | ReleaseModal | ⏳ Teilweise | Feedback | Modal | 🔄 Modal-Familie, Cancel → OsButton | | 113 | ReportList | ⬜ Ausstehend | Display | List | | | 114 | ReportModal | ⬜ Ausstehend | Feedback | Modal | 🔄 Modal-Familie | -| 115 | ReportRow | ⬜ Ausstehend | Display | | | +| 115 | ReportRow | ⏳ Teilweise | Display | | More Details → OsButton | | 116 | ReportsTable | ⬜ Ausstehend | Display | Table | | | 117 | Request | ⬜ Ausstehend | Feature | | | | 118 | ResponsiveImage | ⬜ Ausstehend | Display | | | @@ -484,6 +406,9 @@ Diese sollten zuerst migriert werden: | 2026-02-08 | Claude | OsButton erweitert | attrs/listeners Forwarding für Vue 2 ($listeners) | | 2026-02-09 | Claude | Scope erweitert | ~90 Buttons identifiziert (16 migriert, 14 ohne Props, ~60 mit Props) | | 2026-02-09 | Claude | **Milestone 4a: 8 Buttons** | DisableModal, DeleteUserModal, ReleaseModal, ContributionForm, EnterNonce, MySomethingList, ImageUploader (2x) | +| 2026-02-09 | Claude | **Milestone 4a abgeschlossen** | 6 weitere: donations, profile (2x), badges, notifications/index, ReportRow | +| 2026-02-11 | Claude | **M4b: icon + circle** | icon-Slot implementiert, circle-Prop mit CVA | +| 2026-02-11 | Claude | **9 icon-Buttons migriert (M4c)** | DisableModal, DeleteUserModal, CtaUnblockAuthor, LocationSelect, CategoriesSelect, my-email-address, profile Chat, PaginationButtons (2x circle) | --- @@ -504,18 +429,18 @@ Diese sollten zuerst migriert werden: 10. [x] Webapp-Integration (Jest, Docker, CI) 11. [x] 16 Buttons migrieren (validiert ✅) -**Milestone 4a: 14 Buttons ohne neue Props** -12. [ ] Modal Cancel-Buttons (3) -13. [ ] Form Cancel/Submit-Buttons (3) -14. [ ] ImageUploader Crop-Buttons (2) -15. [ ] Page Buttons (6) +**Milestone 4a: 14 Buttons ohne neue Props** ✅ +12. [x] Modal Cancel-Buttons (3) +13. [x] Form Cancel/Submit-Buttons (3) +14. [x] ImageUploader Crop-Buttons (2) +15. [x] Page Buttons (6) -**Milestone 4b: Props für ~60 Buttons hinzufügen** -16. [ ] icon-Prop zu OsButton hinzufügen -17. [ ] circle-Variant zu OsButton hinzufügen +**Milestone 4b: Props für ~49 Buttons hinzufügen** +16. [x] icon-Slot zu OsButton hinzufügen ✅ +17. [x] circle-Variant zu OsButton hinzufügen ✅ 18. [ ] loading-Prop zu OsButton hinzufügen -**Milestone 4c: ~60 Buttons mit neuen Props migrieren** +**Milestone 4c: ~49 Buttons mit neuen Props migrieren** 19. [ ] Button-Komponenten (~15) 20. [ ] Navigation (~8) 21. [ ] Editor (~15) @@ -1213,7 +1138,7 @@ $box-shadow-small-inset: inset 0 0 0 1px rgba(0,0,0,.05) ## Phase 3: Webapp-Integration (Tracking) -### OsButton Migration - Abgeschlossen (16/90) +### OsButton Migration - Abgeschlossen (132/132) ✅ | # | Datei | Button | Status | |---|-------|--------|--------| @@ -1234,70 +1159,34 @@ $box-shadow-small-inset: inset 0 0 0 1px rgba(0,0,0,.05) | 15 | terms-and-conditions-confirm.vue | Read T&C | ✅ Migriert | | 16 | terms-and-conditions-confirm.vue | Save | ✅ Migriert | -### OsButton Migration - Ausstehend ohne neue Props (Milestone 4a: 14/90) +### OsButton Migration - Alle Milestones abgeschlossen ✅ -| # | Datei | Button | OsButton Props | Status | -|---|-------|--------|----------------|--------| -| 17 | Modal/DisableModal.vue | Cancel | `default` | ⬜ Ausstehend | -| 18 | Modal/DeleteUserModal.vue | Cancel | `default` | ⬜ Ausstehend | -| 19 | Modal/ReleaseModal.vue | Cancel | `default` | ⬜ Ausstehend | -| 20 | ContributionForm.vue | Cancel | `:disabled` | ⬜ Ausstehend | -| 21 | EnterNonce.vue | Submit | `variant="primary" :disabled` | ⬜ Ausstehend | -| 22 | MySomethingList.vue | Cancel | `default` | ⬜ Ausstehend | -| 23 | ImageUploader.vue | Crop Confirm 1 | `variant="primary"` | ⬜ Ausstehend | -| 24 | ImageUploader.vue | Crop Confirm 2 | `variant="primary"` | ⬜ Ausstehend | -| 25 | admin/donations.vue | Save | `variant="primary"` | ⬜ Ausstehend | -| 26 | profile/_id/_slug.vue | Unblock | `default` | ⬜ Ausstehend | -| 27 | profile/_id/_slug.vue | Unmute | `default` | ⬜ Ausstehend | -| 28 | settings/badges.vue | Remove | `default` | ⬜ Ausstehend | -| 29 | notifications/index.vue | Mark All Read | `variant="primary" :disabled` | ⬜ Ausstehend | -| 30 | ReportRow.vue | More Details | `size="sm"` | ⬜ Ausstehend | +| Milestone | Status | Details | +|-----------|--------|---------| +| M4a: Buttons ohne neue Props | ✅ | 14 Buttons (Modals, Forms, Pages) | +| M4b: Props implementieren | ✅ | icon (Slot), circle, loading | +| M4c: Buttons mit icon/circle/loading | ✅ | Alle verbleibenden Buttons migriert | -### OsButton Migration - Ausstehend mit neuen Props (Milestone 4c: ~60/90) +### OsButton Features - Alle implementiert ✅ -> Diese Buttons benötigen icon, circle, und/oder loading Props. -> Siehe "Ausstehend - benötigen neue Props (~60)" oben für vollständige Liste. - -**Kategorien:** -| Kategorie | Anzahl | Props benötigt | -|-----------|--------|----------------| -| Button-Komponenten | ~15 | icon, circle, loading | -| Navigation | ~8 | icon, circle | -| Editor | ~15 | icon | -| Filter/Chat | ~10 | icon, circle | -| Forms/Modals | ~5 | icon, loading | -| Features/Pages | ~12 | icon, circle, loading | - -### Fehlende OsButton-Features - -| Feature | Benötigt für | Status | -|---------|-------------|--------| -| `icon` Prop | ~55 Buttons | ⬜ Fehlt | -| `circle` Variant | ~25 Buttons | ⬜ Fehlt | -| `loading` Prop | ~10 Buttons | ⬜ Fehlt | -| `appearance="outline"` | ✅ Implementiert | ✅ Erledigt | -| `appearance="ghost"` | ✅ Implementiert | ✅ Erledigt | +| Feature | Status | +|---------|--------| +| `variant` (7 Varianten) | ✅ | +| `appearance` (filled/outline/ghost) | ✅ | +| `size` (xs/sm/md/lg/xl) | ✅ | +| `icon` Slot | ✅ | +| `circle` Prop | ✅ | +| `loading` Prop | ✅ | +| `disabled` mit hover/active-Override | ✅ | +| `fullWidth` Prop | ✅ | +| `type` Prop (button/submit/reset) | ✅ | ### Nächste Schritte -**Milestone 4a: 14 Buttons ohne neue Props migrieren** -1. Modal Cancel-Buttons (3) -2. Form Cancel/Submit-Buttons (3) -3. ImageUploader Crop-Buttons (2) -4. Page Buttons (6) - -**Milestone 4b: Props für ~60 Buttons hinzufügen** -1. Icon-Prop zu OsButton hinzufügen -2. Circle-Variant zu OsButton hinzufügen -3. Loading-Prop zu OsButton hinzufügen - -**Milestone 4c: ~60 Buttons mit neuen Props migrieren** -1. Button-Komponenten (~15) -2. Navigation (~8) -3. Editor (~15) -4. Filter/Chat (~10) -5. Forms/Modals (~5) -6. Features/Pages (~12) +1. Snapshot-Dateien aktualisieren +2. Test-Selektoren anpassen +3. BaseButton.vue ggf. entfernen +4. Phase 4: Weitere Komponenten (OsIcon, OsCard, OsModal, ...) ### Integrations-Protokoll diff --git a/packages/ui/PROJEKT.md b/packages/ui/PROJEKT.md index e110ff28e..adc35f605 100644 --- a/packages/ui/PROJEKT.md +++ b/packages/ui/PROJEKT.md @@ -80,11 +80,11 @@ Phase 0: ██████████ 100% (6/6 Aufgaben) ✅ Phase 1: ██████████ 100% (6/6 Aufgaben) ✅ Phase 2: ██████████ 100% (26/26 Aufgaben) ✅ -Phase 3: █████████░ 83% (20/24 Aufgaben) - Webapp-Integration (M4a ✅, M5 ✅) +Phase 3: ██████████ 100% (24/24 Aufgaben) ✅ - Webapp-Integration komplett Phase 4: █░░░░░░░░░ 6% (1/17 Aufgaben) - OsButton ✅ Phase 5: ░░░░░░░░░░ 0% (0/7 Aufgaben) ─────────────────────────────────────── -Gesamt: ███████░░░ 69% (59/86 Aufgaben) +Gesamt: ████████░░ 74% (63/86 Aufgaben) ``` ### Katalogisierung (Details in KATALOG.md) @@ -94,30 +94,31 @@ Styleguide: ██████████ 100% (38 Komponenten erfasst) Analyse: ██████████ 100% (Button, Modal, Menu detailiert) ``` -### OsButton Migration (Phase 3) +### OsButton Migration (Phase 3) ✅ ``` -Scope gesamt: ~90 Buttons in Webapp -├─ Migriert: 32 Buttons (36%) ✅ -├─ Ohne neue Props: 0 Buttons (Milestone 4a ✅) -└─ Mit icon/circle/loading: ~60 Buttons (Milestone 4c) +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: ✅ xs, sm, md, lg, xl +├─ size: ✅ sm, md, lg, xl ├─ disabled: ✅ mit hover/active-Override -├─ icon: ⬜ TODO (Milestone 4b) -├─ circle: ⬜ TODO (Milestone 4b) -└─ loading: ⬜ TODO (Milestone 4b) +├─ 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-10 (Session 12) +**Letzte Aktualisierung:** 2026-02-13 (Session 19) -**Aktuelle Phase:** Phase 3 (Webapp-Integration) - Milestone 4a abgeschlossen ✅ (32 Buttons migriert, nächster: Milestone 4b) +**Aktuelle Phase:** Phase 3 ✅ ABGESCHLOSSEN + Code-Review-Feedback eingearbeitet **Zuletzt abgeschlossen:** - [x] Projektordner erstellt @@ -183,11 +184,171 @@ OsButton Features: - Completeness Check (verify Script prüft Story, Visual, checkA11y, Keyboard, Varianten) - ESLint Plugins: vuejs-accessibility, playwright, storybook, jsdoc -**Aktuell in Arbeit:** -- Phase 3, Milestone 4b: icon/circle/loading Props in OsButton implementieren -- Phase 3, Milestone 4c: ~60 Buttons mit icon/circle/loading migrieren +**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 12 - CSS-Linting, CI-Optimierung, Code-Review Fixes):** +**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 (`