feat: UI improvements

This commit is contained in:
Aleksander Grygier 2026-01-27 11:07:20 +01:00
parent d4a6815ea9
commit 7eff7a31de
3 changed files with 25 additions and 57 deletions

View File

@ -1,4 +1,5 @@
<script lang="ts">
import Badge from '$lib/components/ui/badge/badge.svelte';
import type { MCPPromptInfo, MCPServerSettingsEntry } from '$lib/types';
import { getFaviconUrl } from '$lib/utils';
@ -14,31 +15,30 @@
</script>
<div class="flex items-start gap-3">
{#if faviconUrl}
<img
src={faviconUrl}
alt=""
class="mt-0.5 h-5 w-5 shrink-0 rounded"
onerror={(e) => {
(e.currentTarget as HTMLImageElement).style.display = 'none';
}}
/>
{/if}
<div class="min-w-0 flex-1">
<div class="text-xs text-muted-foreground">
{serverLabel}
</div>
<div class="mb-0.5 flex items-center gap-1.5 text-xs text-muted-foreground">
{#if faviconUrl}
<img
src={faviconUrl}
alt=""
class="h-3 w-3 shrink-0 rounded-sm"
onerror={(e) => {
(e.currentTarget as HTMLImageElement).style.display = 'none';
}}
/>
{/if}
<span>{serverLabel}</span>
</div>
<div class="flex items-center gap-2">
<span class="font-medium">
{prompt.title || prompt.name}
</span>
{#if prompt.arguments?.length}
<span class="rounded-full bg-muted px-1.5 py-0.5 text-xs text-muted-foreground">
<Badge variant="secondary">
{prompt.arguments.length} arg{prompt.arguments.length > 1 ? 's' : ''}
</span>
</Badge>
{/if}
</div>

View File

@ -4,6 +4,7 @@
import ChatFormPromptPickerListItem from './ChatFormPromptPickerListItem.svelte';
import ChatFormPromptPickerListItemSkeleton from './ChatFormPromptPickerListItemSkeleton.svelte';
import { SvelteMap } from 'svelte/reactivity';
import ScrollArea from '$lib/components/ui/scroll-area/scroll-area.svelte';
interface Props {
prompts: MCPPromptInfo[];
@ -28,14 +29,14 @@
}: Props = $props();
</script>
<div>
<ScrollArea>
{#if showSearchInput}
<div class="p-2 pb-0">
<div class="absolute top-0 right-0 left-0 z-10 p-2 pb-0">
<SearchInput placeholder="Search prompts..." bind:value={searchQuery} />
</div>
{/if}
<div class="max-h-64 overflow-y-auto p-2">
<div class="max-h-64 p-2" class:pt-13={showSearchInput}>
{#if isLoading}
<ChatFormPromptPickerListItemSkeleton />
{:else if prompts.length === 0}
@ -57,4 +58,4 @@
{/each}
{/if}
</div>
</div>
</ScrollArea>

View File

@ -1,6 +1,6 @@
<script lang="ts">
import type { MCPPromptInfo, MCPServerSettingsEntry } from '$lib/types';
import { getFaviconUrl } from '$lib/utils';
import ChatFormPromptPickerHeader from './ChatFormPromptPickerHeader.svelte';
interface Props {
prompt: MCPPromptInfo;
@ -11,47 +11,14 @@
}
let { prompt, server, serverLabel, isSelected = false, onClick }: Props = $props();
let faviconUrl = $derived(server ? getFaviconUrl(server.url) : null);
</script>
<button
type="button"
onclick={onClick}
class="flex w-full cursor-pointer items-start gap-3 rounded-lg px-3 py-2 text-left hover:bg-accent {isSelected
? 'bg-accent'
class="flex w-full cursor-pointer items-start gap-3 rounded-lg px-3 py-2 text-left hover:bg-accent/50 {isSelected
? 'bg-accent/50'
: ''}"
>
<div class="min-w-0 flex-1">
<div class="mb-0.5 flex items-center gap-1.5 text-xs text-muted-foreground">
{#if faviconUrl}
<img
src={faviconUrl}
alt=""
class="h-3 w-3 shrink-0 rounded-sm"
onerror={(e) => {
(e.currentTarget as HTMLImageElement).style.display = 'none';
}}
/>
{/if}
<span>{serverLabel}</span>
</div>
<div class="flex items-center gap-2">
<span class="font-medium">{prompt.title || prompt.name}</span>
{#if prompt.arguments && prompt.arguments.length > 0}
<span class="text-xs text-muted-foreground">
({prompt.arguments.length} arg{prompt.arguments.length > 1 ? 's' : ''})
</span>
{/if}
</div>
{#if prompt.description}
<p class="truncate text-sm text-muted-foreground">
{prompt.description}
</p>
{/if}
</div>
<ChatFormPromptPickerHeader {prompt} {server} {serverLabel} />
</button>