mirror of
https://github.com/khoaliber/dockhand.git
synced 2026-03-02 21:19:05 +00:00
84 lines
2.3 KiB
Svelte
84 lines
2.3 KiB
Svelte
<script lang="ts">
|
|
import { themeStore, type FontSize } from '$lib/stores/theme';
|
|
import { sseConnected } from '$lib/stores/events';
|
|
import { Badge } from '$lib/components/ui/badge';
|
|
import { Wifi } from 'lucide-svelte';
|
|
import type { Component } from 'svelte';
|
|
|
|
interface Props {
|
|
icon: Component;
|
|
title: string;
|
|
count?: number | string;
|
|
total?: number;
|
|
showConnection?: boolean;
|
|
class?: string;
|
|
iconClass?: string;
|
|
countClass?: string;
|
|
}
|
|
|
|
let {
|
|
icon: Icon,
|
|
title,
|
|
count,
|
|
total,
|
|
showConnection = true,
|
|
class: className = '',
|
|
iconClass = '',
|
|
countClass = 'min-w-12'
|
|
}: Props = $props();
|
|
|
|
// Font size scaling for page header
|
|
let fontSize = $state<FontSize>('normal');
|
|
themeStore.subscribe(prefs => fontSize = prefs.fontSize);
|
|
|
|
// Page header text size - shifted smaller (normal = what was small)
|
|
const headerTextClass = $derived(() => {
|
|
switch (fontSize) {
|
|
case 'small': return 'text-lg';
|
|
case 'normal': return 'text-xl';
|
|
case 'medium': return 'text-2xl';
|
|
case 'large': return 'text-2xl';
|
|
case 'xlarge': return 'text-3xl';
|
|
default: return 'text-xl';
|
|
}
|
|
});
|
|
|
|
// Page header icon size - shifted smaller (normal = what was small)
|
|
const headerIconClass = $derived(() => {
|
|
switch (fontSize) {
|
|
case 'small': return 'w-4 h-4';
|
|
case 'normal': return 'w-5 h-5';
|
|
case 'medium': return 'w-6 h-6';
|
|
case 'large': return 'w-6 h-6';
|
|
case 'xlarge': return 'w-7 h-7';
|
|
default: return 'w-5 h-5';
|
|
}
|
|
});
|
|
|
|
// Format count display
|
|
const countDisplay = $derived(() => {
|
|
if (count === undefined) return null;
|
|
const countStr = typeof count === 'number' ? count.toLocaleString() : count;
|
|
if (total !== undefined) {
|
|
return `${countStr} of ${total.toLocaleString()}`;
|
|
}
|
|
return countStr;
|
|
});
|
|
</script>
|
|
|
|
<div class="flex items-center gap-3 {className}">
|
|
<Icon class="{headerIconClass()} {iconClass}" />
|
|
<h1 class="{headerTextClass()} font-bold">{title}</h1>
|
|
{#if countDisplay()}
|
|
<Badge variant="secondary" class="text-xs tabular-nums {countClass} justify-center">
|
|
{countDisplay()}
|
|
</Badge>
|
|
{/if}
|
|
{#if showConnection}
|
|
<span title={$sseConnected ? 'Live updates active - grid will auto-refresh' : 'Connecting to live updates...'}>
|
|
<Wifi class="w-3.5 h-3.5 {$sseConnected ? 'text-emerald-500' : 'text-muted-foreground'}" />
|
|
</span>
|
|
{/if}
|
|
<slot />
|
|
</div>
|