chore: tailwind linting (#28165)

chore: tailwind cannonical classes
This commit is contained in:
Daniel Dietzler
2026-05-01 06:18:03 +02:00
committed by GitHub
parent b60e9c6771
commit 5e9bda7fab
248 changed files with 963 additions and 880 deletions
@@ -268,9 +268,9 @@
</script>
<svelte:window onresize={onPositionChange} />
<Label class="block mb-1 {hideLabel ? 'sr-only' : ''} text-xs text-neutral-500 font-light" for={inputId}>{label}</Label>
<Label class="mb-1 block {hideLabel ? 'sr-only' : ''} text-xs font-light text-neutral-500" for={inputId}>{label}</Label>
<div
class="relative w-full dark:text-gray-300 text-gray-700 text-base"
class="relative w-full text-base text-gray-700 dark:text-gray-300"
use:focusOutside={{ onFocusOut: deactivate }}
use:shortcuts={[
{
@@ -284,7 +284,7 @@
>
<div>
{#if isActive}
<div class="absolute inset-y-0 start-0 flex items-center ps-3">
<div class="absolute inset-y-0 inset-s-0 flex items-center ps-3">
<div class="dark:text-immich-dark-fg/75">
<Icon icon={mdiMagnify} aria-hidden />
</div>
@@ -300,11 +300,11 @@
aria-expanded={isOpen}
autocomplete="off"
bind:this={input}
class:!ps-8={isActive}
class:!rounded-b-none={isOpen && dropdownDirection === 'bottom'}
class:!rounded-t-none={isOpen && dropdownDirection === 'top'}
class:ps-8!={isActive}
class:rounded-b-none!={isOpen && dropdownDirection === 'bottom'}
class:rounded-t-none!={isOpen && dropdownDirection === 'top'}
class:cursor-pointer={!isActive}
class="immich-form-input text-sm w-full pe-12! transition-all"
class="immich-form-input w-full pe-12! text-sm transition-all"
id={inputId}
onfocus={activate}
oninput={onInput}
@@ -355,7 +355,7 @@
/>
<div
class="absolute end-0 top-0 h-full flex px-4 justify-center items-center content-between"
class="absolute inset-e-0 top-0 flex h-full content-between items-center justify-center px-4"
class:pe-2={selectedOption}
class:pointer-events-none={!selectedOption}
>
@@ -379,10 +379,10 @@
role="listbox"
id={listboxId}
in:fly={{ duration: 250 }}
class="fixed z-1 text-start text-sm w-full overflow-y-auto bg-white dark:bg-gray-800 border-gray-300 dark:border-gray-900"
class="fixed z-1 w-full overflow-y-auto border-gray-300 bg-white text-start text-sm dark:border-gray-900 dark:bg-gray-800"
class:rounded-b-xl={dropdownDirection === 'bottom'}
class:rounded-t-xl={dropdownDirection === 'top'}
class:shadow={dropdownDirection === 'bottom'}
class:shadow-sm={dropdownDirection === 'bottom'}
class:border={isOpen}
style:top={position?.top}
style:bottom={position?.bottom}
@@ -398,7 +398,7 @@
role="option"
aria-selected={selectedIndex === 0}
aria-disabled={true}
class="text-start w-full px-4 py-2 hover:bg-gray-200 dark:hover:bg-gray-700 cursor-default aria-selected:bg-gray-200 aria-selected:dark:bg-gray-700"
class="w-full cursor-default px-4 py-2 text-start hover:bg-gray-200 aria-selected:bg-gray-200 dark:hover:bg-gray-700 aria-selected:dark:bg-gray-700"
id={`${listboxId}-${0}`}
onclick={closeDropdown}
>
@@ -410,7 +410,7 @@
<li
aria-selected={index === selectedIndex}
bind:this={optionRefs[index]}
class="text-start w-full px-4 py-2 hover:bg-gray-200 dark:hover:bg-gray-700 transition-all cursor-pointer aria-selected:bg-gray-200 aria-selected:dark:bg-gray-700 wrap-break-words"
class="wrap-break-words w-full cursor-pointer px-4 py-2 text-start transition-all hover:bg-gray-200 aria-selected:bg-gray-200 dark:hover:bg-gray-700 aria-selected:dark:bg-gray-700"
id={`${listboxId}-${index}`}
onclick={() => handleSelect(option)}
role="option"
@@ -66,12 +66,12 @@
!multiRow && 'grid-cols-[10%_80%_10%] sm:grid-cols-[25%_50%_25%]',
'justify-between lg:grid-cols-[25%_50%_25%]',
appBarBorder,
'mx-2 my-2 place-items-center rounded-lg p-2 max-md:p-0 transition-all',
'm-2 place-items-center rounded-lg p-2 transition-all max-md:p-0',
tailwindClasses,
forceDark ? 'bg-immich-dark-gray! text-white' : 'bg-subtle dark:bg-immich-dark-gray',
]}
>
<div class="flex place-items-center sm:gap-6 justify-self-start dark:text-immich-dark-fg {forceDark ? 'dark' : ''}">
<div class="flex place-items-center justify-self-start sm:gap-6 dark:text-immich-dark-fg {forceDark ? 'dark' : ''}">
{#if showBackButton}
<IconButton
aria-label={$t('close')}
@@ -90,7 +90,7 @@
{@render children?.()}
</div>
<div class="max-[350px]:me-0 max-[350px]:gap-0 me-4 flex place-items-center gap-1 justify-self-end">
<div class="me-4 flex place-items-center gap-1 justify-self-end max-[350px]:me-0 max-[350px]:gap-0">
{@render trailing?.()}
</div>
</nav>
@@ -28,7 +28,7 @@
<img {src} alt="" width="500" draggable="false" />
{#if title}
<h2 class="text-xl font-medium my-4">{title}</h2>
<h2 class="my-4 text-xl font-medium">{title}</h2>
{/if}
<p class="text-immich-text-gray-500 dark:text-immich-dark-fg font-light text-center">{text}</p>
<p class="text-immich-text-gray-500 text-center font-light dark:text-immich-dark-fg">{text}</p>
</svelte:element>
@@ -15,6 +15,6 @@
<div style="width: {width}px; height: {width}px">
{#await promise then url}
<img src={url} {alt} class="h-full w-full" />
<img src={url} {alt} class="size-full" />
{/await}
</div>
@@ -11,9 +11,9 @@
let { label, onRemove }: Props = $props();
</script>
<div class="flex group transition-all">
<div class="group flex transition-all">
<span
class="inline-block h-min whitespace-nowrap ps-3 pe-1 group-hover:ps-3 py-1 text-center align-baseline leading-none text-gray-100 dark:text-immich-dark-gray bg-primary rounded-s-full hover:bg-immich-primary/80 dark:hover:bg-immich-dark-primary/80 transition-all"
class="inline-block h-min rounded-s-full bg-primary py-1 ps-3 pe-1 text-center align-baseline leading-none whitespace-nowrap text-gray-100 transition-all group-hover:ps-3 hover:bg-immich-primary/80 dark:text-immich-dark-gray dark:hover:bg-immich-dark-primary/80"
>
<p class="text-sm">
{label}
@@ -22,7 +22,7 @@
<button
type="button"
class="text-gray-100 dark:text-immich-dark-gray bg-immich-primary/95 dark:bg-immich-dark-primary/95 rounded-e-full place-items-center place-content-center pe-2 ps-1 py-1 hover:bg-immich-primary/80 dark:hover:bg-immich-dark-primary/80 transition-all"
class="place-content-center place-items-center rounded-e-full bg-immich-primary/95 py-1 ps-1 pe-2 text-gray-100 transition-all hover:bg-immich-primary/80 dark:bg-immich-dark-primary/95 dark:text-immich-dark-gray dark:hover:bg-immich-dark-primary/80"
title={$t('remove_tag')}
onclick={onRemove}
>
@@ -78,7 +78,7 @@
</script>
<figure
class="{sizeClass} {colorClass} {interactiveClass} overflow-hidden shadow-md rounded-full"
class="{sizeClass} {colorClass} {interactiveClass} overflow-hidden rounded-full shadow-md"
title={noTitle ? undefined : title}
>
{#if user.profileImagePath}
@@ -86,14 +86,14 @@
bind:this={img}
src={getProfileImageUrl(user)}
alt={$t('profile_image_of_user', { values: { user: title } })}
class="h-full w-full object-cover"
class="size-full object-cover"
class:hidden={showFallback}
draggable="false"
/>
{/if}
{#if showFallback}
<span
class="uppercase flex h-full w-full select-none items-center justify-center font-medium"
class="flex size-full items-center justify-center font-medium uppercase select-none"
class:text-xs={size === 'sm'}
class:text-lg={size === 'lg'}
class:text-xl={size === 'xl'}
@@ -26,11 +26,11 @@
type="button"
onclick={() => onNewAlbum(searchQuery)}
use:scrollIntoViewIfSelected
class="flex w-full items-center gap-4 px-6 py-2 transition-colors hover:bg-gray-200 dark:hover:bg-gray-700 rounded-xl"
class="flex w-full items-center gap-4 rounded-xl px-6 py-2 transition-colors hover:bg-gray-200 dark:hover:bg-gray-700"
class:bg-gray-200={selected}
class:dark:bg-gray-700={selected}
>
<div class="flex h-12 w-12 items-center justify-center">
<div class="flex size-12 items-center justify-center">
<Icon icon={mdiPlus} size="30" />
</div>
<p class="">
@@ -64,7 +64,7 @@
<div
bind:this={menuScrollView}
class={[
'duration-250 ease-in-out fixed min-w-50 w-max max-w-75 rounded-lg shadow-lg bg-slate-100 z-1 immich-scrollbar',
'fixed z-1 w-max max-w-75 min-w-50 rounded-lg bg-slate-100 shadow-lg duration-250 ease-in-out immich-scrollbar',
position.needScrollBar ? 'overflow-auto' : 'overflow-hidden',
]}
style:left="{position.left}px"
@@ -53,7 +53,7 @@
onclick={handleClick}
onmouseover={() => ($selectedIdStore = id)}
onmouseleave={() => ($selectedIdStore = undefined)}
class="w-full p-4 text-start text-sm font-medium {textColor} focus:outline-none focus:ring-2 focus:ring-inset cursor-pointer border-gray-200 flex gap-2 items-center {isActive
class="w-full p-4 text-start text-sm font-medium {textColor} flex cursor-pointer items-center gap-2 border-gray-200 focus:ring-2 focus:outline-none focus:ring-inset {isActive
? activeColor
: 'bg-slate-100'}"
role="menuitem"
@@ -65,7 +65,7 @@
<div class="flex justify-between">
{text}
{#if shortcutLabel}
<span class="text-gray-500 ps-4">
<span class="ps-4 text-gray-500">
{shortcutLabel}
</span>
{/if}
@@ -91,7 +91,7 @@
},
]}
>
<section class="fixed start-0 top-0 flex h-dvh w-dvw" {oncontextmenu} role="presentation">
<section class="fixed inset-s-0 top-0 flex h-dvh w-dvw" {oncontextmenu} role="presentation">
<ContextMenu
{direction}
{x}
@@ -387,7 +387,7 @@
/>
{#if showAssetName && !isTimelineAsset(asset)}
<div
class="absolute text-center p-1 text-xs font-mono font-semibold w-full bottom-0 bg-linear-to-t bg-slate-50/75 dark:bg-slate-800/75 overflow-clip text-ellipsis whitespace-pre-wrap"
class="absolute bottom-0 w-full overflow-clip bg-slate-50/75 bg-linear-to-t p-1 text-center font-mono text-xs font-semibold text-ellipsis whitespace-pre-wrap dark:bg-slate-800/75"
>
{asset.originalFileName}
</div>
@@ -390,7 +390,7 @@
>
{#snippet children({ feature })}
<div
class="rounded-full w-10 h-10 bg-immich-primary text-white flex justify-center items-center font-mono font-bold shadow-lg hover:bg-immich-dark-primary transition-all duration-200 hover:text-immich-dark-bg opacity-90"
class="flex size-10 items-center justify-center rounded-full bg-immich-primary font-mono font-bold text-white opacity-90 shadow-lg transition-all duration-200 hover:bg-immich-dark-primary hover:text-immich-dark-bg"
>
{feature.properties?.point_count?.toLocaleString()}
</div>
@@ -407,11 +407,11 @@
>
{#snippet children({ feature }: { feature: Feature })}
{#if useLocationPin}
<Icon icon={mdiMapMarker} size="50px" class="text-primary -translate-y-[50%]" />
<Icon icon={mdiMapMarker} size="50px" class="translate-y-[-50%] text-primary" />
{:else}
<img
src={getAssetMediaUrl({ id: feature.properties?.id })}
class="rounded-full w-15 h-15 border-2 border-immich-primary shadow-lg hover:border-immich-dark-primary transition-all duration-200 hover:scale-150 object-cover bg-immich-primary"
class="size-15 rounded-full border-2 border-immich-primary bg-immich-primary object-cover shadow-lg transition-all duration-200 hover:scale-150 hover:border-immich-dark-primary"
alt={feature.properties?.city && feature.properties.country
? $t('map_marker_for_images', {
values: { city: feature.properties.city, country: feature.properties.country },
@@ -31,7 +31,7 @@
in:fade={{ duration: 100 }}
out:fade={{ duration: 100 }}
id="account-info-panel"
class="absolute z-1 end-6 top-19 w-[min(360px,100vw-50px)] rounded-3xl bg-gray-200 shadow-lg dark:border dark:border-immich-dark-gray dark:bg-immich-dark-gray"
class="absolute inset-e-6 top-19 z-1 w-[min(360px,100vw-50px)] rounded-3xl bg-gray-200 shadow-lg dark:border dark:border-immich-dark-gray dark:bg-immich-dark-gray"
use:focusTrap
>
<div
@@ -39,7 +39,7 @@
>
<div class="relative">
<UserAvatar user={authManager.user} size="xl" />
<div class="absolute bottom-0 end-0 rounded-full w-6 h-6">
<div class="absolute inset-e-0 bottom-0 size-6 rounded-full">
<IconButton
color="primary"
icon={mdiPencil}
@@ -68,9 +68,9 @@
color="secondary"
variant="ghost"
shape="round"
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"
class="border hover:bg-immich-primary/10 dark:border-immich-dark-gray dark:bg-gray-500 dark:text-white dark:hover:bg-immich-dark-primary/50"
>
<div class="flex place-content-center place-items-center text-center gap-2 px-2">
<div class="flex place-content-center place-items-center gap-2 px-2 text-center">
<Icon icon={mdiCog} size="18" aria-hidden />
{$t('account_settings')}
</div>
@@ -84,9 +84,9 @@
size="small"
color="secondary"
aria-current={page.url.pathname.includes('/admin') ? 'page' : undefined}
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"
class="border hover:bg-immich-primary/10 dark:border-immich-dark-gray dark:bg-gray-500 dark:text-white dark:hover:bg-immich-dark-primary/50"
>
<div class="flex place-content-center place-items-center text-center gap-2 px-2">
<div class="flex place-content-center place-items-center gap-2 px-2 text-center">
<Icon icon={mdiWrench} size="18" aria-hidden />
{$t('administration')}
</div>
@@ -106,7 +106,7 @@
<button
type="button"
class="text-center mt-4 underline text-xs text-primary"
class="mt-4 text-center text-xs text-primary underline"
onclick={async () => {
onClose?.();
if (info) {
@@ -49,14 +49,14 @@
<svelte:window bind:innerWidth />
<nav id="dashboard-navbar" class="max-md:h-(--navbar-height-md) h-(--navbar-height) w-dvw text-sm">
<nav id="dashboard-navbar" class="h-(--navbar-height) w-dvw text-sm max-md:h-(--navbar-height-md)">
<SkipLink text={$t('skip_to_content')} />
<div
class="grid h-full grid-cols-[--spacing(32)_auto] items-center py-2 sidebar:grid-cols-[--spacing(64)_auto] {noBorder
? ''
: 'border-b'}"
>
<div class="flex flex-row gap-1 mx-4 items-center">
<div class="mx-4 flex flex-row items-center gap-1">
<IconButton
id={menuButtonId}
shape="round"
@@ -80,14 +80,14 @@
<Logo variant={mediaQueryManager.isFullSidebar ? 'inline' : 'icon'} class="max-md:h-12" />
</a>
</div>
<div class="flex justify-between gap-4 lg:gap-8 pe-6">
<div class="hidden w-full max-w-5xl flex-1 tall:ps-0 sm:block">
<div class="flex justify-between gap-4 pe-6 lg:gap-8">
<div class="hidden w-full max-w-5xl flex-1 sm:block tall:ps-0">
{#if featureFlagsManager.value.search}
<SearchBar grayTheme={true} />
{/if}
</div>
<section class="flex place-items-center justify-end gap-1 md:gap-2 w-full sm:w-auto">
<section class="flex w-full place-items-center justify-end gap-1 sm:w-auto md:gap-2">
{#if featureFlagsManager.value.search}
<IconButton
color="secondary"
@@ -146,7 +146,7 @@
{#if hasUnreadNotifications}
<div
class="pointer-events-none absolute border top-0 right-1 flex h-5 w-5 items-center justify-center rounded-full bg-primary text-[10px] font-bold text-light"
class="pointer-events-none absolute top-0 right-1 flex size-5 items-center justify-center rounded-full border bg-primary text-[10px] font-bold text-light"
>
{notificationManager.notifications.length}
</div>
@@ -100,13 +100,13 @@
</script>
<button
class="min-h-20 p-2 py-3 hover:bg-immich-primary/10 dark:hover:bg-immich-dark-primary/10 border-b border-gray-200 dark:border-immich-dark-gray w-full"
class="min-h-20 w-full border-b border-gray-200 p-2 py-3 hover:bg-immich-primary/10 dark:border-immich-dark-gray dark:hover:bg-immich-dark-primary/10"
type="button"
onclick={() => onclick(notification)}
title={notification.createdAt}
>
<div class="grid grid-cols-[56px_1fr_32px] items-center gap-2">
<div class="flex place-items-center place-content-center">
<div class="flex place-content-center place-items-center">
<IconButton
icon={getIconType(notification.type)}
color={getAlertColor(notification.level)}
@@ -118,7 +118,7 @@
</div>
<Stack class="text-left" gap={1}>
<Text size="tiny" class="text-black dark:text-white text-base" fontWeight="semi-bold">{notification.title}</Text>
<Text size="tiny" class="text-base text-black dark:text-white" fontWeight="semi-bold">{notification.title}</Text>
{#if notification.description}
<Text class="overflow-hidden text-gray-600 dark:text-gray-300">{notification.description}</Text>
{/if}
@@ -127,7 +127,7 @@
</Stack>
{#if !notification.readAt}
<div class="w-2 h-2 rounded-full bg-primary text-right justify-self-center"></div>
<div class="size-2 justify-self-center rounded-full bg-primary text-right"></div>
{/if}
</div>
</button>
@@ -66,11 +66,11 @@
in:fade={{ duration: 100 }}
out:fade={{ duration: 100 }}
id="notification-panel"
class="absolute right-6 top-17.5 z-1 w-[min(360px,100vw-50px)] rounded-3xl bg-gray-100 border border-gray-200 shadow-lg dark:border dark:border-light dark:bg-immich-dark-gray text-light"
class="absolute top-17.5 right-6 z-1 w-[min(360px,100vw-50px)] rounded-3xl border border-gray-200 bg-gray-100 text-light shadow-lg dark:border dark:border-light dark:bg-immich-dark-gray"
use:focusTrap
>
<Stack class="max-h-125">
<div class="flex justify-between items-center mt-4 mx-4">
<div class="mx-4 mt-4 flex items-center justify-between">
<Text size="medium" color="secondary" fontWeight="semi-bold">{$t('notifications')}</Text>
<div>
<Button
@@ -88,7 +88,7 @@
{#if noUnreadNotifications}
<Stack
class="py-12 flex flex-col place-items-center place-content-center text-gray-700 dark:text-gray-300"
class="flex flex-col place-content-center place-items-center py-12 text-gray-700 dark:text-gray-300"
gap={1}
>
<Icon icon={mdiBellOutline} size="20"></Icon>
@@ -91,5 +91,5 @@
</script>
{#if !hidden}
<span class="absolute start-0 h-[3px] bg-immich-primary shadow-2xl" style:width={`${$progress * 100}%`}></span>
<span class="absolute inset-s-0 h-[3px] bg-immich-primary shadow-2xl" style:width={`${$progress * 100}%`}></span>
{/if}
@@ -8,11 +8,11 @@
<!-- Individual Purchase Option -->
<div
class="border border-gray-300 dark:border-gray-800 w-[min(375px,100%)] p-8 rounded-3xl bg-gray-100 dark:bg-gray-900"
class="w-[min(375px,100%)] rounded-3xl border border-gray-300 bg-gray-100 p-8 dark:border-gray-800 dark:bg-gray-900"
>
<div class="text-primary">
<Icon icon={mdiAccount} size="56" />
<p class="font-semibold text-lg mt-1">{$t('purchase_individual_title')}</p>
<p class="mt-1 text-lg font-semibold">{$t('purchase_individual_title')}</p>
</div>
<div class="mt-4 dark:text-immich-gray">
@@ -20,20 +20,20 @@
<p>{$t('purchase_per_user')}</p>
</div>
<div class="flex flex-col justify-between h-50 dark:text-immich-gray">
<div class="flex h-50 flex-col justify-between dark:text-immich-gray">
<div class="mt-6 flex flex-col gap-1">
<div class="grid grid-cols-[36px_auto]">
<Icon icon={mdiCheckCircleOutline} size="24" class="text-green-500 self-center" />
<Icon icon={mdiCheckCircleOutline} size="24" class="self-center text-green-500" />
<p class="self-center">{$t('purchase_individual_description_1')}</p>
</div>
<div class="grid grid-cols-[36px_auto]">
<Icon icon={mdiCheckCircleOutline} size="24" class="text-green-500 self-center" />
<Icon icon={mdiCheckCircleOutline} size="24" class="self-center text-green-500" />
<p class="self-center">{$t('purchase_lifetime_description')}</p>
</div>
<div class="grid grid-cols-[36px_auto]">
<Icon icon={mdiCheckCircleOutline} size="24" class="text-green-500 self-center" />
<Icon icon={mdiCheckCircleOutline} size="24" class="self-center text-green-500" />
<p class="self-center">{$t('purchase_individual_description_2')}</p>
</div>
</div>
@@ -13,12 +13,12 @@
let { onDone }: Props = $props();
</script>
<div class="m-auto w-3/4 text-center flex flex-col place-content-center place-items-center my-6">
<div class="m-auto my-6 flex w-3/4 flex-col place-content-center place-items-center text-center">
<Icon icon={mdiPartyPopper} class="text-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>
<p class="mt-8 text-4xl font-bold">{$t('purchase_activated_title')}</p>
<p class="mt-6 text-lg">{$t('purchase_activated_subtitle')}</p>
<div class="mb-4 w-full mt-6 border rounded-xl p-4 bg-gray-50 dark:bg-gray-900 dark:border-gray-600">
<div class="mt-6 mb-4 w-full rounded-xl border bg-gray-50 p-4 dark:border-gray-600 dark:bg-gray-900">
<SettingSwitch
title={$t('show_supporter_badge')}
subtitle={$t('show_supporter_badge_description')}
@@ -55,7 +55,7 @@
</div>
{/if}
<div class="flex flex-col sm:flex-row gap-6 mt-4 justify-between">
<div class="mt-4 flex flex-col justify-between gap-6 sm:flex-row">
<ServerPurchaseOptionCard />
<UserPurchaseOptionCard />
</div>
@@ -8,11 +8,11 @@
<!-- SERVER Purchase Options -->
<div
class="border border-gray-300 dark:border-gray-800 w-[min(375px,100%)] p-8 rounded-3xl bg-gray-100 dark:bg-gray-900"
class="w-[min(375px,100%)] rounded-3xl border border-gray-300 bg-gray-100 p-8 dark:border-gray-800 dark:bg-gray-900"
>
<div class="text-primary">
<Icon icon={mdiServer} size="56" />
<p class="font-semibold text-lg mt-1">{$t('purchase_server_title')}</p>
<p class="mt-1 text-lg font-semibold">{$t('purchase_server_title')}</p>
</div>
<div class="mt-4 dark:text-immich-gray">
@@ -20,20 +20,20 @@
<p>{$t('purchase_per_server')}</p>
</div>
<div class="flex flex-col justify-between h-50 dark:text-immich-gray">
<div class="flex h-50 flex-col justify-between dark:text-immich-gray">
<div class="mt-6 flex flex-col gap-1">
<div class="grid grid-cols-[36px_auto]">
<Icon icon={mdiCheckCircleOutline} size="24" class="text-green-500 self-center" />
<Icon icon={mdiCheckCircleOutline} size="24" class="self-center text-green-500" />
<p class="self-center">{$t('purchase_server_description_1')}</p>
</div>
<div class="grid grid-cols-[36px_auto]">
<Icon icon={mdiCheckCircleOutline} size="24" class="text-green-500 self-center" />
<Icon icon={mdiCheckCircleOutline} size="24" class="self-center text-green-500" />
<p class="self-center">{$t('purchase_lifetime_description')}</p>
</div>
<div class="grid grid-cols-[36px_auto]">
<Icon icon={mdiCheckCircleOutline} size="24" class="text-green-500 self-center" />
<Icon icon={mdiCheckCircleOutline} size="24" class="self-center text-green-500" />
<p class="self-center">{$t('purchase_server_description_2')}</p>
</div>
</div>
@@ -248,11 +248,11 @@
]}
/>
<div class="w-full relative z-auto" use:focusOutside={{ onFocusOut }} tabindex="-1">
<div class="relative z-auto w-full" use:focusOutside={{ onFocusOut }} tabindex="-1">
<form
draggable="false"
autocomplete="off"
class="select-text text-sm"
class="text-sm select-text"
action={Route.search()}
onreset={() => (value = '')}
{onsubmit}
@@ -265,11 +265,11 @@
type="text"
name="q"
id="main-search-bar"
class="w-full transition-all border-2 ps-14 py-4 max-md:py-2 text-immich-fg/75 dark:text-immich-dark-fg
class="w-full border-2 py-4 ps-14 text-immich-fg/75 transition-all max-md:py-2 dark:text-immich-dark-fg
{showClearIcon ? 'pe-22.5' : 'pe-14'}
{grayTheme ? 'dark:bg-immich-dark-gray' : 'dark:bg-immich-dark-bg'}
{showSuggestions && isSearchSuggestions ? 'rounded-t-3xl' : 'rounded-3xl bg-gray-200'}
{searchStore.isSearchEnabled ? 'border-gray-200 dark:border-gray-700 bg-white' : 'border-transparent'}"
{searchStore.isSearchEnabled ? 'border-gray-200 bg-white dark:border-gray-700' : 'border-transparent'}"
placeholder={$t('search_your_photos')}
required
pattern="^(?!m:$).*$"
@@ -309,9 +309,9 @@
<div
id={searchTypeId}
class="absolute inset-y-0 flex items-center end-16"
class="absolute inset-y-0 inset-e-16 flex items-center"
class:max-md:hidden={value}
class:end-28={value.length > 0}
class:inset-e-28={value.length > 0}
>
<div class="relative" use:focusOutside={{ onFocusOut: closeSearchTypeDropdown }}>
<Button
@@ -320,7 +320,7 @@
color={searchStore.isSearchEnabled ? 'primary' : 'secondary'}
class="px-3 py-1 text-xs {searchStore.isSearchEnabled
? 'border border-transparent'
: 'border border-secondary/5 text-muted hover:text-dark font-light'}"
: 'border-secondary/5 border font-light text-muted hover:text-dark'}"
onclick={toggleSearchTypeDropdown}
aria-expanded={showSearchTypeDropdown}
aria-haspopup="listbox"
@@ -330,13 +330,13 @@
{#if showSearchTypeDropdown}
<div
class="absolute top-full right-0 mt-1 bg-white dark:bg-immich-dark-gray border border-gray-200 dark:border-gray-600 rounded-lg shadow-lg py-1 min-w-32 z-9999"
class="absolute top-full right-0 z-9999 mt-1 min-w-32 rounded-lg border border-gray-200 bg-white py-1 shadow-lg dark:border-gray-600 dark:bg-immich-dark-gray"
>
{#each searchTypes as searchType (searchType.value)}
<button
type="button"
tabindex="0"
class="w-full text-left px-3 py-2 text-xs hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors
class="w-full px-3 py-2 text-left text-xs transition-colors hover:bg-gray-100 dark:hover:bg-gray-700
{currentSearchType === searchType.value ? 'bg-gray-100 dark:bg-gray-700' : ''}"
onclick={() => selectSearchType(searchType.value)}
>
@@ -349,7 +349,7 @@
</div>
{#if showClearIcon}
<div class="absolute inset-y-0 end-0 flex items-center pe-2">
<div class="absolute inset-y-0 inset-e-0 flex items-center pe-2">
<IconButton
onclick={onClear}
icon={mdiClose}
@@ -361,7 +361,7 @@
/>
</div>
{/if}
<div class="absolute inset-y-0 start-0 flex items-center ps-2">
<div class="absolute inset-y-0 inset-s-0 flex items-center ps-2">
<IconButton
type="submit"
aria-label={$t('search')}
@@ -375,7 +375,7 @@
</div>
</form>
<div class="absolute inset-y-0 {showClearIcon ? 'end-14' : 'end-2'} flex items-center ps-6 transition-all">
<div class="absolute inset-y-0 {showClearIcon ? 'inset-e-14' : 'inset-e-2'} flex items-center ps-6 transition-all">
<IconButton
aria-label={$t('show_search_options')}
shape="round"
@@ -76,7 +76,7 @@
<div id="camera-selection">
<Text fontWeight="medium">{$t('camera')}</Text>
<div class="grid grid-auto-fit-40 gap-5 mt-1">
<div class="mt-1 grid grid-auto-fit-40 gap-5">
<div class="w-full">
<Combobox
label={$t('make')}
@@ -14,7 +14,7 @@
<fieldset>
<Text class="mb-2" fontWeight="medium">{$t('display_options')}</Text>
<div class="flex flex-wrap gap-x-5 gap-y-2 mt-1">
<div class="mt-1 flex flex-wrap gap-x-5 gap-y-2">
<div class="flex items-center gap-2">
<Checkbox id="not-in-album-checkbox" size="tiny" bind:checked={filters.isNotInAlbum} />
<Label label={$t('not_in_any_album')} for="not-in-album-checkbox" class="text-sm font-normal" />
@@ -94,7 +94,7 @@
{#if isOpen && isSearchSuggestions}
<div
transition:fly={{ y: 25, duration: 150 }}
class="absolute w-full rounded-b-3xl border-2 border-t-0 border-gray-200 bg-white pb-5 shadow-2xl transition-all dark:border-gray-700 dark:bg-immich-dark-gray dark:text-gray-300 z-1"
class="absolute z-1 w-full rounded-b-3xl border-2 border-t-0 border-gray-200 bg-white pb-5 shadow-2xl transition-all dark:border-gray-700 dark:bg-immich-dark-gray dark:text-gray-300"
>
<div class="flex items-center justify-between px-5 pt-5 text-xs">
<Text class="py-2" color="muted" aria-hidden={true}>{$t('recent_searches')}</Text>
@@ -102,7 +102,7 @@
<button
id={getId(0)}
type="button"
class="rounded-lg p-2 font-semibold text-primary aria-selected:bg-immich-primary/25 hover:bg-immich-primary/25"
class="rounded-lg p-2 font-semibold text-primary hover:bg-immich-primary/25 aria-selected:bg-immich-primary/25"
role="option"
onclick={() => handleClearAll()}
tabindex="-1"
@@ -121,7 +121,7 @@
<!-- svelte-ignore a11y_click_events_have_key_events -->
<div
id={getId(index)}
class="relative flex w-full cursor-pointer gap-3 py-3 ps-5 hover:bg-gray-100 aria-selected:bg-gray-100 dark:aria-selected:bg-gray-500/30 dark:hover:bg-gray-500/30"
class="relative flex w-full cursor-pointer gap-3 py-3 ps-5 hover:bg-gray-100 aria-selected:bg-gray-100 dark:hover:bg-gray-500/30 dark:aria-selected:bg-gray-500/30"
onclick={() => handleSelect(savedSearchTerm)}
role="option"
tabindex="-1"
@@ -131,7 +131,7 @@
<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">
<div aria-hidden={true} class="absolute inset-e-5 top-0 items-center justify-center py-3">
<IconButton
shape="round"
color="secondary"
@@ -70,7 +70,7 @@
<div id="location-selection">
<Text fontWeight="medium">{$t('place')}</Text>
<div class="grid grid-auto-fit-40 gap-5 mt-1">
<div class="mt-1 grid grid-auto-fit-40 gap-5">
<div class="w-full">
<Combobox
label={$t('country')}
@@ -15,7 +15,7 @@
<fieldset>
<Text class="mb-2" fontWeight="medium">{$t('media_type')}</Text>
<div class="flex flex-wrap gap-x-5 gap-y-2 mt-1">
<div class="mt-1 flex flex-wrap gap-x-5 gap-y-2">
<RadioButton name="media-type" id="type-all" bind:group={filteredMedia} label={$t('all')} value={MediaType.All} />
<RadioButton
name="media-type"
@@ -52,10 +52,10 @@
};
const styles = tv({
base: 'flex flex-col items-center rounded-3xl border-2 hover:bg-subtle dark:hover:bg-immich-dark-primary/20 p-2 transition-all',
base: 'flex flex-col items-center rounded-3xl border-2 p-2 transition-all hover:bg-subtle dark:hover:bg-immich-dark-primary/20',
variants: {
selected: {
true: 'dark:border-slate-500 border-slate-400 bg-slate-200 dark:bg-slate-800 dark:text-white',
true: 'border-slate-400 bg-slate-200 dark:border-slate-500 dark:bg-slate-800 dark:text-white',
false: 'border-transparent',
},
},
@@ -63,7 +63,7 @@
</script>
{#await peoplePromise}
<div id="spinner" class="flex h-54 items-center justify-center -mb-4">
<div id="spinner" class="-mb-4 flex h-54 items-center justify-center">
<LoadingSpinner size="large" />
</div>
{:then people}
@@ -72,14 +72,14 @@
? filterPeople(people, name)
: filterPeople(people, name).slice(0, numberOfPeople)}
<div id="people-selection" class="max-h-60 -mb-4 overflow-y-auto immich-scrollbar">
<div class="flex items-center w-full justify-between gap-6">
<div id="people-selection" class="-mb-4 max-h-60 overflow-y-auto immich-scrollbar">
<div class="flex w-full items-center justify-between gap-6">
<Text class="py-3" fontWeight="medium">{$t('people')}</Text>
<SearchBar bind:name placeholder={$t('filter_people')} showLoadingSpinner={false} />
</div>
<SingleGridRow
class="grid grid-auto-fill-20 gap-1 mt-2 overflow-y-auto immich-scrollbar space-between"
class="space-between mt-2 grid grid-auto-fill-20 gap-1 overflow-y-auto immich-scrollbar"
bind:itemCount={numberOfPeople}
>
{#each peopleList as person (person.id)}
@@ -95,13 +95,13 @@
</SingleGridRow>
{#if showAllPeople || people.length > peopleList.length}
<div class="flex justify-center mt-2">
<div class="mt-2 flex justify-center">
<Button
color="primary"
variant="ghost"
shape="round"
leadingIcon={showAllPeople ? mdiClose : mdiArrowRight}
class="flex gap-2 place-items-center"
class="flex place-items-center gap-2"
onclick={() => (showAllPeople = !showAllPeople)}
>
{showAllPeople ? $t('collapse') : $t('see_all_people')}
@@ -69,7 +69,7 @@
</div>
</form>
<section class="flex flex-wrap pt-2 gap-1">
<section class="flex flex-wrap gap-1 pt-2">
{#each selectedTags ?? [] as tagId (tagId)}
{@const tag = tagMap[tagId]}
{#if tag}
@@ -15,7 +15,7 @@
<section>
<fieldset>
<Text class="mb-2" fontWeight="medium">{$t('search_type')}</Text>
<div class="flex flex-wrap gap-x-5 gap-y-2 my-2">
<div class="my-2 flex flex-wrap gap-x-5 gap-y-2">
{#if featureFlagsManager.value.smartSearch}
<RadioButton name="query-type" id="context-radio" label={$t('context')} bind:group={queryType} value="smart" />
{/if}
@@ -64,7 +64,7 @@
</script>
<div
class="border-2 rounded-2xl border-primary/20 mt-4 px-6 py-4 transition-all {isOpen
class="mt-4 rounded-2xl border-2 border-primary/20 px-6 py-4 transition-all {isOpen
? 'border-primary/60 shadow-md'
: ''}"
bind:this={accordionElement}
@@ -76,7 +76,7 @@
class="flex w-full place-items-center justify-between text-start"
>
<div>
<div class="flex gap-2 place-items-center">
<div class="flex place-items-center gap-2">
{#if icon}
<Icon {icon} class="text-primary" size="24" aria-hidden />
{/if}
@@ -86,7 +86,7 @@
</div>
{#if subtitleSnippet}{@render subtitleSnippet()}{:else}
<p class="text-sm dark:text-immich-dark-fg mt-1">{subtitle}</p>
<p class="mt-1 text-sm dark:text-immich-dark-fg">{subtitle}</p>
{/if}
</div>
@@ -110,7 +110,7 @@
</button>
{#if isOpen}
<ul transition:slide={{ duration: 150 }} class="mb-2 ms-4">
<ul transition:slide={{ duration: 150 }} class="ms-4 mb-2">
{@render children?.()}
</ul>
{/if}
@@ -29,7 +29,7 @@
<div class="flex place-items-center justify-between">
<div>
<div class="flex h-6.5 place-items-center gap-1">
<label class="font-medium text-sm" for={title}>
<label class="text-sm font-medium" for={title}>
{title}
</label>
{#if isEdited}
@@ -81,7 +81,7 @@
<div class="mb-4 w-full">
<div class="flex place-items-center gap-1">
<label class="font-medium text-primary text-sm min-h-6" for={label}>{label}</label>
<label class="min-h-6 text-sm font-medium text-primary" for={label}>{label}</label>
{#if required}
<div class="text-red-400">*</div>
{/if}
@@ -97,7 +97,7 @@
</div>
{#if description}
<p class="immich-form-label pb-2 text-sm" id="{label}-desc">
<p class="pb-2 text-sm immich-form-label" id="{label}-desc">
{description}
</p>
{:else}
@@ -105,11 +105,11 @@
{/if}
{#if inputType !== SettingInputFieldType.PASSWORD}
<div class="flex place-items-center place-content-center gap-2">
<div class="flex place-content-center place-items-center gap-2">
{#if inputType === SettingInputFieldType.COLOR}
<input
bind:this={input}
class="immich-form-input w-full pb-2 rounded-none me-1"
class="me-1 immich-form-input w-full rounded-none pb-2"
aria-describedby={description ? `${label}-desc` : undefined}
aria-labelledby="{label}-label"
id={label}
@@ -128,7 +128,7 @@
<input
bind:this={input}
class="immich-form-input w-full pb-2 min-w-[50px]"
class="immich-form-input w-full min-w-[50px] pb-2"
class:color-picker={inputType === SettingInputFieldType.COLOR}
aria-describedby={description ? `${label}-desc` : undefined}
aria-labelledby="{label}-label"
@@ -35,7 +35,7 @@
<div class="flex place-items-center justify-between">
<div class="me-2">
<div class="flex h-6.5 place-items-center gap-1">
<label class="font-medium text-primary text-sm" for={switchId}>
<label class="text-sm font-medium text-primary" for={switchId}>
{title}
</label>
{#if isEdited}
@@ -10,6 +10,6 @@
<PurchaseInfo />
<div class="mb-6 mt-2">
<div class="mt-2 mb-6">
<ServerStatus />
</div>
@@ -73,7 +73,7 @@
{#if authManager.isPurchased && authManager.preferences.purchase.showSupportBadge}
<button
onclick={() => goto(Route.userSettings({ isOpen: OpenQueryParam.PURCHASE_SETTINGS }))}
class="w-full mt-2"
class="mt-2 w-full"
type="button"
>
<SupporterBadge size="small" effect="always" />
@@ -86,18 +86,18 @@
onmouseleave={() => (hoverButton = false)}
onfocus={onButtonHover}
onblur={() => (hoverButton = false)}
class="p-2 flex justify-between place-items-center place-content-center border border-immich-primary/20 dark:border-immich-dark-primary/10 mt-2 rounded-lg shadow-md dark:bg-immich-dark-primary/10 min-w-52 w-full"
class="mt-2 flex w-full min-w-52 place-content-center place-items-center justify-between rounded-lg border border-immich-primary/20 p-2 shadow-md dark:border-immich-dark-primary/10 dark:bg-immich-dark-primary/10"
>
<div class="flex justify-between w-full place-items-center place-content-center">
<div class="flex place-items-center place-content-center gap-1">
<div class="flex w-full place-content-center place-items-center justify-between">
<div class="flex place-content-center place-items-center gap-1">
<Logo variant="icon" size="tiny" />
<p class="flex text-primary font-medium">
<p class="flex font-medium text-primary">
{$t('purchase_button_buy_immich')}
</p>
</div>
<div>
<Icon icon={mdiInformationOutline} class="hidden sidebar:flex text-primary font-medium" size="18" />
<Icon icon={mdiInformationOutline} class="hidden font-medium text-primary sidebar:flex" size="18" />
</div>
</div>
</button>
@@ -108,15 +108,15 @@
{#if showMessage}
<dialog
open
class="hidden sidebar:block w-125 absolute bottom-19 start-64 bg-gray-50 dark:border-gray-800 border border-gray-200 dark:bg-immich-dark-gray dark:text-white text-black rounded-3xl shadow-2xl px-8 py-6"
class="absolute inset-s-64 bottom-19 hidden w-125 rounded-3xl border border-gray-200 bg-gray-50 px-8 py-6 text-black shadow-2xl sidebar:block dark:border-gray-800 dark:bg-immich-dark-gray dark:text-white"
transition:fade={{ duration: 150 }}
onmouseover={() => (hoverMessage = true)}
onmouseleave={() => (hoverMessage = false)}
onfocus={() => (hoverMessage = true)}
onblur={() => (hoverMessage = false)}
>
<div class="flex justify-between place-items-center">
<div class="h-10 w-10">
<div class="flex place-items-center justify-between">
<div class="size-10">
<Logo variant="icon" size="small" />
</div>
<IconButton
@@ -133,11 +133,11 @@
/>
</div>
<h1 class="text-lg font-medium my-3 text-primary">
<h1 class="my-3 text-lg font-medium text-primary">
{$t('purchase_panel_title')}
</h1>
<div class="text-gray-800 dark:text-white my-4">
<div class="my-4 text-gray-800 dark:text-white">
<p>
{$t('purchase_panel_info_1')}
</p>
@@ -29,17 +29,17 @@
<a
href={Route.viewAlbum(album)}
title={album.albumName}
class="flex w-full place-items-center justify-between gap-4 rounded-e-full py-3 transition-[padding] delay-100 duration-100 hover:cursor-pointer hover:bg-subtle hover:text-immich-primary dark:text-immich-dark-fg dark:hover:bg-immich-dark-gray dark:hover:text-immich-dark-primary ps-10 group-hover:sm:px-10 md:px-10"
class="flex w-full place-items-center justify-between gap-4 rounded-e-full py-3 ps-10 transition-[padding] delay-100 duration-100 hover:cursor-pointer hover:bg-subtle hover:text-immich-primary group-hover:sm:px-10 md:px-10 dark:text-immich-dark-fg dark:hover:bg-immich-dark-gray dark:hover:text-immich-dark-primary"
>
<div>
<div
class="h-6 w-6 bg-cover rounded bg-gray-200 dark:bg-gray-600"
class="size-6 rounded-sm bg-gray-200 bg-cover dark:bg-gray-600"
style={album.albumThumbnailAssetId
? `background-image:url('${getAssetMediaUrl({ id: album.albumThumbnailAssetId })}')`
: ''}
></div>
</div>
<div class="grow text-sm font-medium truncate">
<div class="grow truncate text-sm font-medium">
{album.albumName}
</div>
</a>
@@ -58,16 +58,16 @@
</script>
<div
class="text-sm flex md:flex ps-5 pe-1 place-items-center place-content-center justify-between min-w-52 overflow-hidden dark:text-immich-dark-fg"
class="flex min-w-52 place-content-center place-items-center justify-between overflow-hidden ps-5 pe-1 text-sm md:flex dark:text-immich-dark-fg"
>
{#if $connected}
<div class="flex gap-2 place-items-center place-content-center">
<div class="w-1.75 h-1.75 bg-green-500 rounded-full"></div>
<div class="flex place-content-center place-items-center gap-2">
<div class="size-1.75 rounded-full bg-green-500"></div>
<p class="dark:text-immich-gray">{$t('server_online')}</p>
</div>
{:else}
<div class="flex gap-2 place-items-center place-content-center">
<div class="w-1.75 h-1.75 bg-red-500 rounded-full"></div>
<div class="flex place-content-center place-items-center gap-2">
<div class="size-1.75 rounded-full bg-red-500"></div>
<p class="text-red-500">{$t('server_offline')}</p>
</div>
{/if}
@@ -77,7 +77,7 @@
<button
type="button"
onclick={() => info && modalManager.show(ServerAboutModal, { versions, info })}
class="dark:text-immich-gray flex gap-1 place-items-center place-content-center"
class="flex place-content-center place-items-center gap-1 dark:text-immich-gray"
>
{#if isMain}
<Icon icon={mdiAlert} size="1.5em" color="#ffcc4d" /> {info?.sourceRef}
@@ -96,17 +96,17 @@
href={releaseInfo.releaseUrl}
target="_blank"
rel="noopener noreferrer"
class="mt-3 p-2.5 ms-4 rounded-lg text-sm min-w-52 border border-gray-200/50 dark:border-gray-700/50 bg-white/50 dark:bg-gray-800/50 hover:border-immich-primary/40 dark:hover:border-immich-dark-primary/40 hover:bg-immich-primary/5 dark:hover:bg-immich-dark-primary/5 transition-all duration-200 group block"
class="group ms-4 mt-3 block min-w-52 rounded-lg border border-gray-200/50 bg-white/50 p-2.5 text-sm transition-all duration-200 hover:border-immich-primary/40 hover:bg-immich-primary/5 dark:border-gray-700/50 dark:bg-gray-800/50 dark:hover:border-immich-dark-primary/40 dark:hover:bg-immich-dark-primary/5"
>
<div class="flex items-center justify-between gap-2">
<div class="flex items-center gap-2">
<Icon icon={mdiNewBox} size="16" class="text-immich-primary dark:text-immich-dark-primary opacity-80" />
<Icon icon={mdiNewBox} size="16" class="text-immich-primary opacity-80 dark:text-immich-dark-primary" />
<Text size="tiny" fontWeight="medium" class="text-gray-700 dark:text-gray-300">
{releaseInfo.availableVersion}
</Text>
</div>
<span
class="text-[11px] text-gray-500 dark:text-gray-400 group-hover:text-immich-primary dark:group-hover:text-immich-dark-primary transition-colors opacity-70 group-hover:opacity-100"
class="text-[11px] text-gray-500 opacity-70 transition-colors group-hover:text-immich-primary group-hover:opacity-100 dark:text-gray-400 dark:group-hover:text-immich-dark-primary"
>
{$t('new_update')}!
</span>
@@ -34,7 +34,7 @@
</script>
<div
class="p-4 bg-light-100 ms-4 rounded-lg text-sm min-w-52"
class="ms-4 min-w-52 rounded-lg bg-light-100 p-4 text-sm"
title={$t('storage_usage', {
values: {
used: getByteUnitString(usedBytes, $locale, 3),
@@ -58,7 +58,7 @@
{thresholds}
/>
{:else}
<p class="font-medium text-immich-dark-gray dark:text-white mb-4">{$t('storage')}</p>
<p class="mb-4 font-medium text-immich-dark-gray dark:text-white">{$t('storage')}</p>
<LoadingSpinner />
{/if}
</div>
@@ -35,9 +35,9 @@
{/if}
<div
class="bg-gray-50 dark:bg-immich-dark-gray/50 w-full p-2 rounded-2xl border border-gray-100 dark:border-gray-900 overflow-y-auto immich-scrollbar"
class="w-full overflow-y-auto rounded-2xl border border-gray-100 bg-gray-50 p-2 immich-scrollbar dark:border-gray-900 dark:bg-immich-dark-gray/50"
>
<ol class="flex gap-2 items-center">
<ol class="flex items-center gap-2">
<li>
<IconButton
shape="round"
@@ -51,15 +51,15 @@
/>
</li>
{#each parents as parent (parent)}
<li class="flex gap-2 items-center font-mono text-sm text-nowrap text-primary">
<li class="flex items-center gap-2 font-mono text-sm text-nowrap text-primary">
<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)}>
<a class="whitespace-pre-wrap underline hover:font-semibold" href={getLink(parent.path)}>
{parent.value}
</a>
</li>
{/each}
<li class="flex gap-2 items-center font-mono text-sm text-nowrap text-primary">
<li class="flex items-center gap-2 font-mono text-sm text-nowrap text-primary">
<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>
@@ -26,7 +26,7 @@
<a
href={getLink(node.path)}
title={node.value}
class={`flex grow place-items-center ps-2 py-1 text-sm rounded-lg hover:bg-slate-200 dark:hover:bg-slate-800 hover:font-semibold ${isTarget ? 'bg-slate-100 dark:bg-slate-700 font-semibold text-primary' : 'dark:text-gray-200'}`}
class={`flex grow place-items-center rounded-lg py-1 ps-2 text-sm hover:bg-slate-200 hover:font-semibold dark:hover:bg-slate-800 ${isTarget ? 'bg-slate-100 font-semibold text-primary dark:bg-slate-700' : 'dark:text-gray-200'}`}
data-sveltekit-keepfocus
>
{#if node.size > 0}
@@ -34,7 +34,7 @@
<Icon icon={isOpen ? mdiChevronDown : mdiChevronRight} class="text-gray-400" size="20" />
</button>
{/if}
<div class={node.size === 0 ? 'ml-[1.5em] ' : ''}>
<div class={node.size === 0 ? 'ml-[1.5em]' : ''}>
<Icon
icon={isActive ? icons.active : icons.default}
class={isActive ? 'text-primary' : 'text-gray-400'}
@@ -42,7 +42,7 @@
size="20"
/>
</div>
<span class="text-nowrap overflow-hidden text-ellipsis font-mono ps-1 pt-1 whitespace-pre-wrap">{node.value}</span>
<span class="overflow-hidden ps-1 pt-1 font-mono text-nowrap text-ellipsis whitespace-pre-wrap">{node.value}</span>
</a>
{#if isOpen}
@@ -13,18 +13,18 @@
{#if items.length > 0}
<div
class="w-full grid grid-cols-2 sm:grid-cols-4 lg:grid-cols-6 2xl:grid-cols-8 gap-2 bg-gray-50 dark:bg-immich-dark-gray/50 rounded-2xl border border-gray-100 dark:border-gray-900"
class="grid w-full grid-cols-2 gap-2 rounded-2xl border border-gray-100 bg-gray-50 sm:grid-cols-4 lg:grid-cols-6 2xl:grid-cols-8 dark:border-gray-900 dark:bg-immich-dark-gray/50"
>
<!-- eslint-disable-next-line svelte/require-each-key -->
{#each items as item}
<button
class="flex flex-col place-items-center gap-2 py-2 px-4 hover:bg-immich-primary/10 dark:hover:bg-immich-primary/40 rounded-xl"
class="flex flex-col place-items-center gap-2 rounded-xl px-4 py-2 hover:bg-immich-primary/10 dark:hover:bg-immich-primary/40"
onclick={() => onClick(item.value)}
title={item.value}
type="button"
>
<Icon {icon} class="text-primary" size="64" />
<p class="text-sm dark:text-gray-200 text-nowrap text-ellipsis overflow-clip w-full whitespace-pre-wrap">
<p class="w-full overflow-clip text-sm text-nowrap text-ellipsis whitespace-pre-wrap dark:text-gray-200">
{item.value}
</p>
</button>
@@ -12,7 +12,7 @@
let { tree, active, icons, getLink }: Props = $props();
</script>
<ul class="list-none ms-2">
<ul class="ms-2 list-none">
{#each tree.children as node (node.color ? node.path + node.color : node.path)}
<li>
<Tree {node} {icons} {active} {getLink} />