diff --git a/package.json b/package.json index 35a62cdf..b339ded6 100644 --- a/package.json +++ b/package.json @@ -79,6 +79,7 @@ "modern-normalize": "^3.0.1", "runed": "^0.31.1", "svelecte": "^5.3.0", + "svelte-sonner": "^1.0.7", "wx-grid-data-provider": "^2.2.0", "wx-svelte-grid": "^2.0.0", "zod": "^4.1.5" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 055d92bb..d3095916 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -47,6 +47,9 @@ importers: svelecte: specifier: ^5.3.0 version: 5.3.0(svelte@5.38.7) + svelte-sonner: + specifier: ^1.0.7 + version: 1.0.7(svelte@5.38.7) wx-grid-data-provider: specifier: ^2.2.0 version: 2.2.0 @@ -2390,6 +2393,11 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + runed@0.28.0: + resolution: {integrity: sha512-k2xx7RuO9hWcdd9f+8JoBeqWtYrm5CALfgpkg2YDB80ds/QE4w0qqu34A7fqiAwiBBSBQOid7TLxwxVC27ymWQ==} + peerDependencies: + svelte: ^5.7.0 + runed@0.29.2: resolution: {integrity: sha512-0cq6cA6sYGZwl/FvVqjx9YN+1xEBu9sDDyuWdDW1yWX7JF2wmvmVKfH+hVCZs+csW+P3ARH92MjI3H9QTagOQA==} peerDependencies: @@ -2557,6 +2565,11 @@ packages: typescript: optional: true + svelte-sonner@1.0.7: + resolution: {integrity: sha512-1EUFYmd7q/xfs2qCHwJzGPh9n5VJ3X6QjBN10fof2vxgy8fYE7kVfZ7uGnd7i6fQaWIr5KvXcwYXE/cmTEjk5A==} + peerDependencies: + svelte: ^5.0.0 + svelte-toolbelt@0.9.3: resolution: {integrity: sha512-HCSWxCtVmv+c6g1ACb8LTwHVbDqLKJvHpo6J8TaqwUme2hj9ATJCpjCPNISR1OCq2Q4U1KT41if9ON0isINQZw==} engines: {node: '>=18', pnpm: '>=8.7.0'} @@ -5279,6 +5292,11 @@ snapshots: dependencies: queue-microtask: 1.2.3 + runed@0.28.0(svelte@5.38.7): + dependencies: + esm-env: 1.2.2 + svelte: 5.38.7 + runed@0.29.2(svelte@5.38.7): dependencies: esm-env: 1.2.2 @@ -5424,6 +5442,11 @@ snapshots: sass: 1.92.1 typescript: 5.9.2 + svelte-sonner@1.0.7(svelte@5.38.7): + dependencies: + runed: 0.28.0(svelte@5.38.7) + svelte: 5.38.7 + svelte-toolbelt@0.9.3(svelte@5.38.7): dependencies: clsx: 2.1.1 diff --git a/src/app.scss b/src/app.scss index e60ca740..7d9d4256 100644 --- a/src/app.scss +++ b/src/app.scss @@ -78,3 +78,35 @@ $font-size-base: 16px; padding: 0; cursor: pointer; } + +// Toast notification overrides (svelte-sonner) +[data-sonner-toaster] { + --normal-bg: var(--toast-bg); + --normal-text: var(--toast-text); + --normal-border: var(--toast-border); + + --success-bg: var(--toast-success-bg); + --success-text: var(--toast-success-text); + --success-border: var(--toast-success-text); + + --error-bg: var(--toast-error-bg); + --error-text: var(--toast-error-text); + --error-border: var(--toast-error-text); + + --warning-bg: var(--toast-warning-bg); + --warning-text: var(--toast-warning-text); + --warning-border: var(--toast-warning-text); + + --info-bg: var(--toast-info-bg); + --info-text: var(--toast-info-text); + --info-border: var(--toast-info-text); + + font-family: var(--font-family); + z-index: 102; // Above dialogs (101) +} + +[data-sonner-toast] { + border-radius: 8px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + font-size: 1.4rem; +} diff --git a/src/lib/components/ui/CopyableText.svelte b/src/lib/components/ui/CopyableText.svelte index b92fab43..fce52c94 100644 --- a/src/lib/components/ui/CopyableText.svelte +++ b/src/lib/components/ui/CopyableText.svelte @@ -1,44 +1,35 @@ - diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index a7e66ab1..4d205a3a 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -5,6 +5,7 @@ import { browser } from '$app/environment' import { QueryClientProvider } from '@tanstack/svelte-query' + import { Toaster } from 'svelte-sonner' import type { LayoutData } from './$types' const { data, children } = $props<{ @@ -18,5 +19,6 @@ + {@render children?.()} diff --git a/src/themes/themes.scss b/src/themes/themes.scss index c98086a4..1d03aaf0 100644 --- a/src/themes/themes.scss +++ b/src/themes/themes.scss @@ -376,6 +376,20 @@ --light-shadow-hover: #{colors.$light--shadow--light--hover}; --light-accent: #{colors.$light--bg--light}; + // Toast notifications + --toast-bg: #{colors.$grey-100}; + --toast-text: #{colors.$text--primary--color--light}; + --toast-text-secondary: #{colors.$text--secondary--color--light}; + --toast-border: #{colors.$border--subtle--light}; + --toast-success-bg: #e8f5e9; + --toast-success-text: #2e7d32; + --toast-error-bg: #{colors.$error--bg--light}; + --toast-error-text: #{colors.$error}; + --toast-warning-bg: #{colors.$notice--bg--light}; + --toast-warning-text: #{colors.$notice--text--light}; + --toast-info-bg: #e3f2fd; + --toast-info-text: #1565c0; + // Gradients --hero-gradient: #{effects.$hero--gradient--light}; --hero-gradient-overlay: #{effects.$hero--gradient--light--overlay}; @@ -728,6 +742,20 @@ --light-shadow-hover: #{colors.$light--shadow--dark--hover}; --light-accent: #{colors.$light--bg--dark}; + // Toast notifications + --toast-bg: #{colors.$grey-20}; + --toast-text: #{colors.$text--primary--color--dark}; + --toast-text-secondary: #{colors.$text--secondary--color--dark}; + --toast-border: #{colors.$border--subtle--dark}; + --toast-success-bg: #1b3d1f; + --toast-success-text: #66bb6a; + --toast-error-bg: #{colors.$error--bg--dark}; + --toast-error-text: #{colors.$error}; + --toast-warning-bg: #{colors.$notice--bg--dark}; + --toast-warning-text: #{colors.$notice--text--dark}; + --toast-info-bg: #0d2744; + --toast-info-text: #64b5f6; + // Gradients --hero-gradient: #{effects.$hero--gradient--dark}; --hero-gradient-overlay: #{effects.$hero--gradient--dark--overlay};