refactor: Icons
This commit is contained in:
parent
5207527e9d
commit
22507fed74
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
Loading…
Reference in New Issue