From 94d3277e2e8f3999650b54dc6303df379dca4e47 Mon Sep 17 00:00:00 2001 From: Till JS Date: Tue, 28 Apr 2026 15:12:27 +0200 Subject: [PATCH] =?UTF-8?q?feat(feedback):=20"Idee=20teilen"=20lebt=20jetz?= =?UTF-8?q?t=20im=20PillNav-Usermen=C3=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ersetzt den schwebenden "Idee?"-Pill durch einen Eintrag im rechten Usermenü (Profil / Credits / Idee teilen / Logout). Ein Affordance an einer Stelle statt zwei nebeneinander. - PillNavigation: neuer onFeedback-Prop + Lightbulb-Icon. Wenn gesetzt, ersetzt der Eintrag den Legacy-/feedback-Link in accountLinks und taucht zusätzlich oben in den userMenuBarItems (barMode) auf. - UserMenuPanel: AccountLink kennt jetzt onClick? als Alternative zu href? — Action-Chips schließen das Panel direkt nach dem Klick. - (app)/+layout: GlobalFeedbackPill-Mount entfernt, FeedbackQuickModal wird state-gebunden gerendert (moduleContext aus Pfad/?app= abgeleitet wie bisher in der alten Pill). - GlobalFeedbackPill.svelte gelöscht — niemand referenziert sie mehr. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../feedback/GlobalFeedbackPill.svelte | 100 ------------------ .../apps/web/src/routes/(app)/+layout.svelte | 23 +++- .../src/navigation/PillNavigation.svelte | 37 ++++++- .../src/navigation/UserMenuPanel.svelte | 14 ++- 4 files changed, 65 insertions(+), 109 deletions(-) delete mode 100644 apps/mana/apps/web/src/lib/components/feedback/GlobalFeedbackPill.svelte diff --git a/apps/mana/apps/web/src/lib/components/feedback/GlobalFeedbackPill.svelte b/apps/mana/apps/web/src/lib/components/feedback/GlobalFeedbackPill.svelte deleted file mode 100644 index 8ca05aa22..000000000 --- a/apps/mana/apps/web/src/lib/components/feedback/GlobalFeedbackPill.svelte +++ /dev/null @@ -1,100 +0,0 @@ - - - -{#if !hidden} - - - (open = false)} /> -{/if} - - diff --git a/apps/mana/apps/web/src/routes/(app)/+layout.svelte b/apps/mana/apps/web/src/routes/(app)/+layout.svelte index e1e5a80e5..f11925b88 100644 --- a/apps/mana/apps/web/src/routes/(app)/+layout.svelte +++ b/apps/mana/apps/web/src/routes/(app)/+layout.svelte @@ -9,7 +9,7 @@ import { page } from '$app/stores'; import type { Component, Snippet } from 'svelte'; import ToastContainer from '$lib/components/ToastContainer.svelte'; - import GlobalFeedbackPill from '$lib/components/feedback/GlobalFeedbackPill.svelte'; + import FeedbackQuickModal from '$lib/components/feedback/FeedbackQuickModal.svelte'; import { onDestroy, setContext, tick } from 'svelte'; import { createReminderScheduler } from '@mana/shared-stores'; import { todoReminderSource } from '$lib/modules/todo/reminder-source'; @@ -251,6 +251,17 @@ let isBottomBarVisible = $state(false); let activeBar = $state(null); + // Quick-feedback modal — opened from the user-menu chip ("Idee teilen"). + // Replaces the older floating "Idee?" pill so feedback lives in the same + // affordance as Profile / Credits / Logout. + let feedbackModalOpen = $state(false); + let feedbackModuleContext = $derived.by(() => { + const path = $page.url.pathname; + const seg = path.split('/').filter(Boolean)[0]; + const fromPath = seg && !seg.startsWith('(') ? seg : null; + return $page.url.searchParams.get('app') ?? fromPath ?? undefined; + }); + function closeAllBars() { isTagStripVisible = false; isQuickInputVisible = false; @@ -1061,6 +1072,7 @@ creditsHref="/?app=credits" themesHref="/?app=themes" helpHref="/?app=help" + onFeedback={() => (feedbackModalOpen = true)} {spotlightActions} {contentSearcher} positioning="static" @@ -1139,9 +1151,12 @@ /> {/if} - - + + (feedbackModalOpen = false)} + /> diff --git a/packages/shared-ui/src/navigation/PillNavigation.svelte b/packages/shared-ui/src/navigation/PillNavigation.svelte index 66980e69d..3db57a988 100644 --- a/packages/shared-ui/src/navigation/PillNavigation.svelte +++ b/packages/shared-ui/src/navigation/PillNavigation.svelte @@ -52,6 +52,7 @@ Heart, House, Key, + Lightbulb, List, MagnifyingGlass, Microphone, @@ -135,6 +136,7 @@ scale: Scales, robot: Robot, key: Key, + lightbulb: Lightbulb, shield: Shield, gift: Gift, 'music-notes': MusicNotes, @@ -318,8 +320,13 @@ contentSearcher?: ContentSearcher; /** Accessible label for the nav element */ ariaLabel?: string; - /** Feedback page href (shown in user dropdown). Set to empty string to hide. */ + /** Feedback page href (shown in user dropdown). Set to empty string to hide. + * Ignored when `onFeedback` is provided — the action takes precedence. */ feedbackHref?: string; + /** Called when the user picks "Idee teilen" in the user menu. When set, + * the Feedback chip opens the host's quick-feedback modal instead of + * navigating to feedbackHref. */ + onFeedback?: () => void; /** Themes page href (shown in user dropdown). Set to empty string to hide. */ themesHref?: string; /** Spiral page href (shown in user dropdown). Set to empty string to hide. */ @@ -391,6 +398,7 @@ contentSearcher, ariaLabel, feedbackHref = '/feedback', + onFeedback, themesHref, spiralHref, creditsHref, @@ -461,7 +469,14 @@ // Account links for UserMenuPanel const accountLinks = $derived.by(() => { - const links: { id: string; label: string; icon: string; href: string; active?: boolean }[] = []; + const links: { + id: string; + label: string; + icon: string; + href?: string; + onClick?: () => void; + active?: boolean; + }[] = []; if (userEmail && profileHref) { links.push({ id: 'profile', @@ -489,7 +504,14 @@ active: currentPath === creditsHref, }); } - if (userEmail && feedbackHref) { + if (userEmail && onFeedback) { + links.push({ + id: 'feedback', + label: 'Idee teilen', + icon: 'lightbulb', + onClick: onFeedback, + }); + } else if (userEmail && feedbackHref) { links.push({ id: 'feedback', label: 'Feedback', @@ -533,6 +555,15 @@ // we don't duplicate it inside the opened bar. const userMenuBarItems = $derived.by(() => { const out: PillDropdownItem[] = []; + if (userEmail && onFeedback) { + out.push({ + id: 'feedback', + label: 'Idee teilen', + icon: 'lightbulb', + onClick: () => onFeedback(), + }); + out.push({ id: 'feedback-divider', label: '', divider: true }); + } if (onThemeModeChange) { out.push( { diff --git a/packages/shared-ui/src/navigation/UserMenuPanel.svelte b/packages/shared-ui/src/navigation/UserMenuPanel.svelte index 8986f6df4..73a9ae9e3 100644 --- a/packages/shared-ui/src/navigation/UserMenuPanel.svelte +++ b/packages/shared-ui/src/navigation/UserMenuPanel.svelte @@ -8,6 +8,7 @@ Gear, Globe, Heart, + Lightbulb, Moon, Palette, Question, @@ -36,6 +37,7 @@ sun: Sun, palette: Palette, robot: Robot, + lightbulb: Lightbulb, logout: SignOut, }; @@ -43,7 +45,8 @@ id: string; label: string; icon: string; - href: string; + href?: string; + onClick?: () => void; active?: boolean; } @@ -182,7 +185,14 @@