mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 21:41:09 +02:00
feat(feedback): "Idee teilen" lebt jetzt im PillNav-Usermenü
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) <noreply@anthropic.com>
This commit is contained in:
parent
eaa1d7432b
commit
94d3277e2e
4 changed files with 65 additions and 109 deletions
|
|
@ -1,100 +0,0 @@
|
|||
<!--
|
||||
GlobalFeedbackPill — fallback feedback affordance for routes outside
|
||||
ModuleShell (settings, profile, dashboards). Sits bottom-right, tucked
|
||||
above the bottom-stack chrome.
|
||||
|
||||
Auto-detects module-context from the URL (e.g. `/todo` → `todo`,
|
||||
`/?app=notes` → `notes`); otherwise leaves moduleContext undefined.
|
||||
Hides itself on /onboarding and on /feedback + /community pages where
|
||||
the affordance would be redundant.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { Lightbulb } from '@mana/shared-icons';
|
||||
import { authStore } from '$lib/stores/auth.svelte';
|
||||
import FeedbackQuickModal from './FeedbackQuickModal.svelte';
|
||||
|
||||
let open = $state(false);
|
||||
|
||||
let path = $derived($page.url.pathname);
|
||||
let activeAppParam = $derived($page.url.searchParams.get('app'));
|
||||
|
||||
let hidden = $derived(
|
||||
path.startsWith('/onboarding') ||
|
||||
path.startsWith('/feedback') ||
|
||||
path.startsWith('/community') ||
|
||||
!authStore.user
|
||||
);
|
||||
|
||||
let moduleContext = $derived.by(() => {
|
||||
// Path-based detection: /todo, /notes, /picture, …
|
||||
const seg = path.split('/').filter(Boolean)[0];
|
||||
const fromPath = seg && !seg.startsWith('(') ? seg : null;
|
||||
// Workbench `?app=` param wins (homepage scene mode).
|
||||
return activeAppParam ?? fromPath ?? undefined;
|
||||
});
|
||||
|
||||
function handleClick() {
|
||||
open = true;
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if !hidden}
|
||||
<button
|
||||
type="button"
|
||||
class="pill"
|
||||
onclick={handleClick}
|
||||
title="Idee oder Feedback?"
|
||||
aria-label="Feedback geben"
|
||||
>
|
||||
<Lightbulb size={18} weight="bold" />
|
||||
<span class="label">Idee?</span>
|
||||
</button>
|
||||
|
||||
<FeedbackQuickModal {open} {moduleContext} onClose={() => (open = false)} />
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.pill {
|
||||
position: fixed;
|
||||
right: 1rem;
|
||||
bottom: calc(var(--bottom-chrome-height, 5rem) + 1rem);
|
||||
z-index: 50;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.375rem;
|
||||
padding: 0.5rem 0.875rem;
|
||||
border: 1px solid hsl(var(--color-border));
|
||||
background: hsl(var(--color-card));
|
||||
color: hsl(var(--color-foreground));
|
||||
border-radius: 999px;
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
box-shadow:
|
||||
0 6px 16px hsl(0 0% 0% / 0.12),
|
||||
0 2px 6px hsl(0 0% 0% / 0.08);
|
||||
transition:
|
||||
transform 0.15s ease,
|
||||
box-shadow 0.15s ease,
|
||||
border-color 0.15s ease;
|
||||
}
|
||||
|
||||
.pill:hover {
|
||||
transform: translateY(-1px);
|
||||
border-color: hsl(var(--color-primary) / 0.5);
|
||||
box-shadow:
|
||||
0 10px 22px hsl(0 0% 0% / 0.16),
|
||||
0 3px 8px hsl(0 0% 0% / 0.1);
|
||||
color: hsl(var(--color-primary));
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.pill .label {
|
||||
display: none;
|
||||
}
|
||||
.pill {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -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<PillBarConfig | null>(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}
|
||||
|
||||
<!-- Global "Idee?" feedback pill — self-hides on /onboarding,
|
||||
/feedback, /community, and for unauthenticated users. -->
|
||||
<GlobalFeedbackPill />
|
||||
<!-- Quick-feedback modal — opened from the user-menu chip. -->
|
||||
<FeedbackQuickModal
|
||||
open={feedbackModalOpen}
|
||||
moduleContext={feedbackModuleContext}
|
||||
onClose={() => (feedbackModalOpen = false)}
|
||||
/>
|
||||
</AuthGate>
|
||||
|
||||
<ToastContainer />
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue