diff --git a/apps/contacts/apps/web/src/lib/components/import/GoogleImport.svelte b/apps/contacts/apps/web/src/lib/components/import/GoogleImport.svelte
index 258da86fc..1662a51fe 100644
--- a/apps/contacts/apps/web/src/lib/components/import/GoogleImport.svelte
+++ b/apps/contacts/apps/web/src/lib/components/import/GoogleImport.svelte
@@ -10,6 +10,7 @@
type GoogleImportResult,
} from '$lib/api/google';
import { contactsStore } from '$lib/stores/contacts.svelte';
+ import { GoogleImportSkeleton } from '$lib/components/skeletons';
type Step = 'connect' | 'select' | 'result';
@@ -170,12 +171,7 @@
{/if}
{#if isLoading}
-
diff --git a/apps/contacts/apps/web/src/lib/components/skeletons/AppLoadingSkeleton.svelte b/apps/contacts/apps/web/src/lib/components/skeletons/AppLoadingSkeleton.svelte
new file mode 100644
index 000000000..a0fb33238
--- /dev/null
+++ b/apps/contacts/apps/web/src/lib/components/skeletons/AppLoadingSkeleton.svelte
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {#each Array(5) as _, i}
+
+ {/each}
+
+
+
+
+
diff --git a/apps/contacts/apps/web/src/lib/components/skeletons/ContactCardSkeleton.svelte b/apps/contacts/apps/web/src/lib/components/skeletons/ContactCardSkeleton.svelte
new file mode 100644
index 000000000..2d3430e1c
--- /dev/null
+++ b/apps/contacts/apps/web/src/lib/components/skeletons/ContactCardSkeleton.svelte
@@ -0,0 +1,70 @@
+
+
+
+
+
diff --git a/apps/contacts/apps/web/src/lib/components/skeletons/ContactDetailSkeleton.svelte b/apps/contacts/apps/web/src/lib/components/skeletons/ContactDetailSkeleton.svelte
new file mode 100644
index 000000000..96318820b
--- /dev/null
+++ b/apps/contacts/apps/web/src/lib/components/skeletons/ContactDetailSkeleton.svelte
@@ -0,0 +1,171 @@
+
+
+
+
+
diff --git a/apps/contacts/apps/web/src/lib/components/skeletons/ContactGridSkeleton.svelte b/apps/contacts/apps/web/src/lib/components/skeletons/ContactGridSkeleton.svelte
new file mode 100644
index 000000000..362727151
--- /dev/null
+++ b/apps/contacts/apps/web/src/lib/components/skeletons/ContactGridSkeleton.svelte
@@ -0,0 +1,57 @@
+
+
+
+ {#each Array(count) as _, i}
+
+ {/each}
+
+
+
diff --git a/apps/contacts/apps/web/src/lib/components/skeletons/ContactListSkeleton.svelte b/apps/contacts/apps/web/src/lib/components/skeletons/ContactListSkeleton.svelte
new file mode 100644
index 000000000..3bb93cb5a
--- /dev/null
+++ b/apps/contacts/apps/web/src/lib/components/skeletons/ContactListSkeleton.svelte
@@ -0,0 +1,31 @@
+
+
+
+ {#each Array(count) as _, i}
+
+ {/each}
+
diff --git a/apps/contacts/apps/web/src/lib/components/skeletons/ContactNotesSkeleton.svelte b/apps/contacts/apps/web/src/lib/components/skeletons/ContactNotesSkeleton.svelte
new file mode 100644
index 000000000..6ebee670b
--- /dev/null
+++ b/apps/contacts/apps/web/src/lib/components/skeletons/ContactNotesSkeleton.svelte
@@ -0,0 +1,40 @@
+
+
+
+ {#each Array(3) as _, i}
+
+ {/each}
+
+
+
diff --git a/apps/contacts/apps/web/src/lib/components/skeletons/ContactRowSkeleton.svelte b/apps/contacts/apps/web/src/lib/components/skeletons/ContactRowSkeleton.svelte
new file mode 100644
index 000000000..58fb5d938
--- /dev/null
+++ b/apps/contacts/apps/web/src/lib/components/skeletons/ContactRowSkeleton.svelte
@@ -0,0 +1,45 @@
+
+
+
+
+
diff --git a/apps/contacts/apps/web/src/lib/components/skeletons/DuplicateGroupSkeleton.svelte b/apps/contacts/apps/web/src/lib/components/skeletons/DuplicateGroupSkeleton.svelte
new file mode 100644
index 000000000..bac423136
--- /dev/null
+++ b/apps/contacts/apps/web/src/lib/components/skeletons/DuplicateGroupSkeleton.svelte
@@ -0,0 +1,89 @@
+
+
+
+
+
diff --git a/apps/contacts/apps/web/src/lib/components/skeletons/DuplicateListSkeleton.svelte b/apps/contacts/apps/web/src/lib/components/skeletons/DuplicateListSkeleton.svelte
new file mode 100644
index 000000000..7e618b617
--- /dev/null
+++ b/apps/contacts/apps/web/src/lib/components/skeletons/DuplicateListSkeleton.svelte
@@ -0,0 +1,69 @@
+
+
+
+
+
+ {#each Array(3) as _}
+
+
+
+
+ {/each}
+
+
+
+
+ {#each Array(count) as _, i}
+
+ {/each}
+
+
+
+
diff --git a/apps/contacts/apps/web/src/lib/components/skeletons/FavoriteCardSkeleton.svelte b/apps/contacts/apps/web/src/lib/components/skeletons/FavoriteCardSkeleton.svelte
new file mode 100644
index 000000000..5d5d3214b
--- /dev/null
+++ b/apps/contacts/apps/web/src/lib/components/skeletons/FavoriteCardSkeleton.svelte
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/contacts/apps/web/src/lib/components/skeletons/FavoriteGridSkeleton.svelte b/apps/contacts/apps/web/src/lib/components/skeletons/FavoriteGridSkeleton.svelte
new file mode 100644
index 000000000..452e4c079
--- /dev/null
+++ b/apps/contacts/apps/web/src/lib/components/skeletons/FavoriteGridSkeleton.svelte
@@ -0,0 +1,56 @@
+
+
+
+ {#each Array(count) as _, i}
+
+ {/each}
+
+
+
diff --git a/apps/contacts/apps/web/src/lib/components/skeletons/GoogleImportSkeleton.svelte b/apps/contacts/apps/web/src/lib/components/skeletons/GoogleImportSkeleton.svelte
new file mode 100644
index 000000000..35305687c
--- /dev/null
+++ b/apps/contacts/apps/web/src/lib/components/skeletons/GoogleImportSkeleton.svelte
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+ {#each Array(6) as _, i}
+
+ {/each}
+
+
+
+
+
+
+
+
diff --git a/apps/contacts/apps/web/src/lib/components/skeletons/ImportPreviewSkeleton.svelte b/apps/contacts/apps/web/src/lib/components/skeletons/ImportPreviewSkeleton.svelte
new file mode 100644
index 000000000..d62e68f64
--- /dev/null
+++ b/apps/contacts/apps/web/src/lib/components/skeletons/ImportPreviewSkeleton.svelte
@@ -0,0 +1,118 @@
+
+
+
+
+
+ {#each Array(3) as _}
+
+
+
+
+ {/each}
+
+
+
+
+
+
+
+ {#each Array(5) as _, i}
+
+ {/each}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/contacts/apps/web/src/lib/components/skeletons/NetworkGraphSkeleton.svelte b/apps/contacts/apps/web/src/lib/components/skeletons/NetworkGraphSkeleton.svelte
new file mode 100644
index 000000000..c1e3ae27a
--- /dev/null
+++ b/apps/contacts/apps/web/src/lib/components/skeletons/NetworkGraphSkeleton.svelte
@@ -0,0 +1,115 @@
+
+
+
+
+
+ {#each Array(8) as _, i}
+
+
+
+ {/each}
+
+
+
+
+
+
+
+
+
Netzwerk wird geladen...
+
+
+
+
diff --git a/apps/contacts/apps/web/src/lib/components/skeletons/TagCardSkeleton.svelte b/apps/contacts/apps/web/src/lib/components/skeletons/TagCardSkeleton.svelte
new file mode 100644
index 000000000..09ff2e540
--- /dev/null
+++ b/apps/contacts/apps/web/src/lib/components/skeletons/TagCardSkeleton.svelte
@@ -0,0 +1,36 @@
+
+
+
+
+
diff --git a/apps/contacts/apps/web/src/lib/components/skeletons/TagGridSkeleton.svelte b/apps/contacts/apps/web/src/lib/components/skeletons/TagGridSkeleton.svelte
new file mode 100644
index 000000000..f1c72956f
--- /dev/null
+++ b/apps/contacts/apps/web/src/lib/components/skeletons/TagGridSkeleton.svelte
@@ -0,0 +1,50 @@
+
+
+
+ {#each Array(count) as _, i}
+
+ {/each}
+
+
+
diff --git a/apps/contacts/apps/web/src/lib/components/skeletons/index.ts b/apps/contacts/apps/web/src/lib/components/skeletons/index.ts
new file mode 100644
index 000000000..82732122c
--- /dev/null
+++ b/apps/contacts/apps/web/src/lib/components/skeletons/index.ts
@@ -0,0 +1,42 @@
+/**
+ * Contacts App Skeleton Components
+ *
+ * App-specific skeleton loaders that match the exact layout of contact components.
+ * Built on top of @manacore/shared-ui skeleton primitives.
+ */
+
+// Contact List/Grid Skeletons
+export { default as ContactRowSkeleton } from './ContactRowSkeleton.svelte';
+export { default as ContactListSkeleton } from './ContactListSkeleton.svelte';
+export { default as ContactCardSkeleton } from './ContactCardSkeleton.svelte';
+export { default as ContactGridSkeleton } from './ContactGridSkeleton.svelte';
+
+// Tag Skeletons
+export { default as TagCardSkeleton } from './TagCardSkeleton.svelte';
+export { default as TagGridSkeleton } from './TagGridSkeleton.svelte';
+
+// Favorite Skeletons
+export { default as FavoriteCardSkeleton } from './FavoriteCardSkeleton.svelte';
+export { default as FavoriteGridSkeleton } from './FavoriteGridSkeleton.svelte';
+
+// Duplicate Skeletons
+export { default as DuplicateGroupSkeleton } from './DuplicateGroupSkeleton.svelte';
+export { default as DuplicateListSkeleton } from './DuplicateListSkeleton.svelte';
+
+// App Loading Skeleton
+export { default as AppLoadingSkeleton } from './AppLoadingSkeleton.svelte';
+
+// Import Preview Skeleton
+export { default as ImportPreviewSkeleton } from './ImportPreviewSkeleton.svelte';
+
+// Google Import Skeleton
+export { default as GoogleImportSkeleton } from './GoogleImportSkeleton.svelte';
+
+// Contact Detail Skeleton
+export { default as ContactDetailSkeleton } from './ContactDetailSkeleton.svelte';
+
+// Contact Notes Skeleton
+export { default as ContactNotesSkeleton } from './ContactNotesSkeleton.svelte';
+
+// Network Graph Skeleton
+export { default as NetworkGraphSkeleton } from './NetworkGraphSkeleton.svelte';
diff --git a/apps/contacts/apps/web/src/routes/(app)/+layout.svelte b/apps/contacts/apps/web/src/routes/(app)/+layout.svelte
index c0bffdd0b..7f4da318b 100644
--- a/apps/contacts/apps/web/src/routes/(app)/+layout.svelte
+++ b/apps/contacts/apps/web/src/routes/(app)/+layout.svelte
@@ -17,10 +17,14 @@
import { getPillAppItems } from '@manacore/shared-branding';
import { setLocale, supportedLocales } from '$lib/i18n';
import ContactDetailModal from '$lib/components/ContactDetailModal.svelte';
+ import SearchModal from '$lib/components/SearchModal.svelte';
import { contactsStore } from '$lib/stores/contacts.svelte';
import { viewModeStore } from '$lib/stores/view-mode.svelte';
import { contactsSettings } from '$lib/stores/settings.svelte';
+ // Search modal state
+ let searchModalOpen = $state(false);
+
// Check if we're on a contact detail route
const contactDetailMatch = $derived($page.url.pathname.match(/^\/contacts\/([0-9a-f-]{36})$/i));
const showContactModal = $derived(!!contactDetailMatch);
@@ -78,9 +82,10 @@
{ href: '/', label: 'Kontakte', icon: 'users' },
{ href: '/tags', label: 'Tags', icon: 'tag' },
{ href: '/favorites', label: 'Favoriten', icon: 'heart' },
- { href: '/archive', label: 'Archiv', icon: 'archive' },
+ { href: '/network', label: 'Netzwerk', icon: 'share-2' },
{ href: '/settings', label: 'Einstellungen', icon: 'settings' },
{ href: '/feedback', label: 'Feedback', icon: 'chat' },
+ { href: '/help', label: 'Hilfe', icon: 'help-circle' },
];
// Navigation shortcuts (Ctrl+1-5)
@@ -92,7 +97,7 @@
// Cmd/Ctrl+K to open search (works even in inputs)
if ((event.ctrlKey || event.metaKey) && event.key === 'k') {
event.preventDefault();
- // TODO: Open search modal
+ searchModalOpen = true;
return;
}
@@ -231,6 +236,9 @@
{#if showContactModal && modalContactId}
{/if}
+
+
+
(searchModalOpen = false)} />
diff --git a/apps/todo/apps/web/src/lib/components/skeletons/KanbanBoardSkeleton.svelte b/apps/todo/apps/web/src/lib/components/skeletons/KanbanBoardSkeleton.svelte
new file mode 100644
index 000000000..3f6ab58c9
--- /dev/null
+++ b/apps/todo/apps/web/src/lib/components/skeletons/KanbanBoardSkeleton.svelte
@@ -0,0 +1,70 @@
+
+
+
+
+
diff --git a/apps/todo/apps/web/src/lib/components/skeletons/KanbanColumnSkeleton.svelte b/apps/todo/apps/web/src/lib/components/skeletons/KanbanColumnSkeleton.svelte
new file mode 100644
index 000000000..43fddd36c
--- /dev/null
+++ b/apps/todo/apps/web/src/lib/components/skeletons/KanbanColumnSkeleton.svelte
@@ -0,0 +1,99 @@
+
+
+
+
+
diff --git a/apps/todo/apps/web/src/lib/components/skeletons/StatisticsSkeleton.svelte b/apps/todo/apps/web/src/lib/components/skeletons/StatisticsSkeleton.svelte
new file mode 100644
index 000000000..8cd238131
--- /dev/null
+++ b/apps/todo/apps/web/src/lib/components/skeletons/StatisticsSkeleton.svelte
@@ -0,0 +1,252 @@
+
+
+
+
+
diff --git a/apps/todo/apps/web/src/lib/components/skeletons/TaskItemSkeleton.svelte b/apps/todo/apps/web/src/lib/components/skeletons/TaskItemSkeleton.svelte
new file mode 100644
index 000000000..9a2a08148
--- /dev/null
+++ b/apps/todo/apps/web/src/lib/components/skeletons/TaskItemSkeleton.svelte
@@ -0,0 +1,80 @@
+
+
+
+
+
diff --git a/apps/todo/apps/web/src/lib/components/skeletons/TaskListSkeleton.svelte b/apps/todo/apps/web/src/lib/components/skeletons/TaskListSkeleton.svelte
new file mode 100644
index 000000000..cd3f1cc18
--- /dev/null
+++ b/apps/todo/apps/web/src/lib/components/skeletons/TaskListSkeleton.svelte
@@ -0,0 +1,73 @@
+
+
+
+
+
diff --git a/apps/todo/apps/web/src/lib/components/skeletons/index.ts b/apps/todo/apps/web/src/lib/components/skeletons/index.ts
new file mode 100644
index 000000000..6628b5579
--- /dev/null
+++ b/apps/todo/apps/web/src/lib/components/skeletons/index.ts
@@ -0,0 +1,20 @@
+/**
+ * Todo App Skeleton Components
+ *
+ * App-specific skeleton loaders that match the exact layout of todo components.
+ * Built on top of @manacore/shared-ui skeleton primitives.
+ */
+
+// App Loading Skeleton
+export { default as AppLoadingSkeleton } from './AppLoadingSkeleton.svelte';
+
+// Task List Skeletons
+export { default as TaskItemSkeleton } from './TaskItemSkeleton.svelte';
+export { default as TaskListSkeleton } from './TaskListSkeleton.svelte';
+
+// Statistics Skeletons
+export { default as StatisticsSkeleton } from './StatisticsSkeleton.svelte';
+
+// Kanban Skeletons
+export { default as KanbanColumnSkeleton } from './KanbanColumnSkeleton.svelte';
+export { default as KanbanBoardSkeleton } from './KanbanBoardSkeleton.svelte';
diff --git a/apps/todo/apps/web/src/routes/(app)/+page.svelte b/apps/todo/apps/web/src/routes/(app)/+page.svelte
index a4818a266..00ef8a394 100644
--- a/apps/todo/apps/web/src/routes/(app)/+page.svelte
+++ b/apps/todo/apps/web/src/routes/(app)/+page.svelte
@@ -11,6 +11,7 @@
import QuickAddTask from '$lib/components/QuickAddTask.svelte';
import CollapsibleSection from '$lib/components/CollapsibleSection.svelte';
import TaskEditModal from '$lib/components/TaskEditModal.svelte';
+ import { TaskListSkeleton } from '$lib/components/skeletons';
import type { Task } from '@todo/shared';
let isLoading = $state(true);
@@ -130,11 +131,7 @@