- Created 11 reusable UI components: PageHeader, SectionCard, StatCard, StatusBadge, TabBar, MemberList, ActivityFeed, EventCard, ContentSkeleton, QuickLinkGrid, ModuleCard - Created route-specific +layout.svelte for documents, calendar, kanban, events, settings, account - Each layout renders PageHeader instantly from parent data, shows ContentSkeleton during navigation - Removed full-page PageSkeleton from parent layout - Refactored all pages to use new components instead of inline markup - Overview page: uses StatCard, SectionCard, EventCard, ActivityFeed, MemberList, QuickLinkGrid - Events list: uses EventCard, Button components - Event detail: uses ModuleCard, SectionCard - Settings/Account/Calendar/Kanban: headers in layouts, toolbars in pages - Added i18n keys for overview page (EN + ET) - 0 errors, 112 tests pass
47 lines
1014 B
Svelte
47 lines
1014 B
Svelte
<script lang="ts">
|
|
import type { Snippet } from "svelte";
|
|
|
|
interface Props {
|
|
title: string;
|
|
subtitle?: string;
|
|
icon?: string;
|
|
iconColor?: string;
|
|
actions?: Snippet;
|
|
class?: string;
|
|
}
|
|
|
|
let {
|
|
title,
|
|
subtitle,
|
|
icon,
|
|
iconColor = "text-white",
|
|
actions,
|
|
class: className = "",
|
|
}: Props = $props();
|
|
</script>
|
|
|
|
<header
|
|
class="flex items-center justify-between px-6 py-5 border-b border-light/5 shrink-0 {className}"
|
|
>
|
|
<div class="flex items-center gap-3 min-w-0">
|
|
{#if icon}
|
|
<span
|
|
class="material-symbols-rounded {iconColor} shrink-0"
|
|
style="font-size: 28px; font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 28;"
|
|
>{icon}</span
|
|
>
|
|
{/if}
|
|
<div class="min-w-0">
|
|
<h1 class="text-h1 font-heading text-white truncate">{title}</h1>
|
|
{#if subtitle}
|
|
<p class="text-body-sm text-light/50 mt-0.5">{subtitle}</p>
|
|
{/if}
|
|
</div>
|
|
</div>
|
|
{#if actions}
|
|
<div class="flex items-center gap-2 shrink-0 ml-4">
|
|
{@render actions()}
|
|
</div>
|
|
{/if}
|
|
</header>
|