From 677123091ab8297ea834f90cbe2779fb6fedfc16 Mon Sep 17 00:00:00 2001 From: Till JS Date: Fri, 17 Apr 2026 15:46:51 +0200 Subject: [PATCH] refactor(settings): unify section styling, remove Credits tab MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - AiSettings: Tailwind → scoped CSS with theme tokens; tier cards as buttons with subtle primary-tinted active state; Tier 0 in matching card; pill toggles for behavior settings; improved body text readability - VaultSection: theme-token colors, SettingsSectionHeader with status badge action, unified button system, flat subsection structure with border dividers, collapsible encrypted-fields list (5 by default), threat-model disclosure moved above destructive actions, wizard step numbering; dropped stale dark-mode @media block - Settings ListView: overflow-x: hidden so chip-row scroll stays scoped; hashchange + workbench:navigate-anchor effect for live deep-links - Remove Credits tab (stub redirecting to /?app=credits) — full Credits module + dashboard widget already cover balance/purchases/transactions --- .../lib/components/settings/AiSettings.svelte | 693 ++++++++---- .../lib/components/settings/searchIndex.ts | 26 +- .../settings/sections/CreditsSection.svelte | 75 -- .../settings/sections/VaultSection.svelte | 994 ++++++++++-------- .../src/lib/modules/settings/ListView.svelte | 3 - 5 files changed, 1055 insertions(+), 736 deletions(-) delete mode 100644 apps/mana/apps/web/src/lib/components/settings/sections/CreditsSection.svelte diff --git a/apps/mana/apps/web/src/lib/components/settings/AiSettings.svelte b/apps/mana/apps/web/src/lib/components/settings/AiSettings.svelte index c7c04db1d..232e81c72 100644 --- a/apps/mana/apps/web/src/lib/components/settings/AiSettings.svelte +++ b/apps/mana/apps/web/src/lib/components/settings/AiSettings.svelte @@ -3,13 +3,9 @@ * AiSettings — Settings-page section for the tiered LLM orchestrator. * * Lets the user pick which @mana/shared-llm tiers Mana is allowed to - * use. Each tier is a checkbox with an explanation of what it means - * for privacy + speed + cost. The cloud tier is gated behind an - * additional consent checkbox the first time it's enabled. - * - * Drops into the main settings page (/settings) as a self-contained - * Card section, mirroring the existing PasskeyManager / SessionManager - * pattern. + * use. Each tier is a selectable row with an explanation of what it + * means for privacy + speed + cost. The cloud tier is gated behind + * an additional consent step the first time it's enabled. */ import { llmSettingsState, updateLlmSettings, tierLabel, type LlmTier } from '@mana/shared-llm'; import { @@ -30,7 +26,7 @@ let loadingBrowser = $state(false); function toggleTier(tier: LlmTier) { - if (tier === 'none') return; // 'none' is implicit, not a real toggle + if (tier === 'none') return; const current = settings.allowedTiers; const next = current.includes(tier) ? current.filter((t) => t !== tier) : [...current, tier]; updateLlmSettings({ allowedTiers: next }); @@ -57,8 +53,6 @@ updateLlmSettings({ showSourceInUi: value }); } - // Tier card metadata — defined inline because it's specific to this UI - // and changes alongside layout updates. type TierCard = { tier: LlmTier; icon: typeof Robot; @@ -99,7 +93,7 @@ bullets: [ 'Direkt aus dem Browser — keine Mana-Server-Zwischenstation', 'Du zahlst beim Provider, wir sehen nichts davon', - 'Schluessel werden verschluesselt in deinem Vault gespeichert', + 'Schlüssel werden verschlüsselt in deinem Vault gespeichert', ], }, { @@ -123,24 +117,28 @@ const browserCacheReady = $derived(webgpuSupported && localLlmStatus.current.state === 'ready'); -
- -
-
- -
-

Lokal (ohne KI) — immer aktiv

-

- Mana funktioniert auch ganz ohne KI: Datum-Erkennung, Suche und einfache Klassifikation - laufen über klassische Algorithmen. Manche Funktionen sind dann begrenzt, dafür ist alles - 100% offline und kostet nichts. -

+
+ +
+
+ +
+
+
+ Lokal (ohne KI) + immer aktiv
+

Basis-Funktionen ohne jede KI

+

+ Mana funktioniert auch ganz ohne KI: Datum-Erkennung, Suche und einfache Klassifikation + laufen über klassische Algorithmen. Manche Funktionen sind dann begrenzt, dafür ist alles + 100% offline und kostet nichts. +

- -
+ +
{#each tierCards as card} {@const enabled = isEnabled(card.tier)} {@const tierBlocked = card.tier === 'browser' && !webgpuSupported} @@ -148,189 +146,518 @@ type="button" onclick={() => !tierBlocked && toggleTier(card.tier)} disabled={tierBlocked} - class="w-full rounded-xl border p-4 text-left transition-all {enabled - ? 'border-primary bg-primary/5 ring-1 ring-primary/30' - : 'border-border bg-card hover:border-primary/40'} {tierBlocked - ? 'cursor-not-allowed opacity-50' - : 'cursor-pointer'}" + class="tier-row" + class:enabled + class:blocked={tierBlocked} > -
-
- +
+ +
+
+
+ {card.title} + {#if enabled} + aktiv + {/if}
-
-
-
{card.title}
- {#if enabled} - aktiv{card.subtitle}

+
    + {#each card.bullets as bullet} +
  • {bullet}
  • + {/each} +
+ {#if card.warning} +

+ + {card.warning} +

+ {/if} + + {#if card.tier === 'browser' && enabled && webgpuSupported} +
+ {#if browserCacheReady} + ✓ Modell geladen + {:else if localLlmStatus.current.state === 'downloading'} + + Lade {defaultModelInfo.displayName} ({( + localLlmStatus.current.progress * 100 + ).toFixed(0)}%)… + + {:else} + + {/if}
-

{card.subtitle}

-
    - {#each card.bullets as bullet} -
  • - - {bullet} -
  • - {/each} -
- {#if card.warning} -
- - {card.warning} -
- {/if} + {/if} - - {#if card.tier === 'browser' && enabled && webgpuSupported} -
- {#if browserCacheReady} - ✓ Modell geladen - {:else if localLlmStatus.current.state === 'downloading'} - - Lade {defaultModelInfo.displayName} ({( - localLlmStatus.current.progress * 100 - ).toFixed(0)}%)… - - {:else} - - - {/if} -
- {/if} + {#if card.tier === 'browser' && tierBlocked} +

+ WebGPU nicht verfügbar in deinem Browser. Funktioniert in Chrome/Edge 113+ oder Safari + 18+. +

+ {/if} - {#if card.tier === 'browser' && tierBlocked} -

- WebGPU nicht verfügbar in deinem Browser. Funktioniert in Chrome/Edge 113+ oder - Safari 18+. + {#if card.tier === 'byok' && enabled} +

e.stopPropagation()} + onkeydown={(e) => e.stopPropagation()} + role="presentation" + > + +
+ {/if} + + {#if card.tier === 'cloud' && enabled && !settings.cloudConsentGiven} + + {/if} - {#if card.tier === 'cloud' && enabled && !settings.cloudConsentGiven} -
e.stopPropagation()} - onkeydown={(e) => e.stopPropagation()} - role="presentation" + {#if card.tier === 'cloud' && enabled && settings.cloudConsentGiven} + - {/if} - - {#if card.tier === 'cloud' && enabled && settings.cloudConsentGiven} -
- ✓ Cloud-Zustimmung erteilt - - -
- {/if} -
+ Zurücknehmen + +
+ {/if}
{/each}
-
- Aktuelle Reihenfolge: - {#if settings.allowedTiers.length === 0} - Nur lokal (ohne KI) — die meisten KI-Funktionen sind begrenzt. - {:else} - {settings.allowedTiers.map((t) => tierLabel(t)).join(' → ')} → Lokal (Fallback) - {/if} +
+ Aktuelle Reihenfolge: + + {#if settings.allowedTiers.length === 0} + Nur lokal (ohne KI) — die meisten KI-Funktionen sind begrenzt. + {:else} + {settings.allowedTiers.map((t) => tierLabel(t)).join(' → ')} → Lokal (Fallback) + {/if} +
-
-
diff --git a/apps/mana/apps/web/src/lib/modules/settings/ListView.svelte b/apps/mana/apps/web/src/lib/modules/settings/ListView.svelte index 96fec0cba..6dbd9b0e3 100644 --- a/apps/mana/apps/web/src/lib/modules/settings/ListView.svelte +++ b/apps/mana/apps/web/src/lib/modules/settings/ListView.svelte @@ -15,7 +15,6 @@ import GeneralSection from '$lib/components/settings/sections/GeneralSection.svelte'; import AiSection from '$lib/components/settings/sections/AiSection.svelte'; import SecuritySection from '$lib/components/settings/sections/SecuritySection.svelte'; - import CreditsSection from '$lib/components/settings/sections/CreditsSection.svelte'; import DataSection from '$lib/components/settings/sections/DataSection.svelte'; let activeCategory = $state('general'); @@ -76,8 +75,6 @@ {:else if activeCategory === 'security'} - {:else if activeCategory === 'credits'} - {:else if activeCategory === 'data'} {/if}