refactor: Icons

This commit is contained in:
Aleksander Grygier 2025-11-26 00:43:49 +01:00
parent 5207527e9d
commit 22507fed74
3 changed files with 72 additions and 11 deletions

View File

@ -1,9 +1,10 @@
<script lang="ts">
import { Paperclip, Image, FileText, File, Volume2 } from '@lucide/svelte';
import { Paperclip } from '@lucide/svelte';
import { Button } from '$lib/components/ui/button';
import * as DropdownMenu from '$lib/components/ui/dropdown-menu';
import * as Tooltip from '$lib/components/ui/tooltip';
import { TOOLTIP_DELAY_DURATION } from '$lib/constants/tooltip-config';
import { FILE_TYPE_ICONS } from '$lib/constants/modality-icons';
import { FileTypeCategory } from '$lib/enums';
interface Props {
@ -63,7 +64,7 @@
disabled={!hasVisionModality}
onclick={() => handleFileUpload(FileTypeCategory.IMAGE)}
>
<Image class="h-4 w-4" />
<FILE_TYPE_ICONS.image class="h-4 w-4" />
<span>Images</span>
</DropdownMenu.Item>
@ -83,7 +84,7 @@
disabled={!hasAudioModality}
onclick={() => handleFileUpload(FileTypeCategory.AUDIO)}
>
<Volume2 class="h-4 w-4" />
<FILE_TYPE_ICONS.audio class="h-4 w-4" />
<span>Audio Files</span>
</DropdownMenu.Item>
@ -100,7 +101,7 @@
class="flex cursor-pointer items-center gap-2"
onclick={() => handleFileUpload(FileTypeCategory.TEXT)}
>
<FileText class="h-4 w-4" />
<FILE_TYPE_ICONS.text class="h-4 w-4" />
<span>Text Files</span>
</DropdownMenu.Item>
@ -111,7 +112,7 @@
class="flex cursor-pointer items-center gap-2"
onclick={() => handleFileUpload(FileTypeCategory.PDF)}
>
<File class="h-4 w-4" />
<FILE_TYPE_ICONS.pdf class="h-4 w-4" />
<span>PDF Files</span>
</DropdownMenu.Item>

View File

@ -9,10 +9,12 @@
modelsLoading,
modelsUpdating,
selectModel,
selectedModelId
selectedModelId,
modelsStore
} from '$lib/stores/models.svelte';
import { isRouterMode, propsStore } from '$lib/stores/props.svelte';
import { DialogModelInformation } from '$lib/components/app';
import { MODALITY_ICONS } from '$lib/constants/modality-icons';
import type { ModelOption } from '$lib/types/models';
interface Props {
@ -379,19 +381,49 @@
<div class="my-1 h-px bg-border"></div>
{/if}
{#each options as option (option.id)}
{@const isLoaded = modelsStore.isModelLoaded(option.model)}
{@const hasVision = option.capabilities.includes('vision')}
{@const hasAudio = option.capabilities.includes('audio')}
{@const isSelected = currentModel === option.model || activeId === option.id}
<button
type="button"
class={cn(
'flex w-full cursor-pointer items-center px-3 py-2 text-left text-sm transition hover:bg-muted focus:bg-muted focus:outline-none',
currentModel === option.model || activeId === option.id
'flex w-full cursor-pointer items-center gap-2 px-3 py-2 text-left text-sm transition hover:bg-muted focus:bg-muted focus:outline-none',
isSelected
? 'bg-accent text-accent-foreground'
: 'text-popover-foreground hover:bg-accent hover:text-accent-foreground'
: 'hover:bg-accent hover:text-accent-foreground',
isLoaded ? 'text-popover-foreground' : 'text-muted-foreground'
)}
role="option"
aria-selected={currentModel === option.model || activeId === option.id}
aria-selected={isSelected}
onclick={() => handleSelect(option.id)}
>
<span class="truncate">{option.model}</span>
<!-- Status dot -->
<span
class={cn(
'h-2 w-2 shrink-0 rounded-full',
isLoaded ? 'bg-green-500' : 'bg-muted-foreground/50'
)}
></span>
<!-- Model name -->
<span class="min-w-0 flex-1 truncate">{option.model}</span>
<!-- Modality icons -->
<div class="flex shrink-0 items-center gap-1">
<MODALITY_ICONS.vision
class={cn(
'h-3.5 w-3.5',
hasVision ? 'text-foreground' : 'text-muted-foreground/40'
)}
/>
<MODALITY_ICONS.audio
class={cn(
'h-3.5 w-3.5',
hasAudio ? 'text-foreground' : 'text-muted-foreground/40'
)}
/>
</div>
</button>
{/each}
</div>

View File

@ -0,0 +1,28 @@
/**
* Icon mappings for file types and model modalities
* Centralized configuration to ensure consistent icon usage across the app
*/
import {
File as FileIcon,
FileText as FileTextIcon,
Image as ImageIcon,
Volume2 as AudioIcon
} from '@lucide/svelte';
import { FileTypeCategory } from '$lib/enums';
export const FILE_TYPE_ICONS = {
[FileTypeCategory.IMAGE]: ImageIcon,
[FileTypeCategory.AUDIO]: AudioIcon,
[FileTypeCategory.TEXT]: FileTextIcon,
[FileTypeCategory.PDF]: FileIcon
} as const;
export const DEFAULT_FILE_ICON = FileIcon;
export type ModelModality = 'vision' | 'audio';
export const MODALITY_ICONS = {
vision: ImageIcon,
audio: AudioIcon
} as const;