chore: migrate to UI lib icon (#22096)

This commit is contained in:
Daniel Dietzler 2025-09-16 21:40:43 +02:00 committed by GitHub
parent dac545496e
commit 7fe2f19258
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
78 changed files with 243 additions and 345 deletions

View File

@ -1,9 +1,8 @@
<script lang="ts">
import Badge from '$lib/elements/Badge.svelte';
import Icon from '$lib/elements/Icon.svelte';
import { locale } from '$lib/stores/preferences.store';
import { JobCommand, type JobCommandDto, type JobCountsDto, type QueueStatusDto } from '@immich/sdk';
import { IconButton } from '@immich/ui';
import { Icon, IconButton } from '@immich/ui';
import {
mdiAlertCircle,
mdiAllInclusive,
@ -66,7 +65,7 @@
<div class="flex flex-col gap-2 p-5 sm:p-7 md:p-9">
<div class="flex items-center gap-4 text-xl font-semibold text-immich-primary dark:text-immich-dark-primary">
<span class="flex items-center gap-2">
<Icon path={icon} size="1.25em" class="hidden shrink-0 sm:block" />
<Icon {icon} size="1.25em" class="hidden shrink-0 sm:block" />
<span class="uppercase">{title}</span>
</span>
<div class="flex gap-2">
@ -136,7 +135,7 @@
color="light-gray"
onClick={() => onCommand({ command: JobCommand.Start, force: false })}
>
<Icon path={mdiAlertCircle} size="36" />
<Icon icon={mdiAlertCircle} size="36" />
<span class="uppercase">{$t('disabled')}</span>
</JobTileButton>
{/if}
@ -144,7 +143,7 @@
{#if !disabled && !isIdle}
{#if waitingCount > 0}
<JobTileButton color="gray" onClick={() => onCommand({ command: JobCommand.Empty, force: false })}>
<Icon path={mdiClose} size="24" />
<Icon icon={mdiClose} size="24" />
<span class="uppercase">{$t('clear')}</span>
</JobTileButton>
{/if}
@ -152,12 +151,12 @@
{@const size = waitingCount > 0 ? '24' : '48'}
<JobTileButton color="light-gray" onClick={() => onCommand({ command: JobCommand.Resume, force: false })}>
<!-- size property is not reactive, so have to use width and height -->
<Icon path={mdiFastForward} {size} />
<Icon icon={mdiFastForward} {size} />
<span class="uppercase">{$t('resume')}</span>
</JobTileButton>
{:else}
<JobTileButton color="light-gray" onClick={() => onCommand({ command: JobCommand.Pause, force: false })}>
<Icon path={mdiPause} size="24" />
<Icon icon={mdiPause} size="24" />
<span class="uppercase">{$t('pause')}</span>
</JobTileButton>
{/if}
@ -166,25 +165,25 @@
{#if !disabled && multipleButtons && isIdle}
{#if allText}
<JobTileButton color="dark-gray" onClick={() => onCommand({ command: JobCommand.Start, force: true })}>
<Icon path={mdiAllInclusive} size="24" />
<Icon icon={mdiAllInclusive} size="24" />
<span class="uppercase">{allText}</span>
</JobTileButton>
{/if}
{#if refreshText}
<JobTileButton color="gray" onClick={() => onCommand({ command: JobCommand.Start, force: undefined })}>
<Icon path={mdiImageRefreshOutline} size="24" />
<Icon icon={mdiImageRefreshOutline} size="24" />
<span class="uppercase">{refreshText}</span>
</JobTileButton>
{/if}
<JobTileButton color="light-gray" onClick={() => onCommand({ command: JobCommand.Start, force: false })}>
<Icon path={mdiSelectionSearch} size="24" />
<Icon icon={mdiSelectionSearch} size="24" />
<span class="uppercase">{missingText}</span>
</JobTileButton>
{/if}
{#if !disabled && !multipleButtons && isIdle}
<JobTileButton color="light-gray" onClick={() => onCommand({ command: JobCommand.Start, force: false })}>
<Icon path={mdiPlay} size="48" />
<Icon icon={mdiPlay} size="48" />
<span class="uppercase">{missingText}</span>
</JobTileButton>
{/if}

View File

@ -1,8 +1,8 @@
<script lang="ts">
import Icon from '$lib/elements/Icon.svelte';
import { locale } from '$lib/stores/preferences.store';
import { getByteUnitString, getBytesWithUnit } from '$lib/utils/byte-units';
import type { ServerStatsResponseDto } from '@immich/sdk';
import { Icon } from '@immich/ui';
import { mdiCameraIris, mdiChartPie, mdiPlayCircle } from '@mdi/js';
import { t } from 'svelte-i18n';
import StatsCard from './stats-card.svelte';
@ -47,7 +47,7 @@
<div class="flex flex-col justify-between rounded-3xl bg-subtle p-5 dark:bg-immich-dark-gray">
<div class="flex flex-wrap gap-x-12">
<div class="flex place-items-center gap-4 text-immich-primary dark:text-immich-dark-primary">
<Icon path={mdiCameraIris} size="25" />
<Icon icon={mdiCameraIris} size="25" />
<p class="uppercase">{$t('photos')}</p>
</div>
@ -59,7 +59,7 @@
</div>
<div class="flex flex-wrap gap-x-12">
<div class="flex place-items-center gap-4 text-immich-primary dark:text-immich-dark-primary">
<Icon path={mdiPlayCircle} size="25" />
<Icon icon={mdiPlayCircle} size="25" />
<p class="uppercase">{$t('videos')}</p>
</div>
@ -71,7 +71,7 @@
</div>
<div class="flex flex-wrap gap-x-7">
<div class="flex place-items-center gap-4 text-immich-primary dark:text-immich-dark-primary">
<Icon path={mdiChartPie} size="25" />
<Icon icon={mdiChartPie} size="25" />
<p class="uppercase">{$t('storage')}</p>
</div>

View File

@ -1,7 +1,6 @@
<script lang="ts">
import Icon from '$lib/elements/Icon.svelte';
import { ByteUnit } from '$lib/utils/byte-units';
import { Code, Text } from '@immich/ui';
import { Code, Icon, Text } from '@immich/ui';
interface Props {
icon: string;
@ -23,7 +22,7 @@
<div class="flex h-[140px] w-full flex-col justify-between rounded-3xl bg-subtle text-primary p-5">
<div class="flex place-items-center gap-4">
<Icon path={icon} size="40" />
<Icon {icon} size="40" />
<Text size="large" fontWeight="bold" class="uppercase">{title}</Text>
</div>

View File

@ -7,7 +7,6 @@
import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte';
import { SettingInputFieldType } from '$lib/constants';
import FormatMessage from '$lib/elements/FormatMessage.svelte';
import Icon from '$lib/elements/Icon.svelte';
import {
AudioCodec,
CQMode,
@ -18,6 +17,7 @@
VideoContainer,
type SystemConfigDto,
} from '@immich/sdk';
import { Icon } from '@immich/ui';
import { mdiHelpCircleOutline } from '@mdi/js';
import { isEqual, sortBy } from 'lodash-es';
import { t } from 'svelte-i18n';
@ -45,7 +45,7 @@
<form autocomplete="off" {onsubmit}>
<div class="ms-4 mt-4 flex flex-col gap-4">
<p class="text-sm dark:text-immich-dark-fg">
<Icon path={mdiHelpCircleOutline} class="inline" size="15" />
<Icon icon={mdiHelpCircleOutline} class="inline" size="15" />
<FormatMessage key="admin.transcoding_codecs_learn_more">
{#snippet children({ tag, message })}
{#if tag === 'h264-link'}

View File

@ -3,11 +3,10 @@
import SettingAccordion from '$lib/components/shared-components/settings/setting-accordion.svelte';
import SettingTextarea from '$lib/components/shared-components/settings/setting-textarea.svelte';
import FormatMessage from '$lib/elements/FormatMessage.svelte';
import Icon from '$lib/elements/Icon.svelte';
import EmailTemplatePreviewModal from '$lib/modals/EmailTemplatePreviewModal.svelte';
import { handleError } from '$lib/utils/handle-error';
import { type SystemConfigDto, type SystemConfigTemplateEmailsDto, getNotificationTemplateAdmin } from '@immich/sdk';
import { Button, modalManager } from '@immich/ui';
import { Button, Icon, modalManager } from '@immich/ui';
import { mdiEyeOutline } from '@mdi/js';
import { t } from 'svelte-i18n';
import { fade } from 'svelte/transition';
@ -96,7 +95,7 @@
onclick={() => getTemplate(templateName, config.templates.email[templateKey])}
title={$t('admin.template_email_preview')}
>
<Icon path={mdiEyeOutline} class="me-1" />
<Icon icon={mdiEyeOutline} class="me-1" />
{$t('admin.template_email_preview')}
</Button>
</div>

View File

@ -1,11 +1,11 @@
<script lang="ts">
import AlbumCard from '$lib/components/album-page/album-card.svelte';
import { AppRoute } from '$lib/constants';
import Icon from '$lib/elements/Icon.svelte';
import { albumViewSettings } from '$lib/stores/preferences.store';
import { type AlbumGroup, isAlbumGroupCollapsed, toggleAlbumGroupCollapsing } from '$lib/utils/album-utils';
import type { ContextMenuPosition } from '$lib/utils/context-menu';
import type { AlbumResponseDto } from '@immich/sdk';
import { Icon } from '@immich/ui';
import { mdiChevronRight } from '@mdi/js';
import { t } from 'svelte-i18n';
import { flip } from 'svelte/animate';
@ -51,7 +51,7 @@
class="w-full text-start mt-2 pt-2 pe-2 pb-2 rounded-md transition-colors cursor-pointer dark:text-immich-dark-fg hover:text-immich-primary dark:hover:text-immich-dark-primary hover:bg-subtle dark:hover:bg-immich-dark-gray"
aria-expanded={!isCollapsed}
>
<Icon path={mdiChevronRight} size="24" class="inline-block -mt-2.5 transition-all duration-250 {iconRotation}" />
<Icon icon={mdiChevronRight} size="24" class="inline-block -mt-2.5 transition-all duration-250 {iconRotation}" />
<span class="font-bold text-3xl text-black dark:text-white">{group.name}</span>
<span class="ms-1.5">({$t('albums_count', { values: { count: albums.length } })})</span>
</button>

View File

@ -1,11 +1,11 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { AppRoute, dateFormats } from '$lib/constants';
import Icon from '$lib/elements/Icon.svelte';
import { locale } from '$lib/stores/preferences.store';
import { user } from '$lib/stores/user.store';
import type { ContextMenuPosition } from '$lib/utils/context-menu';
import type { AlbumResponseDto } from '@immich/sdk';
import { Icon } from '@immich/ui';
import { mdiShareVariantOutline } from '@mdi/js';
import { t } from 'svelte-i18n';
@ -39,7 +39,7 @@
{album.albumName}
{#if album.shared}
<Icon
path={mdiShareVariantOutline}
icon={mdiShareVariantOutline}
size="16"
class="inline ms-1 opacity-70"
title={album.ownerId === $user.id

View File

@ -1,7 +1,6 @@
<script lang="ts">
import AlbumTableHeader from '$lib/components/album-page/albums-table-header.svelte';
import AlbumTableRow from '$lib/components/album-page/albums-table-row.svelte';
import Icon from '$lib/elements/Icon.svelte';
import { AlbumGroupBy, albumViewSettings } from '$lib/stores/preferences.store';
import {
isAlbumGroupCollapsed,
@ -11,6 +10,7 @@
} from '$lib/utils/album-utils';
import type { ContextMenuPosition } from '$lib/utils/context-menu';
import type { AlbumResponseDto } from '@immich/sdk';
import { Icon } from '@immich/ui';
import { mdiChevronRight } from '@mdi/js';
import { t } from 'svelte-i18n';
import { slide } from 'svelte/transition';
@ -54,7 +54,7 @@
>
<td class="text-md text-start -mb-1">
<Icon
path={mdiChevronRight}
icon={mdiChevronRight}
size="20"
class="inline-block -mt-2 transition-all duration-250 {iconRotation}"
/>

View File

@ -1,6 +1,6 @@
<script lang="ts">
import { shortcuts } from '$lib/actions/shortcut';
import Icon from '$lib/elements/Icon.svelte';
import { Icon } from '@immich/ui';
import { mdiChevronRight } from '@mdi/js';
import { t } from 'svelte-i18n';
import NavigationArea from '../navigation-area.svelte';
@ -20,5 +20,5 @@
/>
<NavigationArea onClick={onNextAsset} label={$t('view_next_asset')}>
<Icon path={mdiChevronRight} size="36" ariaHidden />
<Icon icon={mdiChevronRight} size="36" aria-hidden />
</NavigationArea>

View File

@ -1,6 +1,6 @@
<script lang="ts">
import { shortcuts } from '$lib/actions/shortcut';
import Icon from '$lib/elements/Icon.svelte';
import { Icon } from '@immich/ui';
import { mdiChevronLeft } from '@mdi/js';
import { t } from 'svelte-i18n';
import NavigationArea from '../navigation-area.svelte';
@ -20,5 +20,5 @@
/>
<NavigationArea onClick={onPreviousAsset} label={$t('view_previous_asset')}>
<Icon path={mdiChevronLeft} size="36" ariaHidden />
<Icon icon={mdiChevronLeft} size="36" aria-hidden />
</NavigationArea>

View File

@ -1,7 +1,7 @@
<script lang="ts">
import Icon from '$lib/elements/Icon.svelte';
import { locale } from '$lib/stores/preferences.store';
import type { ActivityResponseDto } from '@immich/sdk';
import { Icon } from '@immich/ui';
import { mdiCommentOutline, mdiHeart, mdiHeartOutline } from '@mdi/js';
interface Props {
@ -19,7 +19,7 @@
<div class="w-full flex p-4 items-center justify-center rounded-full gap-5 bg-subtle border bg-opacity-60">
<button type="button" class={disabled ? 'cursor-not-allowed' : ''} onclick={onFavorite} {disabled}>
<div class="flex gap-2 items-center justify-center">
<Icon path={isLiked ? mdiHeart : mdiHeartOutline} size={24} class={isLiked ? 'text-red-400' : 'text-fg'} />
<Icon icon={isLiked ? mdiHeart : mdiHeartOutline} size="24" class={isLiked ? 'text-red-400' : 'text-fg'} />
{#if numberOfLikes}
<div class="text-l">{numberOfLikes.toLocaleString($locale)}</div>
{/if}
@ -27,7 +27,7 @@
</button>
<button type="button" onclick={onOpenActivityTab}>
<div class="flex gap-2 items-center justify-center">
<Icon path={mdiCommentOutline} class="scale-x-[-1]" size={24} />
<Icon icon={mdiCommentOutline} class="scale-x-[-1]" size="24" />
{#if numberOfComments}
<div class="text-l">{numberOfComments.toLocaleString($locale)}</div>
{/if}

View File

@ -4,7 +4,6 @@
import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte';
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
import { AppRoute, timeBeforeShowLoadingSpinner } from '$lib/constants';
import Icon from '$lib/elements/Icon.svelte';
import { activityManager } from '$lib/managers/activity-manager.svelte';
import { locale } from '$lib/stores/preferences.store';
import { getAssetThumbnailUrl } from '$lib/utils';
@ -12,7 +11,7 @@
import { handleError } from '$lib/utils/handle-error';
import { isTenMinutesApart } from '$lib/utils/timesince';
import { ReactionType, type ActivityResponseDto, type AssetTypeEnum, type UserResponseDto } from '@immich/sdk';
import { IconButton } from '@immich/ui';
import { Icon, IconButton } from '@immich/ui';
import { mdiClose, mdiDeleteOutline, mdiDotsVertical, mdiHeart, mdiSend } from '@mdi/js';
import * as luxon from 'luxon';
import { t } from 'svelte-i18n';
@ -187,7 +186,7 @@
{:else if reaction.type === ReactionType.Like}
<div class="relative">
<div class="flex py-3 ps-3 mt-3 gap-4 items-center text-sm">
<div class="text-red-600"><Icon path={mdiHeart} size={20} /></div>
<div class="text-red-600"><Icon icon={mdiHeart} size="20" /></div>
<div class="w-full" title={`${reaction.user.name} (${reaction.user.email})`}>
{$t('user_liked', {

View File

@ -1,10 +1,10 @@
<script lang="ts">
import { SCROLL_PROPERTIES } from '$lib/components/shared-components/album-selection/album-selection-utils';
import Icon from '$lib/elements/Icon.svelte';
import { mobileDevice } from '$lib/stores/mobile-device.svelte';
import { getAssetThumbnailUrl } from '$lib/utils';
import { normalizeSearchString } from '$lib/utils/string-utils.js';
import { type AlbumResponseDto } from '@immich/sdk';
import { Icon } from '@immich/ui';
import { mdiCheckCircle } from '@mdi/js';
import type { Action } from 'svelte/action';
import AlbumListItemDetails from './album-list-item-details.svelte';
@ -165,10 +165,10 @@
>
{#if multiSelected}
<div class="rounded-full">
<Icon path={mdiCheckCircle} size="24" class="text-primary" />
<Icon icon={mdiCheckCircle} size="24" class="text-primary" />
</div>
{:else}
<Icon path={mdiCheckCircle} size="24" class="text-gray-300 hover:text-primary/75" />
<Icon icon={mdiCheckCircle} size="24" class="text-gray-300 hover:text-primary/75" />
{/if}
</button>
{/if}

View File

@ -1,9 +1,9 @@
<script lang="ts">
import ChangeLocation from '$lib/components/shared-components/change-location.svelte';
import Icon from '$lib/elements/Icon.svelte';
import Portal from '$lib/elements/Portal.svelte';
import { handleError } from '$lib/utils/handle-error';
import { updateAsset, type AssetResponseDto } from '@immich/sdk';
import { Icon } from '@immich/ui';
import { mdiMapMarkerOutline, mdiPencil } from '@mdi/js';
import { t } from 'svelte-i18n';
@ -44,7 +44,7 @@
class:hover:text-immich-primary={isOwner}
>
<div class="flex gap-4">
<div><Icon path={mdiMapMarkerOutline} size="24" /></div>
<div><Icon icon={mdiMapMarkerOutline} size="24" /></div>
<div>
{#if asset.exifInfo?.city}
@ -65,7 +65,7 @@
{#if isOwner}
<div>
<Icon path={mdiPencil} size="20" />
<Icon icon={mdiPencil} size="20" />
</div>
{/if}
</button>
@ -77,12 +77,12 @@
title={$t('add_location')}
>
<div class="flex gap-4">
<div><Icon path={mdiMapMarkerOutline} size="24" /></div>
<div><Icon icon={mdiMapMarkerOutline} size="24" /></div>
<p>{$t('add_a_location')}</p>
</div>
<div class="focus:outline-none p-1">
<Icon path={mdiPencil} size="20" />
<Icon icon={mdiPencil} size="20" />
</div>
</button>
{/if}

View File

@ -1,12 +1,11 @@
<script lang="ts">
import { shortcut } from '$lib/actions/shortcut';
import { AppRoute } from '$lib/constants';
import Icon from '$lib/elements/Icon.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import AssetTagModal from '$lib/modals/AssetTagModal.svelte';
import { removeTag } from '$lib/utils/asset-utils';
import { getAssetInfo, type AssetResponseDto } from '@immich/sdk';
import { modalManager } from '@immich/ui';
import { Icon, modalManager } from '@immich/ui';
import { mdiClose, mdiPlus } from '@mdi/js';
import { t } from 'svelte-i18n';
@ -59,7 +58,7 @@
title="Remove tag"
onclick={() => handleRemove(tag.id)}
>
<Icon path={mdiClose} />
<Icon icon={mdiClose} />
</button>
</div>
{/each}
@ -70,7 +69,7 @@
onclick={handleAddTag}
>
<span class="text-sm px-1 flex place-items-center place-content-center gap-1"
><Icon path={mdiPlus} />{$t('add')}</span
><Icon icon={mdiPlus} />{$t('add')}</span
>
</button>
</section>

View File

@ -9,7 +9,6 @@
type RelativeResult,
} from '$lib/components/shared-components/change-date.svelte';
import { AppRoute, QueryParameter, timeToLoadTheMap } from '$lib/constants';
import Icon from '$lib/elements/Icon.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { isFaceEditMode } from '$lib/stores/face-edit.svelte';
import { boundingBoxesArray } from '$lib/stores/people.store';
@ -24,7 +23,7 @@
import { fromISODateTime, fromISODateTimeUTC } from '$lib/utils/timeline-util';
import { getParentPath } from '$lib/utils/tree-utils';
import { AssetMediaSize, getAssetInfo, updateAsset, type AlbumResponseDto, type AssetResponseDto } from '@immich/sdk';
import { IconButton } from '@immich/ui';
import { Icon, IconButton } from '@immich/ui';
import {
mdiCalendar,
mdiCameraIris,
@ -286,7 +285,7 @@
>
<div class="flex gap-4">
<div>
<Icon path={mdiCalendar} size="24" />
<Icon icon={mdiCalendar} size="24" />
</div>
<div>
@ -318,7 +317,7 @@
{#if isOwner}
<div class="p-1">
<Icon path={mdiPencil} size="20" />
<Icon icon={mdiPencil} size="20" />
</div>
{/if}
</button>
@ -326,11 +325,11 @@
<div class="flex justify-between place-items-start gap-4 py-4">
<div class="flex gap-4">
<div>
<Icon path={mdiCalendar} size="24" />
<Icon icon={mdiCalendar} size="24" />
</div>
</div>
<div class="p-1">
<Icon path={mdiPencil} size="20" />
<Icon icon={mdiPencil} size="20" />
</div>
</div>
{/if}
@ -346,7 +345,7 @@
{/if}
<div class="flex gap-4 py-4">
<div><Icon path={mdiImageOutline} size="24" /></div>
<div><Icon icon={mdiImageOutline} size="24" /></div>
<div>
<p class="break-all flex place-items-center gap-2 whitespace-pre-wrap">
@ -394,7 +393,7 @@
{#if asset.exifInfo?.make || asset.exifInfo?.model || asset.exifInfo?.fNumber}
<div class="flex gap-4 py-4">
<div><Icon path={mdiCameraIris} size="24" /></div>
<div><Icon icon={mdiCameraIris} size="24" /></div>
<div>
{#if asset.exifInfo?.make || asset.exifInfo?.model}

View File

@ -1,7 +1,6 @@
<script lang="ts">
import Icon from '$lib/elements/Icon.svelte';
import type { CropAspectRatio } from '$lib/stores/asset-editor.store';
import { Button, type Color } from '@immich/ui';
import { Button, Icon, type Color } from '@immich/ui';
interface Props {
size: {
@ -38,7 +37,7 @@
<li>
<Button shape="round" color={buttonColor} class="flex-col gap-1" size="small" onclick={() => selectType(size.name)}>
<Icon size="1.75em" path={size.icon} viewBox={size.viewBox} class={toRotate(size.rotate) ? 'rotate-90' : ''} />
<Icon size="1.75em" icon={size.icon} viewBox={size.viewBox} class={toRotate(size.rotate) ? 'rotate-90' : ''} />
<span>{rotatedTitle(size.name, rotateHorizontal)}</span>
</Button>
</li>

View File

@ -1,9 +1,8 @@
<script lang="ts">
import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte';
import Icon from '$lib/elements/Icon.svelte';
import { castManager, CastState } from '$lib/managers/cast-manager.svelte';
import { handleError } from '$lib/utils/handle-error';
import { IconButton } from '@immich/ui';
import { Icon, IconButton } from '@immich/ui';
import { mdiCastConnected, mdiPause, mdiPlay } from '@mdi/js';
import { t } from 'svelte-i18n';
@ -72,7 +71,7 @@
</script>
<span class="flex items-center space-x-2 text-gray-200 text-2xl font-bold">
<Icon path={mdiCastConnected} class="text-primary" size="36" />
<Icon icon={mdiCastConnected} class="text-primary" size="36" />
<span>{$t('connected_to')} {castManager.receiverName}</span>
</span>

View File

@ -1,5 +1,5 @@
<script lang="ts">
import Icon from '$lib/elements/Icon.svelte';
import { Icon } from '@immich/ui';
import { mdiImageBrokenVariant } from '@mdi/js';
import { t } from 'svelte-i18n';
@ -18,7 +18,7 @@
style:width
style:height
>
<Icon path={mdiImageBrokenVariant} size="7em" class="max-w-full" />
<Icon icon={mdiImageBrokenVariant} size="7em" class="max-w-full" />
{#if !hideMessage}
<span class="text-center">{$t('error_loading_image')}</span>
{/if}

View File

@ -1,7 +1,7 @@
<script lang="ts">
import BrokenAsset from '$lib/components/assets/broken-asset.svelte';
import Icon from '$lib/elements/Icon.svelte';
import { cancelImageUrl } from '$lib/utils/sw-messaging';
import { Icon } from '@immich/ui';
import { mdiEyeOffOutline } from '@mdi/js';
import type { ActionReturn } from 'svelte/action';
import type { ClassValue } from 'svelte/elements';
@ -97,6 +97,7 @@
{#if hidden}
<div class="absolute start-1/2 top-1/2 translate-x-[-50%] translate-y-[-50%] transform">
<Icon {title} path={mdiEyeOffOutline} size="2em" class={hiddenIconClass} />
<!-- TODO fix `title` type -->
<Icon title={title ?? undefined} icon={mdiEyeOffOutline} size="2em" class={hiddenIconClass} />
</div>
{/if}

View File

@ -1,6 +1,5 @@
<script lang="ts">
import { ProjectionType } from '$lib/constants';
import Icon from '$lib/elements/Icon.svelte';
import { locale, playVideoThumbnailOnHover } from '$lib/stores/preferences.store';
import { getAssetPlaybackUrl, getAssetThumbnailUrl } from '$lib/utils';
import { timeToSeconds } from '$lib/utils/date-time';
@ -23,6 +22,7 @@
import { moveFocus } from '$lib/utils/focus-util';
import { currentUrlReplaceAssetId } from '$lib/utils/navigation';
import { TUNABLES } from '$lib/utils/tunables';
import { Icon } from '@immich/ui';
import { onMount } from 'svelte';
import type { ClassValue } from 'svelte/elements';
import { fade } from 'svelte/transition';
@ -263,20 +263,20 @@
<!-- Favorite asset star -->
{#if !authManager.isSharedLink && asset.isFavorite}
<div class="absolute bottom-2 start-2">
<Icon path={mdiHeart} size="24" class="text-white" />
<Icon icon={mdiHeart} size="24" class="text-white" />
</div>
{/if}
{#if !authManager.isSharedLink && showArchiveIcon && asset.visibility === AssetVisibility.Archive}
<div class={['absolute start-2', asset.isFavorite ? 'bottom-10' : 'bottom-2']}>
<Icon path={mdiArchiveArrowDownOutline} size="24" class="text-white" />
<Icon icon={mdiArchiveArrowDownOutline} size="24" class="text-white" />
</div>
{/if}
{#if asset.isImage && asset.projectionType === ProjectionType.EQUIRECTANGULAR}
<div class="absolute end-0 top-0 flex place-items-center gap-1 text-xs font-medium text-white">
<span class="pe-2 pt-2">
<Icon path={mdiRotate360} size="24" />
<Icon icon={mdiRotate360} size="24" />
</span>
</div>
{/if}
@ -291,7 +291,7 @@
>
<span class="pe-2 pt-2 flex place-items-center gap-1">
<p>{asset.stack.assetCount.toLocaleString($locale)}</p>
<Icon path={mdiCameraBurst} size="24" />
<Icon icon={mdiCameraBurst} size="24" />
</span>
</div>
{/if}
@ -378,13 +378,13 @@
{disabled}
>
{#if disabled}
<Icon path={mdiCheckCircle} size="24" class="text-zinc-800" />
<Icon icon={mdiCheckCircle} size="24" class="text-zinc-800" />
{:else if selected}
<div class="rounded-full bg-[#D9DCEF] dark:bg-[#232932]">
<Icon path={mdiCheckCircle} size="24" class="text-primary" />
<Icon icon={mdiCheckCircle} size="24" class="text-primary" />
</div>
{:else}
<Icon path={mdiCheckCircle} size="24" class="text-white/80 hover:text-white" />
<Icon icon={mdiCheckCircle} size="24" class="text-white/80 hover:text-white" />
{/if}
</button>
{/if}

View File

@ -1,6 +1,6 @@
<script lang="ts">
import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte';
import Icon from '$lib/elements/Icon.svelte';
import { Icon } from '@immich/ui';
import { mdiAlertCircleOutline, mdiPauseCircleOutline, mdiPlayCircleOutline } from '@mdi/js';
import { Duration } from 'luxon';
@ -105,12 +105,12 @@
{#if loading}
<LoadingSpinner />
{:else if error}
<Icon path={mdiAlertCircleOutline} size="24" class="text-red-600" />
<Icon icon={mdiAlertCircleOutline} size="24" class="text-red-600" />
{:else}
<Icon path={pauseIcon} size="24" />
<Icon icon={pauseIcon} size="24" />
{/if}
{:else}
<Icon path={playIcon} size="24" />
<Icon icon={playIcon} size="24" />
{/if}
</span>
</div>

View File

@ -2,10 +2,9 @@
import { goto } from '$app/navigation';
import { page } from '$app/state';
import { ActionQueryParameterValue, AppRoute, QueryParameter } from '$lib/constants';
import Icon from '$lib/elements/Icon.svelte';
import { handleError } from '$lib/utils/handle-error';
import { getAllPeople, getPerson, mergePerson, type PersonResponseDto } from '@immich/sdk';
import { Button, IconButton, modalManager } from '@immich/ui';
import { Button, Icon, IconButton, modalManager } from '@immich/ui';
import { mdiCallMerge, mdiMerge, mdiSwapHorizontal } from '@mdi/js';
import { onMount } from 'svelte';
import { t } from 'svelte-i18n';
@ -127,7 +126,7 @@
<div class="relative h-full">
<div class="flex flex-col h-full justify-between">
<div class="flex h-full items-center justify-center">
<Icon path={mdiCallMerge} size={48} class="rotate-90 dark:text-white" />
<Icon icon={mdiCallMerge} size="48" class="rotate-90 dark:text-white" />
</div>
{#if selectedPeople.length === 1}
<div class="absolute bottom-2">

View File

@ -2,9 +2,9 @@
import { focusOutside } from '$lib/actions/focus-outside';
import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte';
import { AppRoute, QueryParameter } from '$lib/constants';
import Icon from '$lib/elements/Icon.svelte';
import { getPeopleThumbnailUrl } from '$lib/utils';
import { type PersonResponseDto } from '@immich/sdk';
import { Icon } from '@immich/ui';
import {
mdiAccountMultipleCheckOutline,
mdiCalendarEditOutline,
@ -55,7 +55,7 @@
/>
{#if person.isFavorite}
<div class="absolute top-4 start-4">
<Icon path={mdiHeart} size="24" class="text-white" />
<Icon icon={mdiHeart} size="24" class="text-white" />
</div>
{/if}
</div>

View File

@ -1,7 +1,6 @@
<script lang="ts">
import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte';
import { timeBeforeShowLoadingSpinner } from '$lib/constants';
import Icon from '$lib/elements/Icon.svelte';
import { assetViewingStore } from '$lib/stores/asset-viewing.store';
import { photoViewerImgElement } from '$lib/stores/assets-store.svelte';
import { boundingBoxesArray } from '$lib/stores/people.store';
@ -19,7 +18,7 @@
type AssetFaceResponseDto,
type PersonResponseDto,
} from '@immich/sdk';
import { IconButton, modalManager } from '@immich/ui';
import { Icon, IconButton, modalManager } from '@immich/ui';
import { mdiAccountOff, mdiArrowLeftThin, mdiPencil, mdiRestart, mdiTrashCan } from '@mdi/js';
import { onMount } from 'svelte';
import { t } from 'svelte-i18n';
@ -337,7 +336,7 @@
<div
class="flex place-content-center place-items-center rounded-full bg-[#d3d3d3] p-1 transition-all absolute start-1/2 top-1/2 translate-x-[-50%] translate-y-[-50%] transform"
>
<Icon color="primary" path={mdiAccountOff} ariaHidden size="24" />
<Icon color="primary" icon={mdiAccountOff} aria-hidden size="24" />
</div>
{/if}
</div>

View File

@ -1,9 +1,8 @@
<script lang="ts">
import Icon from '$lib/elements/Icon.svelte';
import LibraryImportPathModal from '$lib/modals/LibraryImportPathModal.svelte';
import type { ValidateLibraryImportPathResponseDto } from '@immich/sdk';
import { validate, type LibraryResponseDto } from '@immich/sdk';
import { Button, IconButton, modalManager } from '@immich/ui';
import { Button, Icon, IconButton, modalManager } from '@immich/ui';
import { mdiAlertOutline, mdiCheckCircleOutline, mdiPencilOutline, mdiRefresh } from '@mdi/js';
import { onMount } from 'svelte';
import { t } from 'svelte-i18n';
@ -168,9 +167,9 @@
>
<td class="w-1/8 text-ellipsis ps-8 text-sm">
{#if validatedPath.isValid}
<Icon path={mdiCheckCircleOutline} size="24" title={validatedPath.message} class="text-success" />
<Icon icon={mdiCheckCircleOutline} size="24" title={validatedPath.message} class="text-success" />
{:else}
<Icon path={mdiAlertOutline} size="24" title={validatedPath.message} class="text-warning" />
<Icon icon={mdiAlertOutline} size="24" title={validatedPath.message} class="text-warning" />
{/if}
</td>

View File

@ -1,8 +1,7 @@
<script lang="ts">
import ImmichLogo from '$lib/components/shared-components/immich-logo.svelte';
import Icon from '$lib/elements/Icon.svelte';
import { copyToClipboard } from '$lib/utils';
import { IconButton } from '@immich/ui';
import { Icon, IconButton } from '@immich/ui';
import { mdiCodeTags, mdiContentCopy, mdiMessage, mdiPartyPopper } from '@mdi/js';
import { t } from 'svelte-i18n';
@ -74,7 +73,7 @@
class="flex grow basis-0 justify-center p-4"
>
<div class="flex flex-col place-content-center place-items-center gap-2">
<Icon path={mdiMessage} size={24} />
<Icon icon={mdiMessage} size="24" />
<p class="text-sm">{$t('get_help')}</p>
</div>
</a>
@ -86,7 +85,7 @@
class="flex grow basis-0 justify-center p-4"
>
<div class="flex flex-col place-content-center place-items-center gap-2">
<Icon path={mdiPartyPopper} size={24} />
<Icon icon={mdiPartyPopper} size="24" />
<p class="text-sm">{$t('read_changelog')}</p>
</div>
</a>
@ -98,7 +97,7 @@
class="flex grow basis-0 justify-center p-4"
>
<div class="flex flex-col place-content-center place-items-center gap-2">
<Icon path={mdiCodeTags} size={24} />
<Icon icon={mdiCodeTags} size="24" />
<p class="text-sm">{$t('check_logs')}</p>
</div>
</a>

View File

@ -1,7 +1,6 @@
<script lang="ts">
import FormatMessage from '$lib/elements/FormatMessage.svelte';
import Icon from '$lib/elements/Icon.svelte';
import { Stack } from '@immich/ui';
import { Icon, Stack } from '@immich/ui';
import { mdiAlertCircleOutline } from '@mdi/js';
import type { Translations } from 'svelte-i18n';
@ -15,7 +14,7 @@
<div class="flex flex-col">
<Stack gap={2}>
<div class="flex items-start gap-4 p-6 my-10 bg-gray-100 dark:bg-gray-800/40 rounded-xl border border-gray-700/50">
<Icon path={mdiAlertCircleOutline} size="36" class="text-warning flex-shrink-0 mt-0.5" />
<Icon icon={mdiAlertCircleOutline} size="36" class="text-warning flex-shrink-0 mt-0.5" />
<div class="text-gray-800 dark:text-gray-300 leading-relaxed">
<FormatMessage key="admin.backup_onboarding_description">
{#snippet children({ message })}

View File

@ -1,6 +1,5 @@
<script lang="ts">
import Icon from '$lib/elements/Icon.svelte';
import { Button } from '@immich/ui';
import { Button, Icon } from '@immich/ui';
import { mdiArrowLeft, mdiArrowRight, mdiCheck } from '@mdi/js';
import type { Snippet } from 'svelte';
import { t } from 'svelte-i18n';
@ -37,7 +36,7 @@
{#if title || icon}
<div class="flex gap-2 items-center justify-center w-fit">
{#if icon}
<Icon path={icon} size="30" class="text-immich-primary dark:text-immich-dark-primary" />
<Icon {icon} size="30" class="text-immich-primary dark:text-immich-dark-primary" />
{/if}
{#if title}
<p class="uppercase text-xl text-immich-primary dark:text-immich-dark-primary">

View File

@ -1,8 +1,8 @@
<script lang="ts">
import { moonPath, moonViewBox, sunPath, sunViewBox } from '$lib/assets/svg-paths';
import { Theme } from '$lib/constants';
import Icon from '$lib/elements/Icon.svelte';
import { themeManager } from '$lib/managers/theme-manager.svelte';
import { Icon } from '@immich/ui';
import { t } from 'svelte-i18n';
</script>
@ -18,7 +18,7 @@
<div
class="flex flex-col place-items-center place-content-center justify-around h-full w-full text-immich-primary"
>
<Icon path={sunPath} viewBox={sunViewBox} size="96" />
<Icon icon={sunPath} viewBox={sunViewBox} size="96" />
<p class="uppercase font-semibold text-4xl">{$t('light')}</p>
</div>
</button>
@ -30,7 +30,7 @@
<div
class="flex flex-col place-items-center place-content-center justify-around h-full w-full text-immich-dark-primary"
>
<Icon path={moonPath} viewBox={moonViewBox} size="96" />
<Icon icon={moonPath} viewBox={moonViewBox} size="96" />
<p class="uppercase font-semibold text-4xl">{$t('dark')}</p>
</div>
</button>

View File

@ -1,11 +1,11 @@
<script lang="ts">
import { resizeObserver } from '$lib/actions/resize-observer';
import { AppRoute, QueryParameter } from '$lib/constants';
import Icon from '$lib/elements/Icon.svelte';
import { memoryStore } from '$lib/stores/memory.store.svelte';
import { getAssetThumbnailUrl, memoryLaneTitle } from '$lib/utils';
import { getAltText } from '$lib/utils/thumbnail-util';
import { toTimelineAsset } from '$lib/utils/timeline-util';
import { Icon } from '@immich/ui';
import { mdiChevronLeft, mdiChevronRight } from '@mdi/js';
import { onMount } from 'svelte';
import { t } from 'svelte-i18n';
@ -58,7 +58,7 @@
aria-label={$t('previous')}
onclick={scrollLeft}
>
<Icon path={mdiChevronLeft} size="36" ariaLabel={$t('previous')} /></button
<Icon icon={mdiChevronLeft} size="36" aria-label={$t('previous')} /></button
>
</div>
{/if}
@ -74,7 +74,7 @@
aria-label={$t('next')}
onclick={scrollRight}
>
<Icon path={mdiChevronRight} size="36" ariaLabel={$t('next')} /></button
<Icon icon={mdiChevronRight} size="36" aria-label={$t('next')} /></button
>
</div>
{/if}

View File

@ -1,11 +1,11 @@
<script lang="ts">
import { AppRoute } from '$lib/constants';
import Icon from '$lib/elements/Icon.svelte';
import { placesViewSettings } from '$lib/stores/preferences.store';
import { getAssetThumbnailUrl } from '$lib/utils';
import { getMetadataSearchQuery } from '$lib/utils/metadata-search';
import { type PlacesGroup, isPlacesGroupCollapsed, togglePlacesGroupCollapsing } from '$lib/utils/places-utils';
import { AssetMediaSize, type AssetResponseDto } from '@immich/sdk';
import { Icon } from '@immich/ui';
import { mdiChevronRight } from '@mdi/js';
import { t } from 'svelte-i18n';
@ -28,7 +28,7 @@
class="w-fit mt-2 pt-2 pe-2 mb-2 dark:text-immich-dark-fg"
aria-expanded={!isCollapsed}
>
<Icon path={mdiChevronRight} size="24" class="inline-block -mt-2.5 transition-all duration-250 {iconRotation}" />
<Icon icon={mdiChevronRight} size="24" class="inline-block -mt-2.5 transition-all duration-250 {iconRotation}" />
<span class="font-bold text-3xl text-black dark:text-white">{group.name}</span>
<span class="ms-1.5">({$t('places_count', { values: { count: places.length } })})</span>
</button>
@ -52,7 +52,7 @@
/>
</div>
<span
class="w-100 absolute bottom-2 w-full text-ellipsis px-1 text-center text-sm font-medium capitalize text-white backdrop-blur-[1px] hover:cursor-pointer"
class="absolute bottom-2 w-full text-ellipsis px-1 text-center text-sm font-medium capitalize text-white backdrop-blur-[1px] hover:cursor-pointer"
>
{city}
</span>

View File

@ -1,5 +1,4 @@
<script lang="ts">
import Icon from '$lib/elements/Icon.svelte';
import { PlacesGroupBy, type PlacesViewSettings } from '$lib/stores/preferences.store';
import { normalizeSearchString } from '$lib/utils/string-utils';
import { type AssetResponseDto } from '@immich/sdk';
@ -8,6 +7,7 @@
import PlacesCardGroup from './places-card-group.svelte';
import { type PlacesGroup, getSelectedPlacesGroupOption } from '$lib/utils/places-utils';
import { Icon } from '@immich/ui';
import { t } from 'svelte-i18n';
import { run } from 'svelte/legacy';
@ -114,7 +114,7 @@
{:else}
<div class="flex min-h-[calc(66vh-11rem)] w-full place-content-center items-center dark:text-white">
<div class="flex flex-col content-center items-center text-center">
<Icon path={mdiMapMarkerOff} size="3.5em" />
<Icon icon={mdiMapMarkerOff} size="3.5em" />
<p class="mt-5 text-3xl font-medium">{$t('no_places')}</p>
</div>
</div>

View File

@ -1,6 +1,6 @@
<script lang="ts">
import { SCROLL_PROPERTIES } from '$lib/components/shared-components/album-selection/album-selection-utils';
import Icon from '$lib/elements/Icon.svelte';
import { Icon } from '@immich/ui';
import { mdiPlus } from '@mdi/js';
import { t } from 'svelte-i18n';
import type { Action } from 'svelte/action';
@ -31,7 +31,7 @@
class:dark:bg-gray-700={selected}
>
<div class="flex h-12 w-12 items-center justify-center">
<Icon path={mdiPlus} size="30" />
<Icon icon={mdiPlus} size="30" />
</div>
<p class="">
{$t('new_album')}

View File

@ -22,9 +22,8 @@
<script lang="ts">
import { focusOutside } from '$lib/actions/focus-outside';
import { shortcuts } from '$lib/actions/shortcut';
import Icon from '$lib/elements/Icon.svelte';
import { generateId } from '$lib/utils/generate-id';
import { IconButton } from '@immich/ui';
import { Icon, IconButton } from '@immich/ui';
import { mdiClose, mdiMagnify, mdiUnfoldMoreHorizontal } from '@mdi/js';
import { onMount, tick } from 'svelte';
import { t } from 'svelte-i18n';
@ -270,7 +269,7 @@
{#if isActive}
<div class="absolute inset-y-0 start-0 flex items-center ps-3">
<div class="dark:text-immich-dark-fg/75">
<Icon path={mdiMagnify} ariaHidden={true} />
<Icon icon={mdiMagnify} aria-hidden />
</div>
</div>
{/if}
@ -352,7 +351,7 @@
size="small"
/>
{:else if !isOpen}
<Icon path={mdiUnfoldMoreHorizontal} ariaHidden={true} />
<Icon icon={mdiUnfoldMoreHorizontal} aria-hidden />
{/if}
</div>
</div>

View File

@ -1,9 +1,9 @@
<script lang="ts">
import type { Shortcut } from '$lib/actions/shortcut';
import { shortcut as bindShortcut, shortcutLabel as computeShortcutLabel } from '$lib/actions/shortcut';
import Icon from '$lib/elements/Icon.svelte';
import { optionClickCallbackStore, selectedIdStore } from '$lib/stores/context-menu.store';
import { generateId } from '$lib/utils/generate-id';
import { Icon } from '@immich/ui';
interface Props {
text: string;
@ -59,7 +59,7 @@
role="menuitem"
>
{#if icon}
<Icon path={icon} ariaHidden={true} size="18" />
<Icon {icon} aria-hidden size="18" />
{/if}
<div class="w-full">
<div class="flex justify-between">

View File

@ -9,14 +9,13 @@
<script lang="ts">
import { afterNavigate } from '$app/navigation';
import { Theme } from '$lib/constants';
import Icon from '$lib/elements/Icon.svelte';
import { themeManager } from '$lib/managers/theme-manager.svelte';
import MapSettingsModal from '$lib/modals/MapSettingsModal.svelte';
import { mapSettings } from '$lib/stores/preferences.store';
import { serverConfig } from '$lib/stores/server-config.store';
import { getAssetThumbnailUrl, handlePromiseError } from '$lib/utils';
import { getMapMarkers, type MapMarkerResponseDto } from '@immich/sdk';
import { modalManager } from '@immich/ui';
import { Icon, modalManager } from '@immich/ui';
import mapboxRtlUrl from '@mapbox/mapbox-gl-rtl-text/mapbox-gl-rtl-text.min.js?url';
import { mdiCog, mdiMap, mdiMapMarker } from '@mdi/js';
import type { Feature, GeoJsonProperties, Geometry, Point } from 'geojson';
@ -319,9 +318,9 @@
{#if showSettings}
<Control>
<ControlGroup>
<ControlButton onclick={handleSettingsClick}
><Icon path={mdiCog} size="100%" class="text-black/80" /></ControlButton
>
<ControlButton onclick={handleSettingsClick}>
<Icon icon={mdiCog} size="100%" class="text-black/80" />
</ControlButton>
</ControlGroup>
</Control>
{/if}
@ -330,7 +329,7 @@
<Control position="top-right">
<ControlGroup>
<ControlButton onclick={() => onOpenInMapView()}>
<Icon title={$t('open_in_map_view')} path={mdiMap} size="100%" class="text-black/80" />
<Icon title={$t('open_in_map_view')} icon={mdiMap} size="100%" class="text-black/80" />
</ControlButton>
</ControlGroup>
</Control>
@ -369,7 +368,7 @@
{#snippet children({ feature }: { feature: Feature<Geometry, GeoJsonProperties> })}
{#if useLocationPin}
<Icon
path={mdiMapMarker}
icon={mdiMapMarker}
size="50px"
class="dark:text-immich-dark-primary text-immich-primary -translate-y-[50%]"
/>

View File

@ -2,13 +2,12 @@
import { page } from '$app/state';
import { focusTrap } from '$lib/actions/focus-trap';
import { AppRoute } from '$lib/constants';
import Icon from '$lib/elements/Icon.svelte';
import AvatarEditModal from '$lib/modals/AvatarEditModal.svelte';
import HelpAndFeedbackModal from '$lib/modals/HelpAndFeedbackModal.svelte';
import { user } from '$lib/stores/user.store';
import { userInteraction } from '$lib/stores/user.svelte';
import { getAboutInfo, type ServerAboutResponseDto } from '@immich/sdk';
import { Button, IconButton, modalManager } from '@immich/ui';
import { Button, Icon, IconButton, modalManager } from '@immich/ui';
import { mdiCog, mdiLogout, mdiPencil, mdiWrench } from '@mdi/js';
import { onMount } from 'svelte';
import { t } from 'svelte-i18n';
@ -73,7 +72,7 @@
class="border dark:border-immich-dark-gray dark:bg-gray-500 dark:hover:bg-immich-dark-primary/50 hover:bg-immich-primary/10 dark:text-white"
>
<div class="flex place-content-center place-items-center text-center gap-2 px-2">
<Icon path={mdiCog} size="18" ariaHidden />
<Icon icon={mdiCog} size="18" aria-hidden />
{$t('account_settings')}
</div>
</Button>
@ -89,7 +88,7 @@
class="border dark:border-immich-dark-gray dark:bg-gray-500 dark:hover:bg-immich-dark-primary/50 hover:bg-immich-primary/10 dark:text-white"
>
<div class="flex place-content-center place-items-center text-center gap-2 px-2">
<Icon path={mdiWrench} size="18" ariaHidden />
<Icon icon={mdiWrench} size="18" aria-hidden />
{$t('administration')}
</div>
</Button>

View File

@ -5,11 +5,10 @@
notificationController,
NotificationType as WebNotificationType,
} from '$lib/components/shared-components/notification/notification';
import Icon from '$lib/elements/Icon.svelte';
import { notificationManager } from '$lib/stores/notification-manager.svelte';
import { handleError } from '$lib/utils/handle-error';
import { Button, Scrollable, Stack, Text } from '@immich/ui';
import { Button, Icon, Scrollable, Stack, Text } from '@immich/ui';
import { mdiBellOutline, mdiCheckAll } from '@mdi/js';
import { t } from 'svelte-i18n';
import { flip } from 'svelte/animate';
@ -64,7 +63,7 @@
class="py-12 flex flex-col place-items-center place-content-center text-gray-700 dark:text-gray-300"
gap={1}
>
<Icon path={mdiBellOutline} size={20}></Icon>
<Icon icon={mdiBellOutline} size="20"></Icon>
<Text>{$t('no_notifications')}</Text>
</Stack>
{:else}

View File

@ -6,8 +6,7 @@
type ComponentNotification,
type Notification,
} from '$lib/components/shared-components/notification/notification';
import Icon from '$lib/elements/Icon.svelte';
import { Button, IconButton, type Color } from '@immich/ui';
import { Button, Icon, IconButton, type Color } from '@immich/ui';
import { mdiCloseCircleOutline, mdiInformationOutline, mdiWindowClose } from '@mdi/js';
import { onMount } from 'svelte';
import { t } from 'svelte-i18n';
@ -81,7 +80,7 @@
>
<div class="flex justify-between">
<div class="flex place-items-center gap-2">
<Icon path={icon} color={primaryColor[notification.type]} size="20" />
<Icon {icon} color={primaryColor[notification.type]} size="20" />
<h2 style:color={primaryColor[notification.type]} class="font-medium" data-testid="title">
{#if notification.type == NotificationType.Error}{$t('error')}
{:else if notification.type == NotificationType.Warning}{$t('warning')}

View File

@ -1,5 +1,5 @@
<script lang="ts">
import Icon from '$lib/elements/Icon.svelte';
import { Icon } from '@immich/ui';
import { mdiEyeOffOutline, mdiEyeOutline } from '@mdi/js';
import { t } from 'svelte-i18n';
import type { HTMLInputAttributes } from 'svelte/elements';
@ -37,7 +37,7 @@
onclick={() => (showPassword = !showPassword)}
title={showPassword ? $t('hide_password') : $t('show_password')}
>
<Icon path={showPassword ? mdiEyeOffOutline : mdiEyeOutline} size="1.25em" />
<Icon icon={showPassword ? mdiEyeOffOutline : mdiEyeOutline} size="1.25em" />
</button>
{/if}
</div>

View File

@ -1,8 +1,7 @@
<script lang="ts">
import { ImmichProduct } from '$lib/constants';
import Icon from '$lib/elements/Icon.svelte';
import { getLicenseLink as getProductLink } from '$lib/utils/license-utils';
import { Button } from '@immich/ui';
import { Button, Icon } from '@immich/ui';
import { mdiAccount, mdiCheckCircleOutline } from '@mdi/js';
import { t } from 'svelte-i18n';
</script>
@ -12,7 +11,7 @@
class="border border-gray-300 dark:border-gray-800 w-[min(375px,100%)] p-8 rounded-3xl bg-gray-100 dark:bg-gray-900"
>
<div class="text-immich-primary dark:text-immich-dark-primary">
<Icon path={mdiAccount} size="56" />
<Icon icon={mdiAccount} size="56" />
<p class="font-semibold text-lg mt-1">{$t('purchase_individual_title')}</p>
</div>
@ -24,17 +23,17 @@
<div class="flex flex-col justify-between h-[200px] dark:text-immich-gray">
<div class="mt-6 flex flex-col gap-1">
<div class="grid grid-cols-[36px_auto]">
<Icon path={mdiCheckCircleOutline} size="24" class="text-green-500 self-center" />
<Icon icon={mdiCheckCircleOutline} size="24" class="text-green-500 self-center" />
<p class="self-center">{$t('purchase_individual_description_1')}</p>
</div>
<div class="grid grid-cols-[36px_auto]">
<Icon path={mdiCheckCircleOutline} size="24" class="text-green-500 self-center" />
<Icon icon={mdiCheckCircleOutline} size="24" class="text-green-500 self-center" />
<p class="self-center">{$t('purchase_lifetime_description')}</p>
</div>
<div class="grid grid-cols-[36px_auto]">
<Icon path={mdiCheckCircleOutline} size="24" class="text-green-500 self-center" />
<Icon icon={mdiCheckCircleOutline} size="24" class="text-green-500 self-center" />
<p class="self-center">{$t('purchase_individual_description_2')}</p>
</div>
</div>

View File

@ -1,9 +1,8 @@
<script lang="ts">
import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte';
import Icon from '$lib/elements/Icon.svelte';
import { preferences } from '$lib/stores/user.store';
import { setSupportBadgeVisibility } from '$lib/utils/purchase-utils';
import { Button } from '@immich/ui';
import { Button, Icon } from '@immich/ui';
import { mdiPartyPopper } from '@mdi/js';
import { t } from 'svelte-i18n';
@ -15,7 +14,7 @@
</script>
<div class="m-auto w-3/4 text-center flex flex-col place-content-center place-items-center my-6">
<Icon path={mdiPartyPopper} class="text-immich-primary dark:text-immich-dark-primary" size="96" />
<Icon icon={mdiPartyPopper} class="text-immich-primary dark:text-immich-dark-primary" size="96" />
<p class="text-4xl mt-8 font-bold">{$t('purchase_activated_title')}</p>
<p class="text-lg mt-6">{$t('purchase_activated_subtitle')}</p>

View File

@ -1,8 +1,7 @@
<script lang="ts">
import { ImmichProduct } from '$lib/constants';
import Icon from '$lib/elements/Icon.svelte';
import { getLicenseLink } from '$lib/utils/license-utils';
import { Button } from '@immich/ui';
import { Button, Icon } from '@immich/ui';
import { mdiCheckCircleOutline, mdiServer } from '@mdi/js';
import { t } from 'svelte-i18n';
</script>
@ -12,7 +11,7 @@
class="border border-gray-300 dark:border-gray-800 w-[min(375px,100%)] p-8 rounded-3xl bg-gray-100 dark:bg-gray-900"
>
<div class="text-immich-primary dark:text-immich-dark-primary">
<Icon path={mdiServer} size="56" />
<Icon icon={mdiServer} size="56" />
<p class="font-semibold text-lg mt-1">{$t('purchase_server_title')}</p>
</div>
@ -24,17 +23,17 @@
<div class="flex flex-col justify-between h-[200px] dark:text-immich-gray">
<div class="mt-6 flex flex-col gap-1">
<div class="grid grid-cols-[36px_auto]">
<Icon path={mdiCheckCircleOutline} size="24" class="text-green-500 self-center" />
<Icon icon={mdiCheckCircleOutline} size="24" class="text-green-500 self-center" />
<p class="self-center">{$t('purchase_server_description_1')}</p>
</div>
<div class="grid grid-cols-[36px_auto]">
<Icon path={mdiCheckCircleOutline} size="24" class="text-green-500 self-center" />
<Icon icon={mdiCheckCircleOutline} size="24" class="text-green-500 self-center" />
<p class="self-center">{$t('purchase_lifetime_description')}</p>
</div>
<div class="grid grid-cols-[36px_auto]">
<Icon path={mdiCheckCircleOutline} size="24" class="text-green-500 self-center" />
<Icon icon={mdiCheckCircleOutline} size="24" class="text-green-500 self-center" />
<p class="self-center">{$t('purchase_server_description_2')}</p>
</div>
</div>

View File

@ -1,7 +1,6 @@
<script lang="ts">
import Icon from '$lib/elements/Icon.svelte';
import { searchStore } from '$lib/stores/search.svelte';
import { IconButton } from '@immich/ui';
import { Icon, IconButton } from '@immich/ui';
import { mdiClose, mdiMagnify } from '@mdi/js';
import { t } from 'svelte-i18n';
import { fly } from 'svelte/transition';
@ -129,7 +128,7 @@
aria-selected={selectedIndex === index}
aria-label={savedSearchTerm}
>
<Icon path={mdiMagnify} size="1.5em" ariaHidden={true} />
<Icon icon={mdiMagnify} size="1.5em" aria-hidden />
{savedSearchTerm}
</div>
<div aria-hidden={true} class="absolute end-5 top-0 items-center justify-center py-3">

View File

@ -1,9 +1,8 @@
<script lang="ts">
import Combobox, { type ComboBoxOption } from '$lib/components/shared-components/combobox.svelte';
import Icon from '$lib/elements/Icon.svelte';
import { preferences } from '$lib/stores/user.store';
import { getAllTags, type TagResponseDto } from '@immich/sdk';
import { Checkbox, Label } from '@immich/ui';
import { Checkbox, Icon, Label } from '@immich/ui';
import { mdiClose } from '@mdi/js';
import { onMount } from 'svelte';
import { t } from 'svelte-i18n';
@ -89,7 +88,7 @@
title={$t('remove_tag')}
onclick={() => handleRemove(tagId)}
>
<Icon path={mdiClose} />
<Icon icon={mdiClose} />
</button>
</div>
{/if}

View File

@ -1,5 +1,5 @@
<script lang="ts">
import Icon from '$lib/elements/Icon.svelte';
import { Icon } from '@immich/ui';
import { onDestroy, onMount, type Snippet } from 'svelte';
import { slide } from 'svelte/transition';
import { getAccordionState } from './setting-accordion-state.svelte';
@ -78,7 +78,7 @@
<div>
<div class="flex gap-2 place-items-center">
{#if icon}
<Icon path={icon} class="text-immich-primary dark:text-immich-dark-primary" size="24" ariaHidden />
<Icon {icon} class="text-immich-primary dark:text-immich-dark-primary" size="24" aria-hidden />
{/if}
<h2 class="font-medium text-immich-primary dark:text-immich-dark-primary">
{title}

View File

@ -1,5 +1,5 @@
<script lang="ts">
import Icon from '$lib/elements/Icon.svelte';
import { Icon } from '@immich/ui';
import { mdiChevronDown } from '@mdi/js';
import { t } from 'svelte-i18n';
import { quintOut } from 'svelte/easing';
@ -62,9 +62,9 @@
<div class="grid">
<Icon
path={mdiChevronDown}
icon={mdiChevronDown}
size="1.2em"
ariaHidden={true}
aria-hidden
class="pointer-events-none end-1 relative col-start-1 row-start-1 self-center justify-self-end {disabled
? 'text-immich-bg'
: 'text-immich-fg dark:text-immich-bg'}"

View File

@ -3,7 +3,6 @@
import ImmichLogo from '$lib/components/shared-components/immich-logo.svelte';
import SupporterBadge from '$lib/components/shared-components/side-bar/supporter-badge.svelte';
import { AppRoute } from '$lib/constants';
import Icon from '$lib/elements/Icon.svelte';
import Portal from '$lib/elements/Portal.svelte';
import PurchaseModal from '$lib/modals/PurchaseModal.svelte';
import { purchaseStore } from '$lib/stores/purchase.store';
@ -12,7 +11,7 @@
import { handleError } from '$lib/utils/handle-error';
import { getButtonVisibility } from '$lib/utils/purchase-utils';
import { updateMyPreferences } from '@immich/sdk';
import { Button, IconButton, modalManager } from '@immich/ui';
import { Button, Icon, IconButton, modalManager } from '@immich/ui';
import { mdiClose, mdiInformationOutline } from '@mdi/js';
import { t } from 'svelte-i18n';
import { SvelteDate } from 'svelte/reactivity';
@ -104,7 +103,7 @@
<div>
<Icon
path={mdiInformationOutline}
icon={mdiInformationOutline}
class="hidden sidebar:flex text-immich-primary dark:text-immich-dark-primary font-medium"
size="18"
/>

View File

@ -1,5 +1,4 @@
<script lang="ts">
import Icon from '$lib/elements/Icon.svelte';
import ServerAboutModal from '$lib/modals/ServerAboutModal.svelte';
import { userInteraction } from '$lib/stores/user.svelte';
import { websocketStore } from '$lib/stores/websocket';
@ -10,7 +9,7 @@
type ServerAboutResponseDto,
type ServerVersionHistoryResponseDto,
} from '@immich/sdk';
import { modalManager } from '@immich/ui';
import { Icon, modalManager } from '@immich/ui';
import { mdiAlert } from '@mdi/js';
import { onMount } from 'svelte';
import { t } from 'svelte-i18n';
@ -60,7 +59,7 @@
class="dark:text-immich-gray flex gap-1"
>
{#if isMain}
<Icon path={mdiAlert} size="1.5em" color="#ffcc4d" /> {info?.sourceRef}
<Icon icon={mdiAlert} size="1.5em" color="#ffcc4d" /> {info?.sourceRef}
{:else}
{version}
{/if}

View File

@ -1,6 +1,6 @@
<script lang="ts">
import { page } from '$app/state';
import Icon from '$lib/elements/Icon.svelte';
import { Icon } from '@immich/ui';
import { mdiChevronDown, mdiChevronLeft } from '@mdi/js';
import type { Snippet } from 'svelte';
import { t } from 'svelte-i18n';
@ -42,11 +42,11 @@
onclick={() => (dropdownOpen = !dropdownOpen)}
>
<Icon
path={dropdownOpen ? mdiChevronDown : mdiChevronLeft}
icon={dropdownOpen ? mdiChevronDown : mdiChevronLeft}
size="1em"
class="shrink-0 delay-100 duration-100 "
flipped={flippedLogo}
ariaHidden
aria-hidden
/>
</button>
</span>
@ -62,7 +62,7 @@
: ''}"
>
<div class="flex w-full place-items-center gap-4 ps-5 overflow-hidden truncate">
<Icon path={icon} size="1.5em" class="shrink-0" flipped={flippedLogo} ariaHidden />
<Icon {icon} size="1.5em" class="shrink-0" flipped={flippedLogo} aria-hidden />
<span class="text-sm font-medium">{title}</span>
</div>
<div></div>

View File

@ -1,7 +1,6 @@
<script lang="ts">
import Icon from '$lib/elements/Icon.svelte';
import { TreeNode } from '$lib/utils/tree-utils';
import { IconButton } from '@immich/ui';
import { Icon, IconButton } from '@immich/ui';
import { mdiArrowUpLeft, mdiChevronRight } from '@mdi/js';
import { t } from 'svelte-i18n';
@ -55,7 +54,7 @@
<li
class="flex gap-2 items-center font-mono text-sm text-nowrap text-immich-primary dark:text-immich-dark-primary"
>
<Icon path={mdiChevronRight} class="text-gray-500 dark:text-gray-300" size={16} ariaHidden />
<Icon icon={mdiChevronRight} class="text-gray-500 dark:text-gray-300" size="16" aria-hidden />
<a class="underline hover:font-semibold whitespace-pre-wrap" href={getLink(parent.path)}>
{parent.value}
</a>
@ -65,7 +64,7 @@
<li
class="flex gap-2 items-center font-mono text-sm text-nowrap text-immich-primary dark:text-immich-dark-primary"
>
<Icon path={mdiChevronRight} class="text-gray-500 dark:text-gray-300" size={16} ariaHidden />
<Icon icon={mdiChevronRight} class="text-gray-500 dark:text-gray-300" size="16" aria-hidden />
<p class="cursor-default whitespace-pre-wrap">{node.value}</p>
</li>
</ol>

View File

@ -1,6 +1,6 @@
<script lang="ts">
import Icon from '$lib/elements/Icon.svelte';
import type { TreeNode } from '$lib/utils/tree-utils';
import { Icon } from '@immich/ui';
interface Props {
items: TreeNode[];
@ -23,7 +23,7 @@
title={item.value}
type="button"
>
<Icon path={icon} class="text-immich-primary dark:text-immich-dark-primary" size={64} />
<Icon {icon} class="text-immich-primary dark:text-immich-dark-primary" size="64" />
<p class="text-sm dark:text-gray-200 text-nowrap text-ellipsis overflow-clip w-full whitespace-pre-wrap">
{item.value}
</p>

View File

@ -1,7 +1,7 @@
<script lang="ts">
import TreeItems from '$lib/components/shared-components/tree/tree-items.svelte';
import Icon from '$lib/elements/Icon.svelte';
import { TreeNode } from '$lib/utils/tree-utils';
import { Icon } from '@immich/ui';
import { mdiChevronDown, mdiChevronRight } from '@mdi/js';
interface Props {
@ -31,15 +31,15 @@
>
{#if node.size > 0}
<button type="button" {onclick}>
<Icon path={isOpen ? mdiChevronDown : mdiChevronRight} class="text-gray-400" size={20} />
<Icon icon={isOpen ? mdiChevronDown : mdiChevronRight} class="text-gray-400" size="20" />
</button>
{/if}
<div class={node.size === 0 ? 'ml-[1.5em] ' : ''}>
<Icon
path={isActive ? icons.active : icons.default}
icon={isActive ? icons.active : icons.default}
class={isActive ? 'text-immich-primary dark:text-immich-dark-primary' : 'text-gray-400'}
color={node.color}
size={20}
size="20"
/>
</div>
<span class="text-nowrap overflow-hidden text-ellipsis font-mono ps-1 pt-1 whitespace-pre-wrap">{node.value}</span>

View File

@ -1,12 +1,12 @@
<script lang="ts">
import { AppRoute } from '$lib/constants';
import Icon from '$lib/elements/Icon.svelte';
import type { UploadAsset } from '$lib/models/upload-asset';
import { UploadState } from '$lib/models/upload-asset';
import { locale } from '$lib/stores/preferences.store';
import { uploadAssetsStore } from '$lib/stores/upload';
import { getByteUnitString } from '$lib/utils/byte-units';
import { fileUploadHandler } from '$lib/utils/file-uploader';
import { Icon } from '@immich/ui';
import {
mdiAlertCircle,
mdiCheckCircle,
@ -44,19 +44,19 @@
<div class="flex items-center gap-2">
<div class="flex items-center justify-center">
{#if uploadAsset.state === UploadState.PENDING}
<Icon path={mdiCircleOutline} size="24" class="text-primary" title={$t('pending')} />
<Icon icon={mdiCircleOutline} size="24" class="text-primary" title={$t('pending')} />
{:else if uploadAsset.state === UploadState.STARTED}
<Icon path={mdiLoading} size="24" spin class="text-primary" title={$t('asset_skipped')} />
<Icon icon={mdiLoading} size="24" spin class="text-primary" title={$t('asset_skipped')} />
{:else if uploadAsset.state === UploadState.ERROR}
<Icon path={mdiAlertCircle} size="24" class="text-danger" title={$t('error')} />
<Icon icon={mdiAlertCircle} size="24" class="text-danger" title={$t('error')} />
{:else if uploadAsset.state === UploadState.DUPLICATED}
{#if uploadAsset.isTrashed}
<Icon path={mdiTrashCan} size="24" class="text-gray-500" title={$t('asset_skipped_in_trash')} />
<Icon icon={mdiTrashCan} size="24" class="text-gray-500" title={$t('asset_skipped_in_trash')} />
{:else}
<Icon path={mdiAlertCircle} size="24" class="text-warning" title={$t('asset_skipped')} />
<Icon icon={mdiAlertCircle} size="24" class="text-warning" title={$t('asset_skipped')} />
{/if}
{:else if uploadAsset.state === UploadState.DONE}
<Icon path={mdiCheckCircle} size="24" class="text-success" title={$t('asset_uploaded')} />
<Icon icon={mdiCheckCircle} size="24" class="text-success" title={$t('asset_uploaded')} />
{/if}
</div>
<!-- <span>[{getByteUnitString(uploadAsset.file.size, $locale)}]</span> -->
@ -72,19 +72,19 @@
aria-hidden="true"
tabindex={-1}
>
<Icon path={mdiOpenInNew} size="20" />
<Icon icon={mdiOpenInNew} size="20" />
</a>
<button type="button" onclick={() => handleDismiss(uploadAsset)} class="" aria-hidden="true" tabindex={-1}>
<Icon path={mdiClose} size="20" />
<Icon icon={mdiClose} size="20" />
</button>
</div>
{:else if uploadAsset.state === UploadState.ERROR}
<div class="flex items-center justify-between gap-1">
<button type="button" onclick={() => handleRetry(uploadAsset)} class="" aria-hidden="true" tabindex={-1}>
<Icon path={mdiRestart} size="20" />
<Icon icon={mdiRestart} size="20" />
</button>
<button type="button" onclick={() => handleDismiss(uploadAsset)} class="" aria-hidden="true" tabindex={-1}>
<Icon path={mdiClose} size="20" />
<Icon icon={mdiClose} size="20" />
</button>
</div>
{/if}

View File

@ -1,9 +1,8 @@
<script lang="ts">
import Icon from '$lib/elements/Icon.svelte';
import { locale } from '$lib/stores/preferences.store';
import { uploadAssetsStore } from '$lib/stores/upload';
import { uploadExecutionQueue } from '$lib/utils/file-uploader';
import { IconButton } from '@immich/ui';
import { Icon, IconButton } from '@immich/ui';
import { mdiCancel, mdiCloudUploadOutline, mdiCog, mdiWindowMinimize } from '@mdi/js';
import { t } from 'svelte-i18n';
import { quartInOut } from 'svelte/easing';
@ -163,7 +162,7 @@
class="flex h-16 w-16 place-content-center place-items-center rounded-full bg-subtle p-5 text-sm text-primary shadow-lg"
>
<div class="animate-pulse">
<Icon path={mdiCloudUploadOutline} size="30" />
<Icon icon={mdiCloudUploadOutline} size="30" />
</div>
</button>
</div>

View File

@ -1,10 +1,10 @@
<script lang="ts">
import Icon from '$lib/elements/Icon.svelte';
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
import type { ScrubberMonth } from '$lib/managers/timeline-manager/types';
import { mobileDevice } from '$lib/stores/mobile-device.svelte';
import { getTabbable } from '$lib/utils/focus-util';
import { type ScrubberListener } from '$lib/utils/timeline-util';
import { Icon } from '@immich/ui';
import { mdiPlay } from '@mdi/js';
import { clamp } from 'lodash-es';
import { onMount } from 'svelte';
@ -490,8 +490,8 @@
in:fade={{ duration: 200 }}
out:fade={{ duration: 200 }}
>
<Icon path={mdiPlay} size="20" class="-rotate-90 relative top-[9px] -end-[2px]" />
<Icon path={mdiPlay} size="20" class="rotate-90 relative top-px -end-[2px]" />
<Icon icon={mdiPlay} size="20" class="-rotate-90 relative top-[9px] -end-[2px]" />
<Icon icon={mdiPlay} size="20" class="rotate-90 relative top-px -end-[2px]" />
{#if (timelineManager.scrolling && scrollHoverLabel) || isHover || isDragging}
<p
transition:fade={{ duration: 200 }}

View File

@ -1,6 +1,5 @@
<script lang="ts">
import Thumbnail from '$lib/components/assets/thumbnail/thumbnail.svelte';
import Icon from '$lib/elements/Icon.svelte';
import type { DayGroup } from '$lib/managers/timeline-manager/day-group.svelte';
import type { MonthGroup } from '$lib/managers/timeline-manager/month-group.svelte';
import type { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
@ -14,6 +13,7 @@
import { mdiCheckCircle, mdiCircleOutline } from '@mdi/js';
import { fromTimelinePlainDate, getDateLocaleString } from '$lib/utils/timeline-util';
import { Icon } from '@immich/ui';
import type { Snippet } from 'svelte';
import { flip } from 'svelte/animate';
import { scale } from 'svelte/transition';
@ -178,9 +178,9 @@
onkeydown={() => handleSelectGroup(dayGroup.groupTitle, assetsSnapshot(dayGroup.getAssets()))}
>
{#if assetInteraction.selectedGroup.has(dayGroup.groupTitle)}
<Icon path={mdiCheckCircle} size="24" class="text-primary" />
<Icon icon={mdiCheckCircle} size="24" class="text-primary" />
{:else}
<Icon path={mdiCircleOutline} size="24" color="#757575" />
<Icon icon={mdiCircleOutline} size="24" color="#757575" />
{/if}
</div>
{/if}

View File

@ -1,8 +1,7 @@
<script lang="ts">
import Icon from '$lib/elements/Icon.svelte';
import { locale } from '$lib/stores/preferences.store';
import type { SessionResponseDto } from '@immich/sdk';
import { IconButton } from '@immich/ui';
import { Icon, IconButton } from '@immich/ui';
import {
mdiAndroid,
mdiApple,
@ -34,23 +33,23 @@
<div class="flex w-full flex-row">
<div class="hidden items-center justify-center pe-2 text-immich-primary dark:text-immich-dark-primary sm:flex">
{#if device.deviceOS === 'Android'}
<Icon path={mdiAndroid} size="40" />
<Icon icon={mdiAndroid} size="40" />
{:else if device.deviceOS === 'iOS' || device.deviceOS === 'macOS'}
<Icon path={mdiApple} size="40" />
<Icon icon={mdiApple} size="40" />
{:else if device.deviceOS.includes('Safari')}
<Icon path={mdiAppleSafari} size="40" />
<Icon icon={mdiAppleSafari} size="40" />
{:else if device.deviceOS.includes('Windows')}
<Icon path={mdiMicrosoftWindows} size="40" />
<Icon icon={mdiMicrosoftWindows} size="40" />
{:else if device.deviceOS === 'Linux'}
<Icon path={mdiLinux} size="40" />
<Icon icon={mdiLinux} size="40" />
{:else if device.deviceOS === 'Ubuntu'}
<Icon path={mdiUbuntu} size="40" />
<Icon icon={mdiUbuntu} size="40" />
{:else if device.deviceOS === 'Chrome OS' || device.deviceType === 'Chrome' || device.deviceType === 'Chromium' || device.deviceType === 'Mobile Chrome'}
<Icon path={mdiGoogleChrome} size="40" />
<Icon icon={mdiGoogleChrome} size="40" />
{:else if device.deviceOS === 'Google Cast'}
<Icon path={mdiCast} size="40" />
<Icon icon={mdiCast} size="40" />
{:else}
<Icon path={mdiHelp} size="40" />
<Icon icon={mdiHelp} size="40" />
{/if}
</div>
<div class="flex grow flex-row justify-between gap-1 ps-4 sm:ps-0">

View File

@ -1,7 +1,6 @@
<script lang="ts">
import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte';
import UserAvatar from '$lib/components/shared-components/user-avatar.svelte';
import Icon from '$lib/elements/Icon.svelte';
import PartnerSelectionModal from '$lib/modals/PartnerSelectionModal.svelte';
import {
createPartner,
@ -12,7 +11,7 @@
type PartnerResponseDto,
type UserResponseDto,
} from '@immich/sdk';
import { Button, IconButton, modalManager } from '@immich/ui';
import { Button, Icon, IconButton, modalManager } from '@immich/ui';
import { mdiCheck, mdiClose } from '@mdi/js';
import { onMount } from 'svelte';
import { t } from 'svelte-i18n';
@ -164,11 +163,11 @@
<p class="text-md">{$t('partner_can_access', { values: { partner: partner.user.name } })}</p>
<ul class="text-sm">
<li class="flex gap-2 place-items-center py-1 mt-2">
<Icon path={mdiCheck} />
<Icon icon={mdiCheck} />
{$t('partner_can_access_assets')}
</li>
<li class="flex gap-2 place-items-center py-1">
<Icon path={mdiCheck} />
<Icon icon={mdiCheck} />
{$t('partner_can_access_location')}
</li>
</ul>

View File

@ -4,7 +4,6 @@
import PurchaseContent from '$lib/components/shared-components/purchasing/purchase-content.svelte';
import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte';
import { dateFormats } from '$lib/constants';
import Icon from '$lib/elements/Icon.svelte';
import { locale } from '$lib/stores/preferences.store';
import { purchaseStore } from '$lib/stores/purchase.store';
import { preferences, user } from '$lib/stores/user.store';
@ -19,7 +18,7 @@
isHttpError,
type LicenseResponseDto,
} from '@immich/sdk';
import { Button, modalManager } from '@immich/ui';
import { Button, Icon, modalManager } from '@immich/ui';
import { mdiKey } from '@mdi/js';
import { onMount } from 'svelte';
import { t } from 'svelte-i18n';
@ -123,7 +122,7 @@
<div
class="bg-gray-50 border border-immich-dark-primary/20 dark:bg-immich-dark-primary/15 p-6 pe-12 rounded-xl flex place-content-center gap-4"
>
<Icon path={mdiKey} size="56" class="text-immich-primary dark:text-immich-dark-primary" />
<Icon icon={mdiKey} size="56" class="text-immich-primary dark:text-immich-dark-primary" />
<div>
<p class="text-immich-primary dark:text-immich-dark-primary font-semibold text-lg">
@ -155,7 +154,7 @@
<div
class="bg-gray-50 border border-immich-dark-primary/20 dark:bg-immich-dark-primary/15 p-6 pe-12 rounded-xl flex place-content-center gap-4"
>
<Icon path={mdiKey} size="56" class="text-immich-primary dark:text-immich-dark-primary" />
<Icon icon={mdiKey} size="56" class="text-immich-primary dark:text-immich-dark-primary" />
<div>
<p class="text-immich-primary dark:text-immich-dark-primary font-semibold text-lg">

View File

@ -1,10 +1,10 @@
<script lang="ts">
import Icon from '$lib/elements/Icon.svelte';
import { getAssetThumbnailUrl } from '$lib/utils';
import { getAssetResolution, getFileSize } from '$lib/utils/asset-utils';
import { getAltText } from '$lib/utils/thumbnail-util';
import { toTimelineAsset } from '$lib/utils/timeline-util';
import { type AssetResponseDto, getAllAlbums } from '@immich/sdk';
import { Icon } from '@immich/ui';
import { mdiHeart, mdiImageMultipleOutline, mdiMagnifyPlus } from '@mdi/js';
import { t } from 'svelte-i18n';
@ -46,7 +46,7 @@
<!-- FAVORITE ICON -->
{#if asset.isFavorite}
<div class="absolute bottom-2 start-2">
<Icon path={mdiHeart} size="24" class="text-white" />
<Icon icon={mdiHeart} size="24" class="text-white" />
</div>
{/if}
@ -70,7 +70,7 @@
<div class="bg-immich-primary/90 px-2 py-1 my-0.5 rounded-xl text-xs text-white">
<div class="flex items-center justify-center">
<div class="me-1">{asset.stack.assetCount}</div>
<Icon path={mdiImageMultipleOutline} size="18" />
<Icon icon={mdiImageMultipleOutline} size="18" />
</div>
</div>
{/if}
@ -83,7 +83,7 @@
class="absolute rounded-full top-1 start-1 text-gray-200 p-2 hover:text-white bg-black/35 hover:bg-black/50"
title={$t('view')}
>
<Icon ariaLabel={$t('view')} path={mdiMagnifyPlus} flipped size="18" />
<Icon aria-label={$t('view')} icon={mdiMagnifyPlus} flipped size="18" />
</button>
</div>

View File

@ -1,6 +1,6 @@
<script lang="ts">
import { AppRoute } from '$lib/constants';
import Icon from '$lib/elements/Icon.svelte';
import { Icon } from '@immich/ui';
import { mdiContentDuplicate, mdiCrosshairsGps, mdiImageSizeSelectLarge } from '@mdi/js';
import { t } from 'svelte-i18n';
@ -16,7 +16,7 @@
{#each links as link (link.href)}
<a href={link.href} class="w-full hover:bg-gray-100 dark:hover:bg-immich-dark-gray flex items-center gap-4 p-4">
<span><Icon path={link.icon} class="text-immich-primary dark:text-immich-dark-primary" size="24" /> </span>
<span><Icon icon={link.icon} class="text-immich-primary dark:text-immich-dark-primary" size="24" /> </span>
{link.label}
</a>
{/each}

View File

@ -12,11 +12,10 @@
<script lang="ts" generics="T">
import { clickOutside } from '$lib/actions/click-outside';
import { Button, Text } from '@immich/ui';
import { Button, Icon, Text } from '@immich/ui';
import { mdiCheck } from '@mdi/js';
import { isEqual } from 'lodash-es';
import { fly } from 'svelte/transition';
import Icon from './Icon.svelte';
interface Props {
class?: string;
@ -99,7 +98,7 @@
<!-- BUTTON TITLE -->
<Button onclick={() => (showMenu = true)} fullWidth {title} variant="ghost" color="secondary" size="small">
{#if renderedSelectedOption?.icon}
<Icon path={renderedSelectedOption.icon} />
<Icon icon={renderedSelectedOption.icon} />
{/if}
<Text class={hideTextOnSmallScreen ? 'hidden sm:block' : ''}>{renderedSelectedOption.title}</Text>
</Button>
@ -123,7 +122,7 @@
>
{#if isEqual(selectedOption, option)}
<div class="text-immich-primary dark:text-immich-dark-primary">
<Icon path={mdiCheck} />
<Icon icon={mdiCheck} />
</div>
<p class="justify-self-start text-immich-primary dark:text-immich-dark-primary">
{renderedOption.title}

View File

@ -1,60 +0,0 @@
<script lang="ts">
import type { AriaRole } from 'svelte/elements';
interface Props {
size?: string | number;
color?: string;
path: string;
title?: string | null;
desc?: string;
flipped?: boolean;
class?: string;
viewBox?: string;
role?: AriaRole;
ariaHidden?: boolean | undefined;
ariaLabel?: string | undefined;
ariaLabelledby?: string | undefined;
strokeWidth?: number;
strokeColor?: string;
spin?: boolean;
}
let {
size = '1em',
color = 'currentColor',
path,
title = null,
desc = '',
flipped = false,
class: className = '',
viewBox = '0 0 24 24',
role = 'img',
ariaHidden = undefined,
ariaLabel = undefined,
ariaLabelledby = undefined,
strokeWidth = 0,
strokeColor = 'currentColor',
spin = false,
}: Props = $props();
</script>
<svg
width={size}
height={size}
{viewBox}
class="{className} {flipped ? '-scale-x-100' : ''} {spin ? 'animate-spin' : ''}"
{role}
stroke={strokeColor}
stroke-width={strokeWidth}
aria-label={ariaLabel}
aria-hidden={ariaHidden}
aria-labelledby={ariaLabelledby}
>
{#if title}
<title>{title}</title>
{/if}
{#if desc}
<desc>{desc}</desc>
{/if}
<path d={path} fill={color} />
</svg>

View File

@ -1,8 +1,8 @@
<script lang="ts">
import { focusOutside } from '$lib/actions/focus-outside';
import { shortcuts } from '$lib/actions/shortcut';
import Icon from '$lib/elements/Icon.svelte';
import { generateId } from '$lib/utils/generate-id';
import { Icon } from '@immich/ui';
import { t } from 'svelte-i18n';
interface Props {
@ -83,12 +83,12 @@
>
<span class="sr-only">{$t('rating_count', { values: { count: value } })}</span>
<Icon
path={starIcon}
icon={starIcon}
size="1.5em"
strokeWidth={1}
color={filled ? 'currentcolor' : 'transparent'}
strokeColor={filled ? 'currentcolor' : '#c1cce8'}
ariaHidden
aria-hidden
/>
</label>
<input

View File

@ -4,7 +4,6 @@
import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte';
import UserAvatar from '$lib/components/shared-components/user-avatar.svelte';
import type { RenderedOption } from '$lib/elements/Dropdown.svelte';
import Icon from '$lib/elements/Icon.svelte';
import { handleError } from '$lib/utils/handle-error';
import {
AlbumUserRole,
@ -15,7 +14,7 @@
type AlbumResponseDto,
type UserResponseDto,
} from '@immich/sdk';
import { Modal, ModalBody, modalManager } from '@immich/ui';
import { Icon, Modal, ModalBody, modalManager } from '@immich/ui';
import { mdiArrowDownThin, mdiArrowUpThin, mdiDotsVertical, mdiPlus } from '@mdi/js';
import { findKey } from 'lodash-es';
import { t } from 'svelte-i18n';
@ -142,7 +141,7 @@
<div class="p-2">
<button type="button" class="flex items-center gap-2" onclick={() => onClose({ action: 'shareUser' })}>
<div class="rounded-full w-10 h-10 border border-gray-500 flex items-center justify-center">
<div><Icon path={mdiPlus} size="25" /></div>
<div><Icon icon={mdiPlus} size="25" /></div>
</div>
<div>{$t('invite_people')}</div>
</button>

View File

@ -2,7 +2,6 @@
import AlbumSharedLink from '$lib/components/album-page/album-shared-link.svelte';
import { AppRoute } from '$lib/constants';
import Dropdown from '$lib/elements/Dropdown.svelte';
import Icon from '$lib/elements/Icon.svelte';
import QrCodeModal from '$lib/modals/QrCodeModal.svelte';
import { makeSharedLinkUrl } from '$lib/utils';
import {
@ -14,7 +13,7 @@
type SharedLinkResponseDto,
type UserResponseDto,
} from '@immich/sdk';
import { Button, Link, Modal, ModalBody, Stack, Text } from '@immich/ui';
import { Button, Icon, Link, Modal, ModalBody, Stack, Text } from '@immich/ui';
import { mdiCheck, mdiEye, mdiLink, mdiPencil } from '@mdi/js';
import { onMount } from 'svelte';
import { t } from 'svelte-i18n';
@ -87,7 +86,7 @@
<div
class="flex h-10 w-10 items-center justify-center rounded-full border bg-green-600 text-3xl text-white"
>
<Icon path={mdiCheck} size={24} />
<Icon icon={mdiCheck} size="24" />
</div>
<!-- <UserAvatar {user} size="md" /> -->

View File

@ -1,8 +1,7 @@
<script lang="ts">
import Icon from '$lib/elements/Icon.svelte';
import { tagAssets } from '$lib/utils/asset-utils';
import { getAllTags, upsertTags, type TagResponseDto } from '@immich/sdk';
import { Button, HStack, Modal, ModalBody, ModalFooter } from '@immich/ui';
import { Button, HStack, Icon, Modal, ModalBody, ModalFooter } from '@immich/ui';
import { mdiClose, mdiTag } from '@mdi/js';
import { onMount } from 'svelte';
import { t } from 'svelte-i18n';
@ -90,7 +89,7 @@
title={$t('remove_tag')}
onclick={() => handleRemove(tagId)}
>
<Icon path={mdiClose} />
<Icon icon={mdiClose} />
</button>
</div>
{/if}

View File

@ -1,8 +1,7 @@
<script lang="ts">
import { discordPath, discordViewBox } from '$lib/assets/svg-paths';
import Icon from '$lib/elements/Icon.svelte';
import { type ServerAboutResponseDto } from '@immich/sdk';
import { Modal, ModalBody } from '@immich/ui';
import { Icon, Modal, ModalBody } from '@immich/ui';
import { mdiBugOutline, mdiFaceAgent, mdiGit, mdiGithub, mdiInformationOutline } from '@mdi/js';
import { t } from 'svelte-i18n';
@ -20,7 +19,7 @@
<div class="flex flex-col sm:grid sm:grid-cols-2 gap-2 mt-5">
<div>
<a href="https://{info.version}.archive.immich.app/docs/overview/introduction" target="_blank" rel="noreferrer">
<Icon path={mdiInformationOutline} size="1.5em" class="inline-block" />
<Icon icon={mdiInformationOutline} size="1.5em" class="inline-block" />
<p
class="font-medium text-immich-primary dark:text-immich-dark-primary text-sm underline inline-block"
id="documentation-label"
@ -32,7 +31,7 @@
<div>
<a href="https://github.com/immich-app/immich/" target="_blank" rel="noreferrer">
<Icon path={mdiGithub} size="1.5em" class="inline-block" />
<Icon icon={mdiGithub} size="1.5em" class="inline-block" />
<p
class="font-medium text-immich-primary dark:text-immich-dark-primary text-sm underline inline-block"
id="github-label"
@ -44,7 +43,7 @@
<div>
<a href="https://discord.immich.app" target="_blank" rel="noreferrer">
<Icon path={discordPath} viewBox={discordViewBox} class="inline-block" size="1.5em" />
<Icon icon={discordPath} viewBox={discordViewBox} class="inline-block" size="1.5em" />
<p
class="font-medium text-immich-primary dark:text-immich-dark-primary text-sm underline inline-block"
id="github-label"
@ -56,7 +55,7 @@
<div>
<a href="https://github.com/immich-app/immich/issues/new/choose" target="_blank" rel="noreferrer">
<Icon path={mdiBugOutline} size="1.5em" class="inline-block" />
<Icon icon={mdiBugOutline} size="1.5em" class="inline-block" />
<p
class="font-medium text-immich-primary dark:text-immich-dark-primary text-sm underline inline-block"
id="github-label"
@ -75,7 +74,7 @@
{#if info.thirdPartyDocumentationUrl}
<div>
<a href={info.thirdPartyDocumentationUrl} target="_blank" rel="noreferrer">
<Icon path={mdiInformationOutline} size="1.5em" class="inline-block" />
<Icon icon={mdiInformationOutline} size="1.5em" class="inline-block" />
<p
class="font-medium text-immich-primary dark:text-immich-dark-primary text-sm underline inline-block"
id="documentation-label"
@ -89,7 +88,7 @@
{#if info.thirdPartySourceUrl}
<div>
<a href={info.thirdPartySourceUrl} target="_blank" rel="noreferrer">
<Icon path={mdiGit} size="1.5em" class="inline-block" />
<Icon icon={mdiGit} size="1.5em" class="inline-block" />
<p
class="font-medium text-immich-primary dark:text-immich-dark-primary text-sm underline inline-block"
id="github-label"
@ -103,7 +102,7 @@
{#if info.thirdPartySupportUrl}
<div>
<a href={info.thirdPartySupportUrl} target="_blank" rel="noreferrer">
<Icon path={mdiFaceAgent} class="inline-block" size="1.5em" />
<Icon icon={mdiFaceAgent} class="inline-block" size="1.5em" />
<p
class="font-medium text-immich-primary dark:text-immich-dark-primary text-sm underline inline-block"
id="github-label"
@ -117,7 +116,7 @@
{#if info.thirdPartyBugFeatureUrl}
<div>
<a href={info.thirdPartyBugFeatureUrl} target="_blank" rel="noreferrer">
<Icon path={mdiBugOutline} size="1.5em" class="inline-block" />
<Icon icon={mdiBugOutline} size="1.5em" class="inline-block" />
<p
class="font-medium text-immich-primary dark:text-immich-dark-primary text-sm underline inline-block"
id="github-label"

View File

@ -3,11 +3,10 @@
notificationController,
NotificationType,
} from '$lib/components/shared-components/notification/notification';
import Icon from '$lib/elements/Icon.svelte';
import { getPeopleThumbnailUrl } from '$lib/utils';
import { handleError } from '$lib/utils/handle-error';
import { mergePerson, type PersonResponseDto } from '@immich/sdk';
import { Button, HStack, IconButton, Modal, ModalBody, ModalFooter } from '@immich/ui';
import { Button, HStack, Icon, IconButton, Modal, ModalBody, ModalFooter } from '@immich/ui';
import { mdiArrowLeft, mdiCallMerge, mdiSwapHorizontal } from '@mdi/js';
import { onMount, tick } from 'svelte';
import { t } from 'svelte-i18n';
@ -78,7 +77,7 @@
<div></div>
<div class="flex flex-col h-full items-center justify-center">
<div class="flex h-full items-center justify-center">
<Icon path={mdiCallMerge} size={48} class="rotate-90 dark:text-white" />
<Icon icon={mdiCallMerge} size="48" class="rotate-90 dark:text-white" />
</div>
</div>
<div>
@ -115,7 +114,7 @@
{:else}
<div class="grid w-full grid-cols-1 gap-2">
<div class="px-2">
<button type="button" onclick={() => (choosePersonToMerge = false)}> <Icon path={mdiArrowLeft} /></button>
<button type="button" onclick={() => (choosePersonToMerge = false)}> <Icon icon={mdiArrowLeft} /></button>
</div>
<div class="flex items-center justify-center">
<div class="flex flex-wrap justify-center md:grid md:grid-cols-{potentialMergePeople.length}">

View File

@ -1,8 +1,7 @@
<script lang="ts">
import Icon from '$lib/elements/Icon.svelte';
import { locale } from '$lib/stores/preferences.store';
import { type ServerAboutResponseDto, type ServerVersionHistoryResponseDto } from '@immich/sdk';
import { Modal, ModalBody } from '@immich/ui';
import { Icon, Modal, ModalBody } from '@immich/ui';
import { mdiAlert } from '@mdi/js';
import { DateTime } from 'luxon';
import { t } from 'svelte-i18n';
@ -159,7 +158,7 @@
{#if info.sourceRef === 'main' && info.repository === 'immich-app/immich'}
<div class="col-span-full p-4 flex gap-1">
<Icon path={mdiAlert} size="2em" color="#ffcc4d" />
<Icon icon={mdiAlert} size="2em" color="#ffcc4d" />
<p class="immich-form-label text-sm" id="main-warning">
{$t('main_branch_warning')}
</p>

View File

@ -1,6 +1,5 @@
<script lang="ts">
import Icon from '$lib/elements/Icon.svelte';
import { Modal, ModalBody } from '@immich/ui';
import { Icon, Modal, ModalBody } from '@immich/ui';
import { mdiInformationOutline } from '@mdi/js';
import { t } from 'svelte-i18n';
@ -91,7 +90,7 @@
<div class="flex items-center gap-2">
<p class="mb-1 mt-1 flex">{shortcut.action}</p>
{#if shortcut.info}
<Icon path={mdiInformationOutline} title={shortcut.info} />
<Icon icon={mdiInformationOutline} title={shortcut.info} />
{/if}
</div>
</div>

View File

@ -32,7 +32,6 @@
import AssetSelectControlBar from '$lib/components/timeline/AssetSelectControlBar.svelte';
import Timeline from '$lib/components/timeline/Timeline.svelte';
import { AlbumPageViewMode, AppRoute } from '$lib/constants';
import Icon from '$lib/elements/Icon.svelte';
import { activityManager } from '$lib/managers/activity-manager.svelte';
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
@ -69,7 +68,7 @@
updateAlbumInfo,
type AlbumUserAddDto,
} from '@immich/sdk';
import { Button, IconButton, modalManager } from '@immich/ui';
import { Button, Icon, IconButton, modalManager } from '@immich/ui';
import {
mdiArrowLeft,
mdiCogOutline,
@ -535,8 +534,8 @@
onclick={() => (viewMode = AlbumPageViewMode.SELECT_ASSETS)}
class="mt-5 bg-subtle flex w-full place-items-center gap-6 rounded-2xl border px-8 py-8 text-immich-fg transition-all hover:bg-gray-100 dark:hover:bg-gray-500/20 hover:text-immich-primary dark:border-none dark:text-immich-dark-fg dark:hover:text-immich-dark-primary"
>
<span class="text-text-immich-primary dark:text-immich-dark-primary"
><Icon path={mdiPlus} size="24" />
<span class="text-text-immich-primary dark:text-immich-dark-primary">
<Icon icon={mdiPlus} size="24" />
</span>
<span class="text-lg">{$t('select_photos')}</span>
</button>

View File

@ -4,11 +4,11 @@
import EmptyPlaceholder from '$lib/components/shared-components/empty-placeholder.svelte';
import SingleGridRow from '$lib/components/shared-components/single-grid-row.svelte';
import { AppRoute } from '$lib/constants';
import Icon from '$lib/elements/Icon.svelte';
import { websocketEvents } from '$lib/stores/websocket';
import { getAssetThumbnailUrl, getPeopleThumbnailUrl } from '$lib/utils';
import { getMetadataSearchQuery } from '$lib/utils/metadata-search';
import { AssetMediaSize, type SearchExploreResponseDto } from '@immich/sdk';
import { Icon } from '@immich/ui';
import { mdiHeart } from '@mdi/js';
import { onMount } from 'svelte';
import { t } from 'svelte-i18n';
@ -65,7 +65,7 @@
/>
{#if person.isFavorite}
<div class="absolute top-2 start-2">
<Icon path={mdiHeart} size="24" class="text-white" />
<Icon icon={mdiHeart} size="24" class="text-white" />
</div>
{/if}
<p class="mt-2 text-ellipsis text-sm font-medium dark:text-white">{person.name}</p>
@ -102,7 +102,7 @@
/>
</div>
<span
class="w-100 absolute bottom-2 w-full text-ellipsis px-1 text-center text-sm font-medium capitalize text-white backdrop-blur-[1px] hover:cursor-pointer"
class="absolute bottom-2 w-full text-ellipsis px-1 text-center text-sm font-medium capitalize text-white backdrop-blur-[1px] hover:cursor-pointer"
>
{item.value}
</span>

View File

@ -14,7 +14,6 @@
NotificationType,
} from '$lib/components/shared-components/notification/notification';
import { ActionQueryParameterValue, AppRoute, QueryParameter, SessionStorageKey } from '$lib/constants';
import Icon from '$lib/elements/Icon.svelte';
import PersonEditBirthDateModal from '$lib/modals/PersonEditBirthDateModal.svelte';
import PersonMergeSuggestionModal from '$lib/modals/PersonMergeSuggestionModal.svelte';
import { locale } from '$lib/stores/preferences.store';
@ -23,7 +22,7 @@
import { handleError } from '$lib/utils/handle-error';
import { clearQueryParam } from '$lib/utils/navigation';
import { getAllPeople, getPerson, searchPerson, updatePerson, type PersonResponseDto } from '@immich/sdk';
import { Button, modalManager } from '@immich/ui';
import { Button, Icon, modalManager } from '@immich/ui';
import { mdiAccountOff, mdiEyeOutline } from '@mdi/js';
import { onMount } from 'svelte';
import { t } from 'svelte-i18n';
@ -389,7 +388,7 @@
{:else}
<div class="flex min-h-[calc(66vh-11rem)] w-full place-content-center items-center dark:text-white">
<div class="flex flex-col content-center items-center text-center">
<Icon path={mdiAccountOff} size="3.5em" />
<Icon icon={mdiAccountOff} size="3.5em" />
<p class="mt-5 text-3xl font-medium max-w-lg line-clamp-2 overflow-hidden">
{$t(searchName ? 'search_no_people_named' : 'search_no_people', { values: { name: searchName } })}
</p>

View File

@ -22,7 +22,6 @@
import TagAction from '$lib/components/timeline/actions/TagAction.svelte';
import AssetSelectControlBar from '$lib/components/timeline/AssetSelectControlBar.svelte';
import { AppRoute, QueryParameter } from '$lib/constants';
import Icon from '$lib/elements/Icon.svelte';
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
import type { TimelineAsset, Viewport } from '$lib/managers/timeline-manager/types';
import { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
@ -45,7 +44,7 @@
searchSmart,
type SmartSearchDto,
} from '@immich/sdk';
import { IconButton } from '@immich/ui';
import { Icon, IconButton } from '@immich/ui';
import { mdiArrowLeft, mdiDotsVertical, mdiImageOffOutline, mdiPlus, mdiSelectAll } from '@mdi/js';
import { tick } from 'svelte';
import { t } from 'svelte-i18n';
@ -390,7 +389,7 @@
{:else if !isLoading}
<div class="flex min-h-[calc(66vh-11rem)] w-full place-content-center items-center dark:text-white">
<div class="flex flex-col content-center items-center text-center">
<Icon path={mdiImageOffOutline} size="3.5em" />
<Icon icon={mdiImageOffOutline} size="3.5em" />
<p class="mt-5 text-3xl font-medium">{$t('no_results')}</p>
<p class="text-base font-normal">{$t('no_results_description')}</p>
</div>

View File

@ -6,7 +6,6 @@
notificationController,
} from '$lib/components/shared-components/notification/notification';
import { AppRoute } from '$lib/constants';
import Icon from '$lib/elements/Icon.svelte';
import UserCreateModal from '$lib/modals/UserCreateModal.svelte';
import UserDeleteConfirmModal from '$lib/modals/UserDeleteConfirmModal.svelte';
import UserRestoreConfirmModal from '$lib/modals/UserRestoreConfirmModal.svelte';
@ -16,7 +15,7 @@
import { websocketEvents } from '$lib/stores/websocket';
import { getByteUnitString } from '$lib/utils/byte-units';
import { UserStatus, searchUsersAdmin, type UserAdminResponseDto } from '@immich/sdk';
import { Button, HStack, IconButton, Text, modalManager } from '@immich/ui';
import { Button, HStack, Icon, IconButton, Text, modalManager } from '@immich/ui';
import { mdiDeleteRestore, mdiEyeOutline, mdiInfinity, mdiPlusBoxOutline, mdiTrashCanOutline } from '@mdi/js';
import { DateTime } from 'luxon';
import { onMount } from 'svelte';
@ -116,7 +115,7 @@
{#if immichUser.quotaSizeInBytes !== null && immichUser.quotaSizeInBytes >= 0}
{getByteUnitString(immichUser.quotaSizeInBytes, $locale)}
{:else}
<Icon path={mdiInfinity} size="16" />
<Icon icon={mdiInfinity} size="16" />
{/if}
</div>
</td>