Files
dockhand-upstream/src/lib/components/ModalHeader.svelte
T
2026-07-25 08:41:01 +02:00

49 lines
1.7 KiB
Svelte

<script lang="ts">
import type { Component, Snippet } from 'svelte';
import * as Dialog from '$lib/components/ui/dialog';
import * as Tooltip from '$lib/components/ui/tooltip';
import { currentEnvironment } from '$lib/stores/environment';
// Unified modal header: [icon] Title [truncated resource name] on <amber env>.
// The resource name truncates with an ellipsis and shows the full value in a
// shadcn Tooltip on hover. Content gets an explicit w-80 (the project's proven
// long-text pattern) so it doesn't collapse to w-fit; ignoreNonKeyboardFocus
// stops it opening on the modal's initial focus. The env suffix ("on <name>")
// inherits the title's colour/weight, only the env name is amber. Anything
// else — a rename pencil, a status badge — goes in the `extra` snippet,
// rendered inline after the env suffix.
let {
icon,
title,
name = undefined,
envName = undefined,
extra = undefined
}: {
icon: Component;
title: string;
name?: string;
envName?: string;
extra?: Snippet;
} = $props();
const Icon = $derived(icon);
const env = $derived(envName ?? $currentEnvironment?.name);
</script>
<Dialog.Title class="flex items-center gap-2 min-w-0">
<Icon class="w-5 h-5 shrink-0" />
<span class="shrink-0">{title}</span>
{#if name}
<Tooltip.Root delayDuration={200} ignoreNonKeyboardFocus>
<Tooltip.Trigger class="truncate min-w-0 max-w-[min(60%,28rem)] cursor-default">{name}</Tooltip.Trigger>
<Tooltip.Content class="w-80"><p class="break-all">{name}</p></Tooltip.Content>
</Tooltip.Root>
{/if}
{#if env}
<span class="shrink-0">on <span class="text-amber-600 dark:text-amber-400">{env}</span></span>
{/if}
{#if extra}
<span class="shrink-0 flex items-center gap-2">{@render extra()}</span>
{/if}
</Dialog.Title>