mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-20 07:03:36 +02:00
♻️ refactor: centralize AppLoadingSkeleton in shared-ui
Add configurable AppLoadingSkeleton component to @manacore/shared-ui with multiple layout presets: list, tasks, sidebar, centered, minimal. Migrate 3 apps to use the shared component: - contacts: uses default 'list' layout - todo: uses 'tasks' layout - questions: uses 'sidebar' layout Apps with highly specific layouts (calendar, clock) retain their local implementations for now.
This commit is contained in:
parent
cdac341882
commit
8804ab77a2
13 changed files with 494 additions and 306 deletions
|
|
@ -1,117 +0,0 @@
|
|||
<script lang="ts">
|
||||
/**
|
||||
* AppLoadingSkeleton - Full page loading skeleton for initial app load
|
||||
* Shows a minimal skeleton layout while auth is being checked
|
||||
*/
|
||||
|
||||
import { SkeletonBox } from '@manacore/shared-ui';
|
||||
</script>
|
||||
|
||||
<div class="app-loading-skeleton" role="status" aria-label="App wird geladen...">
|
||||
<!-- Header placeholder -->
|
||||
<div class="header-skeleton">
|
||||
<SkeletonBox width="120px" height="32px" borderRadius="8px" />
|
||||
<div class="header-nav">
|
||||
<SkeletonBox width="80px" height="32px" borderRadius="16px" />
|
||||
<SkeletonBox width="80px" height="32px" borderRadius="16px" />
|
||||
<SkeletonBox width="80px" height="32px" borderRadius="16px" />
|
||||
</div>
|
||||
<SkeletonBox width="36px" height="36px" borderRadius="50%" />
|
||||
</div>
|
||||
|
||||
<!-- Content placeholder -->
|
||||
<div class="content-skeleton">
|
||||
<!-- Page title -->
|
||||
<div class="title-row">
|
||||
<SkeletonBox width="200px" height="32px" />
|
||||
<SkeletonBox width="120px" height="40px" borderRadius="8px" />
|
||||
</div>
|
||||
|
||||
<!-- Search bar -->
|
||||
<SkeletonBox width="100%" height="48px" borderRadius="12px" />
|
||||
|
||||
<!-- List items -->
|
||||
<div class="list-skeleton">
|
||||
{#each Array(5) as _, i}
|
||||
<div class="list-item" style="opacity: {Math.max(0.3, 1 - i * 0.15)};">
|
||||
<SkeletonBox width="48px" height="48px" borderRadius="50%" />
|
||||
<div class="item-content">
|
||||
<SkeletonBox width="60%" height="18px" />
|
||||
<SkeletonBox width="40%" height="14px" />
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.app-loading-skeleton {
|
||||
min-height: 100vh;
|
||||
background: hsl(var(--background));
|
||||
}
|
||||
|
||||
.header-skeleton {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 1rem 2rem;
|
||||
border-bottom: 1px solid hsl(var(--border));
|
||||
}
|
||||
|
||||
.header-nav {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.content-skeleton {
|
||||
max-width: 80rem;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.title-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.list-skeleton {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
.list-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
padding: 1rem;
|
||||
background: hsl(var(--card));
|
||||
border: 1px solid hsl(var(--border));
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.item-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.header-nav {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.header-skeleton {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.content-skeleton {
|
||||
padding: 1rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -22,8 +22,8 @@ export { default as TagGridSkeleton } from './TagGridSkeleton.svelte';
|
|||
export { default as DuplicateGroupSkeleton } from './DuplicateGroupSkeleton.svelte';
|
||||
export { default as DuplicateListSkeleton } from './DuplicateListSkeleton.svelte';
|
||||
|
||||
// App Loading Skeleton
|
||||
export { default as AppLoadingSkeleton } from './AppLoadingSkeleton.svelte';
|
||||
// App Loading Skeleton (from shared-ui)
|
||||
export { AppLoadingSkeleton } from '@manacore/shared-ui';
|
||||
|
||||
// Import Preview Skeleton
|
||||
export { default as ImportPreviewSkeleton } from './ImportPreviewSkeleton.svelte';
|
||||
|
|
|
|||
|
|
@ -1,47 +0,0 @@
|
|||
<div class="flex min-h-screen animate-pulse">
|
||||
<!-- Sidebar -->
|
||||
<aside class="w-64 border-r border-border bg-card">
|
||||
<!-- Header -->
|
||||
<div class="flex h-16 items-center border-b border-border px-4">
|
||||
<div class="h-6 w-28 rounded bg-muted"></div>
|
||||
</div>
|
||||
|
||||
<!-- New Question Button -->
|
||||
<div class="p-4">
|
||||
<div class="h-10 w-full rounded-lg bg-muted"></div>
|
||||
</div>
|
||||
|
||||
<!-- Navigation -->
|
||||
<nav class="space-y-1 px-2">
|
||||
<div class="h-10 w-full rounded-lg bg-muted"></div>
|
||||
|
||||
<div class="my-4 px-3">
|
||||
<div class="h-3 w-20 rounded bg-muted"></div>
|
||||
</div>
|
||||
|
||||
{#each Array(4) as _}
|
||||
<div class="h-10 w-full rounded-lg bg-muted"></div>
|
||||
{/each}
|
||||
</nav>
|
||||
</aside>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="flex-1 p-6">
|
||||
<div class="mb-6">
|
||||
<div class="h-8 w-48 rounded bg-muted"></div>
|
||||
<div class="mt-2 h-4 w-32 rounded bg-muted"></div>
|
||||
</div>
|
||||
|
||||
<div class="mb-6 flex gap-4">
|
||||
<div class="h-10 flex-1 rounded-lg bg-muted"></div>
|
||||
<div class="h-10 w-32 rounded-lg bg-muted"></div>
|
||||
<div class="h-10 w-24 rounded-lg bg-muted"></div>
|
||||
</div>
|
||||
|
||||
<div class="space-y-3">
|
||||
{#each Array(5) as _}
|
||||
<div class="h-24 rounded-xl bg-muted"></div>
|
||||
{/each}
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
export { default as QuestionSkeleton } from './QuestionSkeleton.svelte';
|
||||
export { default as QuestionDetailSkeleton } from './QuestionDetailSkeleton.svelte';
|
||||
export { default as AppLoadingSkeleton } from './AppLoadingSkeleton.svelte';
|
||||
|
||||
// App Loading Skeleton (from shared-ui with 'sidebar' layout)
|
||||
export { AppLoadingSkeleton } from '@manacore/shared-ui';
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
</script>
|
||||
|
||||
{#if !appReady}
|
||||
<AppLoadingSkeleton />
|
||||
<AppLoadingSkeleton layout="sidebar" />
|
||||
{:else}
|
||||
<div class="min-h-screen bg-background text-foreground">
|
||||
{@render children()}
|
||||
|
|
|
|||
|
|
@ -1,130 +0,0 @@
|
|||
<script lang="ts">
|
||||
/**
|
||||
* AppLoadingSkeleton - Full page loading skeleton for initial app load
|
||||
* Shows a minimal skeleton layout while auth is being checked
|
||||
*/
|
||||
|
||||
import { SkeletonBox } from '@manacore/shared-ui';
|
||||
</script>
|
||||
|
||||
<div class="app-loading-skeleton" role="status" aria-label="App wird geladen...">
|
||||
<!-- Header placeholder -->
|
||||
<div class="header-skeleton">
|
||||
<SkeletonBox width="140px" height="32px" borderRadius="8px" />
|
||||
<div class="header-nav">
|
||||
<SkeletonBox width="36px" height="36px" borderRadius="50%" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Content placeholder -->
|
||||
<div class="content-skeleton">
|
||||
<!-- Page title -->
|
||||
<div class="title-row">
|
||||
<SkeletonBox width="180px" height="28px" />
|
||||
</div>
|
||||
<SkeletonBox width="220px" height="16px" />
|
||||
|
||||
<!-- Quick add bar -->
|
||||
<div class="quick-add-skeleton">
|
||||
<SkeletonBox width="100%" height="52px" borderRadius="12px" />
|
||||
</div>
|
||||
|
||||
<!-- Task sections -->
|
||||
<div class="sections-skeleton">
|
||||
<!-- Section header -->
|
||||
<div class="section-header">
|
||||
<SkeletonBox width="100px" height="20px" />
|
||||
<SkeletonBox width="28px" height="28px" borderRadius="50%" />
|
||||
</div>
|
||||
|
||||
<!-- Task items -->
|
||||
<div class="task-list">
|
||||
{#each Array(4) as _, i}
|
||||
<div class="task-item" style="opacity: {Math.max(0.3, 1 - i * 0.18)};">
|
||||
<SkeletonBox width="22px" height="22px" borderRadius="6px" />
|
||||
<div class="task-content">
|
||||
<SkeletonBox width="{70 - i * 8}%" height="18px" />
|
||||
<SkeletonBox width="{40 + i * 5}%" height="14px" />
|
||||
</div>
|
||||
<SkeletonBox width="24px" height="24px" borderRadius="4px" />
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.app-loading-skeleton {
|
||||
min-height: 100vh;
|
||||
background: hsl(var(--background));
|
||||
}
|
||||
|
||||
.header-skeleton {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 1rem 1.5rem;
|
||||
border-bottom: 1px solid hsl(var(--border));
|
||||
}
|
||||
|
||||
.header-nav {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.content-skeleton {
|
||||
max-width: 48rem;
|
||||
margin: 0 auto;
|
||||
padding: 1.5rem 1rem;
|
||||
}
|
||||
|
||||
.title-row {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.quick-add-skeleton {
|
||||
margin: 1.5rem 0;
|
||||
}
|
||||
|
||||
.sections-skeleton {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0.75rem 0;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.task-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.task-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
padding: 0.875rem 1rem;
|
||||
background: hsl(var(--card));
|
||||
border: 1px solid hsl(var(--border));
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.task-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.375rem;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.content-skeleton {
|
||||
padding: 1rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -5,8 +5,8 @@
|
|||
* Built on top of @manacore/shared-ui skeleton primitives.
|
||||
*/
|
||||
|
||||
// App Loading Skeleton
|
||||
export { default as AppLoadingSkeleton } from './AppLoadingSkeleton.svelte';
|
||||
// App Loading Skeleton (from shared-ui with 'tasks' layout)
|
||||
export { AppLoadingSkeleton } from '@manacore/shared-ui';
|
||||
|
||||
// Task List Skeletons
|
||||
export { default as TaskItemSkeleton } from './TaskItemSkeleton.svelte';
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
</script>
|
||||
|
||||
{#if !appReady}
|
||||
<AppLoadingSkeleton />
|
||||
<AppLoadingSkeleton layout="tasks" listItemCount={4} />
|
||||
{:else}
|
||||
<div class="min-h-screen bg-background text-foreground">
|
||||
{@render children()}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue